Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1] 2
  Reply  |  Print  
Author Topic: Why I hate the Concatenate operator...  (Read 30019 times)
David H.
Posts: 158


« on: October 02, 2009, 10:02:07 am »

If you run the following program:-

Code
  1. MAIN
  2.  
  3.   DEFINE my_int INTEGER
  4.   DEFINE my_str STRING
  5.  
  6.   LET my_int = 100
  7.   LET my_str = NULL
  8.  
  9.   --With USING
  10.   DISPLAY "1=TESTA" || my_int USING "<<<<<<<&"
  11.   DISPLAY "2=TESTB", my_int USING "<<<<<<<&"
  12.  
  13.   --With NULL
  14.   DISPLAY "3=TESTA-" || my_str || "-"
  15.   DISPLAY "4=TESTB-", my_str , "-"
  16.  
  17. END MAIN

The output is:-

0
2=TESTB100

4=TESTB--

Ideally I'd like "||" to behave like ",", but I guess you'll say that is not going to be an option... Alternatively, could we have an alternative character for ",", so that I can write:-

Code
  1. FUNCTION my_func()
  2.  
  3.     DEFINE a,b,c STRING
  4.  
  5.     RETURN a+b+c
  6.  
  7. END FUNCTION

For me, "," was a bad choice of operator as RETURN a,b,c has two meanings!

Cheers,

David
Sebastien F.
Four Js
Posts: 545


« Reply #1 on: October 02, 2009, 10:23:10 am »

David,

Actually the || concatenation operator was introduced by Informix 4gl, and comes from Informix SQL:

> select '1' || '2' + 3 from systables where tabid=1;
(constant)         
15.0000000000000000
1 row(s) retrieved.

In 4gl it has the same behavior (order of precedence / effect of NULL):

main
    define x int
    let x = '1' || '2' + 3
    display x
end main

displays 15....

Seb
Reuben B.
Four Js
Posts: 1119


« Reply #2 on: October 02, 2009, 10:48:24 am »

I gave up trying to remember the semantics of || and , and used SFMT https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/Operators.html#OP_SFMT when that came out.  Was it 1.20?

Code
  1. FUNCTION my_func()
  2.  
  3.     DEFINE a,b,c STRING
  4.  
  5.  
  6.     RETURN SFMT("%1%2%3",a,b,c)
  7.  
  8. END FUNCTION
and

 
Code
  1. --With USING
  2.   DISPLAY "1=TESTA" || my_int USING "<<<<<<<&"
  3.   DISPLAY "2=TESTB", my_int USING "<<<<<<<&"
  4.   DISPLAY SFMT("?=TESTC%1", my_int USING "<<<<<<<&")
  5.  
  6.   --With NULL
  7.   DISPLAY "3=TESTA-" || my_str || "-"
  8.   DISPLAY "4=TESTB-", my_str , "-"
  9.   DISPLAY SFMT("?=TESTC-%1-", my_str)



I found the strings were much easier to read rather being a mess of quotes and commas i.e.

SFMT("SELECT %1 FROM %2 WHERE %3", select_clause, from_clause, where_clause)

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
David H.
Posts: 158


« Reply #3 on: October 02, 2009, 11:02:04 am »

Hi Seb,

Thats just about what I expected you'd say! Lets forget about || for a second (although the behaviour with USING is still weird for me..). What do you think about the feasibility of an alternate character for the comma operator, so it can be used in RETURN statements.

Whilst we are on the subject of SQL functionality making it into 4GL. I'd like to see NVL() and some kind of inline IF statement, i.e. IFF(expression,truevalue,falsevalue) added at some point too...

Cheers,

David
Sebastien F.
Four Js
Posts: 545


« Reply #4 on: October 02, 2009, 11:13:21 am »

The nice thing with the comma concat operator is that elements are formatted, compared to ||.

We have in mind to do something like CONCAT(a,b,c).

