If I am going to write and give examples of programming in CL I need to start by explaining some of the CL language shortcuts I use. Perhaps "shortcuts" are not the right word, maybe "shorthand". Oh well, I am sure you will work out what I mean as you read this.

I use these shortcuts extensively in my CL code as for a couple of reasons:

I think it is easier for someone else to understand the code I have written. It is just quicker to write, the faster I can write code the more I can get done.

I am going to start with my favorite three.

Comments overflowing onto multiple lines

The number of times I have seen this kind of thing in other's CL code:

/* Comments over more */ /* than one line */

Unlike some other programming languages if I put a plus ( + ) at the end of the comment line the next line(s) also become comments until an end of comment characters ( */ ) are found.

/* Comments + over + more + than + one + line */

If condition comparisons

I don't have to type *EQ in the condition parameter of an If or Select's When command, I can just use the mathematical symbols.

Before I start explaining how this is done I need to introduce a couple of characters: the "not" and the "or".

¬ | Not character

(top right corner) Or character

(vertical line or unbroken pipe)

In my experience neither of these are mapped on my TN5250 emulation software's keyboard default configuration. I had to map a key to each character so I could use them. I will explain how they are used below

For my first example I am going to show an If command with an equal test, the same syntax in used in a Select's When:

IF COND(&VAR1 *EQ 'A') THEN(... IF COND(&VAR1 = 'A') THEN(...

No surprises that a "not" symbol can be used in a not equal comparison:

IF COND(&VAR1 *NE 'B') THEN(... IF COND(&VAR1 ¬= 'B') THEN(...

Greater than comparison:

IF COND(&VAR1 *GT 'A') THEN(... IF COND(&VAR1 > 'A') THEN(...

Greater or equal to comparison:

IF COND(&VAR1 *GE 'B') THEN(... IF COND(&VAR1 >= 'B') THEN(...

Less than comparison:

IF COND(&VAR1 *LT 'B') THEN(... IF COND(&VAR1 < 'B') THEN(...

Less or equal to comparison:

IF COND(&VAR1 *LE 'A') THEN(... IF COND(&VAR1 <= 'A') THEN(...

Then there are two more obscure comparison, which I have to admit I did not know until researching for this post.

Not greater than (isn't this the same as less or equal to?):

IF COND(&VAR1 *NG 'A') THEN(... IF COND(&VAR1 ¬> 'A') THEN(...

Not less than (isn't this the same as greater or equal to?):

IF COND(&VAR1 *NL 'A') THEN(... IF COND(&VAR1 ¬< 'A') THEN(...

For logical variables, in other words indicators, I can, just as I do in RPG, compare if it is or is not:

IF COND(&FLAG) THEN(... IF COND(*NOT &FLAG) THEN(... IF COND(¬ &FLAG) THEN(...

The third example shows using the not character, rather than using the word *NOT .

If I want to add a "and" to my if statement I can do:

IF COND((&VAR1 = 'A') *AND (&VAR2 = 'B')) + THEN(... IF COND((&VAR1 = 'A') & (&VAR2 = 'B')) + THEN(...

Here I can show how the "or" character can replace the word *OR :

IF COND((&VAR1 = 'A') *OR (&VAR1 = 'B')) + THEN(... IF COND((&VAR1 = 'A') | (&VAR1 = 'B')) + THEN(...

Concatenating strings

I think these shortcuts are my favorites, and most used. There are three types of concatenation in CL:

Simple concatenation – simply putting two strings together Concatenation trimming the blanks off the first string Concatenation trimming the blanks, but adding one blank

This is where we find that the vertical line character ( | ) assumes a different role.

In this first example I am just going to concatenate the two variables together with a simple concatenation:

01 PGM 02 DCL VAR(&LASTNAME) TYPE(*CHAR) LEN(15) VALUE('SMITH') 03 DCL VAR(&FIRSTNAME) TYPE(*CHAR) LEN(15) VALUE('JOHN') 04 DCL VAR(&FULLNAME) TYPE(*CHAR) LEN(30) 05 CHGVAR VAR(&FULLNAME) VALUE(&FIRSTNAME *CAT &LASTNAME) 06 CHGVAR VAR(&FULLNAME) VALUE(&FIRSTNAME || &LASTNAME)

The double vertical line ( || ) used in line 6 replaces the *CAT shown on line 5. The result of these two lines is the same:

&FULLNAME = 'JOHN SMITH '

To remove the trailing blanks in the first name variable I would use the *TCAT in place of the *CAT , or |< in place of || .

07 CHGVAR VAR(&FULLNAME) VALUE(&FIRSTNAME *TCAT &LASTNAME) 08 CHGVAR VAR(&FULLNAME) VALUE(&FIRSTNAME |< &LASTNAME)

The result of this is:

&FULLNAME = 'JOHNSMITH '

Which is not pretty.

The third type of concatenation is one that RPG does not have, which in my opinion is a shame. This time I use the *BCAT or |> .

09 CHGVAR VAR(&FULLNAME) VALUE(&FIRSTNAME *BCAT &LASTNAME) 10 CHGVAR VAR(&FULLNAME) VALUE(&FIRSTNAME |> &LASTNAME)

The result is just what I desired.

&FULLNAME = 'JOHN SMITH '

If I am concatenating multiple strings together I think you will find that it is easier to understand what is happening using the shortcuts rather than the long handed version.

CHGVAR VAR(&EVERYTHING) VALUE(&FIRSTNAME *BCAT + &LASTNAME *TCAT ', ' *CAT &ADDRESS *TCAT + ', ' *CAT &CITY *TCAT ', ' *CAT &STATE + *CAT ' ' *CAT &POSTALCODE) CHGVAR VAR(&EVERYTHING) + VALUE(&FIRSTNAME |> + &LASTNAME |< ', ' || + &ADDRESS |< ', ' || + &CITY |< ', ' || + &STATE |> &POSTALCODE)

In my opinion the second statement is clearer than the first. Both of these gives the same result:

&EVERYTHING = 'JOHN SMITH, 100 MAIN ST, ANYTOWN, CA 90000-0100'

If you know of any other shortcuts would like to share please either add it as a comment, below, or use the Contact form, on the right.

You can learn more about this from the IBM website:

This article was written for IBM i 7.3, and should work for earlier releases too.