I will add a request for NVL(expr,default) and IF(expr,trueval,falseval).

Seb
David H.
Posts: 158


« Reply #5 on: October 02, 2009, 11:19:50 am »

Hi Reuben.

Yes like you we do use SFMT() a lot, and its been a great addition to the language. The only downsides being it can get confusing which argument is which when you have more than a few (i.e. which one is %8?).

Also if you want to spread the quoted text of multiple lines to improve readability then you still end up using || or "," . Which brings me to something else I noticed:-

Code
  1. MAIN
  2.  
  3.   DEFINE my_int INTEGER
  4.   DEFINE my_str STRING
  5.  
  6.   LET my_int = 100
  7.   LET my_str = NULL
  8.  
  9.  
  10.   DISPLAY SFMT("a=this is a test",
  11.                " of a multiline string: %1",my_int USING "<<<<<<<&")
  12.  
  13.   DISPLAY SFMT("b=this is a test",
  14.                " of a multiline string: [%1]",my_str)
  15.  
  16.   DISPLAY SFMT("c=this is a test" ||
  17.                " of a multiline string: %1",my_int USING "<<<<<<<&")
  18.  
  19.   DISPLAY SFMT("d=this is a test" ||
  20.                " of a multiline string: [%1]",my_str)
  21.  
  22.  
  23. END MAIN

gives:-

a=this is a test
b=this is a test
c=this is a test of a multiline string: 100
d=this is a test of a multiline string: []

:-)

David
Rene S.
Four Js
Posts: 112


« Reply #6 on: October 02, 2009, 11:38:58 am »

Hello,
about the NVL operator: I would like to suggest another option: the runtime could easily treat any NULL value in expressions as zero (if numeric) or empty (if String) . This could be controlled by an FGLPROFILE entry (system wide) or by a pseudo statement (like WHENEVER). This idea comes from a 4gl language being used in Germany. This language has the same problem with NULL values in expression. This language has solved this problem (as I remember well) with two configuration parameters: NULLEXPRESSIONS - treat a NULL value as zero or empty in expressions - and NULLVALUES - don't use NULL values at all in the program.

This still allows to assign NULL to any variable, On the other hand, any expression would behave more intuitive.
Rene
David H.
Posts: 158


« Reply #7 on: October 02, 2009, 12:04:57 pm »

Hi Rene,

That would be great for us, as we never want a NULL somewhere in an expression to make the entire expression NULL and have to continually code around this...

Cheers,

David
Sebastien F.
Four Js
Posts: 545


« Reply #8 on: October 02, 2009, 12:14:18 pm »

Maybe we need both a NVL() operator and what Rene suggested.

My instinct is that we'll have customers not willing to use the global configuration flag, to keep legacy code working as today.
I could bet that there are some lines of code relying on the current || expression evaluation resolving to NULL if one item in the expression is NULL, and then insert the result in the database...

Seb
David H.
Posts: 158


« Reply #9 on: October 02, 2009, 12:16:44 pm »

Hi Seb,

Yes, I'd agree that both options would probably be best to cover all the bases.

Regards,

David
Neil M.
Four Js
Posts: 21


« Reply #10 on: October 02, 2009, 02:32:09 pm »

If you run the following program:-

Code
  1. MAIN
  2.  
  3.   DEFINE my_int INTEGER
  4.   DEFINE my_str STRING
  5.  
  6.   LET my_int = 100
  7.   LET my_str = NULL
  8.  
  9.   --With USING
  10.   DISPLAY "1=TESTA" || my_int USING "<<<<<<<&"
  11.   DISPLAY "2=TESTB", my_int USING "<<<<<<<&"
  12.  
  13.   --With NULL
  14.   DISPLAY "3=TESTA-" || my_str || "-"
  15.   DISPLAY "4=TESTB-", my_str , "-"
  16.  
  17. END MAIN

Brackets help ( not sure why exactly ):
Code
  1.   DISPLAY "1=TESTA" || (my_int USING "<<<<<<<&")
  2.  
Result:
1=TESTA100

I like the idea of additional fglprofile parameters to control the 'NULL problems'

Regards,
Neil
David H.
Posts: 158


« Reply #11 on: October 02, 2009, 03:29:54 pm »


Brackets help ( not sure why exactly ):
Code
  1.   DISPLAY "1=TESTA" || (my_int USING "<<<<<<<&")
  2.  
Result:
1=TESTA100


Thats an interesting discovery! Presumably because they alter the evaluation order...
Sebastien F.
Four Js
Posts: 545


« Reply #12 on: October 02, 2009, 04:00:39 pm »

Sorry I should have mentioned this before in this thread:

The order of precedence of the || operator is higher as USING:

https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/Operators.html#PRECEDENCE_LIST

So when you write:

Code
  1.  LET x = a || b USING "<<<"

It is equivalent to:

Code
  1.  LET x = (a || b) USING "<<<"

Seb


Brackets help ( not sure why exactly ):
Code
  1.   DISPLAY "1=TESTA" || (my_int USING "<<<<<<<&")
  2.  
Result:
1=TESTA100


Thats an interesting discovery! Presumably because they alter the evaluation order...
Reuben B.
Four Js
Posts: 1119


« Reply #13 on: October 04, 2009, 10:59:25 pm »

The nice thing with the comma concat operator is that elements are formatted, compared to ||.

We have in mind to do something like CONCAT(a,b,c).

I will add a request for NVL(expr,default) and IF(expr,trueval,falseval).

Seb

I used to have a nvl() and if() in our libraries in my previous job.


The 1996 version of our nvl is available in the IIUG software repository

FUNCTION nvl(l_original, l_if_null)
DEFINE  l_original                     CHAR(80),
        l_if_null                      CHAR(80)

    IF LENGTH(l_original) = 0 THEN
        RETURN l_if_null
    ELSE
        IF l_original[1]="$" THEN   # Cope with money fields
           LET l_original[1]=" "
        END IF
        RETURN l_original
    END IF

END FUNCTION

... I am sure when we generoised we would've switched to STRINGs  (ScottN can share the 2009 version if he wishes).

The if would've been something like

FUNCTION if(a,b,c)
DEFINE a SMALLINT -- colud use BOOLEAN Genero 2.2 on
DEFINE b,c STRING
   IF a THEN
      RETURN b
   ELSE
      RETURN c
   END IF
END FUNCTION

and used in things like

LET increment = if(x.sort_order = "Asc",1, -1).

The downside is that both sides of the expression are evaluated.  So it is suitable for the above example where b,c are constants but not so suitable for

CALL if(x.mode = "insert", insert_record(), update_record())

The thing with these simple library functions like this is if that a number of existing customers have them then there is an argument then we should include them in the language so that any new developers do not need to recreate them from scratch and have that functionality from day one, the negative is that existing customers may already have those functions as different names, or similar functions with the same name. 





Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Reuben B.
Four Js
Posts: 1119


« Reply #14 on: October 04, 2009, 11:07:57 pm »

Hello,
about the NVL operator: I would like to suggest another option: the runtime could easily treat any NULL value in expressions as zero (if numeric) or empty (if String) . This could be controlled by an FGLPROFILE entry (system wide) or by a pseudo statement (like WHENEVER). This idea comes from a 4gl language being used in Germany. This language has the same problem with NULL values in expression. This language has solved this problem (as I remember well) with two configuration parameters: NULLEXPRESSIONS - treat a NULL value as zero or empty in expressions - and NULLVALUES - don't use NULL values at all in the program.

This still allows to assign NULL to any variable, On the other hand, any expression would behave more intuitive.
Rene

to play devils advocate again, what would DATE, DATETIME evaluate to?

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Pages: [1] 2
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines