Programming languages and what’s next

  • Post category:Programming
  • Reading time:7 mins read

My review of programming languages I learned in during my years in IT.

BASIC

On the Texas Instruments TI99-4a. 

Could do everything with it. Especially in combination with PEEK and POKE. Nice for building small games.

Impossible to maintain.

GOTO is unavoidable.

Assembler

In various variants.

Z80, 6802, PDP 11, System 390.

Fast, furious, unreadable, unmaintainable.

Algol 68

Loved this language. REF!

Have only seen it run on DEC 10. Mainly used in academic environments (in the Netherlands?)?

Pascal

Well. Structured. Pretty popular in the early 90s. 

Again is this widely adopted?

COBOL

Old. Never programmed extensively in it – just for year 2000.

Totally Readable.

Funny (rediculous) numbering scheme.

Seems to be necessary to use GOTO in some cases which I do not believe.

Smalltalk

Beautiful language.

Should have become the de facto OO programming language but failed for unclear reasons.

Probably because it was way ahead of it’s time with it’s OO base.

Java

Totally nitty gritty programming language.

Productivity based on frameworks, which no one knows which to use.

Never understood why this language was so widely adopted – besides it’s openness and platform independency.

Should never have become the de facto OO programming language but did so because Sun made it open (good move).

Far too many framework needed. J(2)EE add more complexity than it resolves.

Always upgrade issues. (Proud programmer: We run the application in Java! Fed up IT manager: Which Java?)

Rexx

Can do everything quickly.

But nothing structurally.

Ugly code. Readable but ugly.

Some very very strong concepts.

Php

Hodge podgy language of programming concepts and html.

Likely high programmer productivity if you maintain a stark discipline of programming standards. Stark danger of creating unmaintainable crap code mix of html and php.

Python

Nice structured language.

Difficult to set up and reuse.

Can be productive if nitty gritty setup issues can be overcome.

Ruby (on Rails or off-track)

Nice, probably the most elegant OO language. Too nitty gritty to my taste still. Like it though.

I would start with this language if I had to start today.

What is next

Visual programming? Clicking building blocks together?

In programming we should maybe separate the construction of applications from the coding of functions (or objects, or whatever you call the lower level blocks of code.

Programming complex algorithms (efficiently) will probably always remain a craft for specialists.

Constructing applications from the pieces should be brought to a higher level.

The industry (well – the software selling industry) is looking at microservices but that gives operational issues and becomes too distrubuted.

We need a way to build a house from software bricks and doors and windows and roof elements.

Probably we need more standards for that. 

Another bold statement.

AI systems “programming” themselves is nonsense (I have not seen a shred of evidence). 

AI systems are stochastical systems. 

Programming is imperical.

In summary, up to today you can not build software without getting into the nitty gritty very quickly. 

It’s like building a house but having find your own tree and rocks first to cut wood and blicks from. 

And then contruct nails and screws.

A better approach to that would help.

What do you think is the programming language of the future? What need should it address?

WTO directly from Rexx

  • Post category:Rexx
  • Reading time:1 mins read

There are probably more ways do write a message in the system log – “Write to Operator” from a Rexx script.

This is a very straightforward one I found some time ago somewhere on the Interweb.

/* rexx */                                           
trace r                                              
call syscalls 'ON'                                   
address syscall                                      
path='/dev/console'                                  
'open' path O_wronly 666                             
if retval=-1 then                                    
do                                                    
say 'file not opened, error codes' errno errnojr     
return                                               
end                                                  
fd=retval                                            
rec= 'This is my message text to appear in the system log.' || esc_n                            
'write' fd 'rec' length(rec)                         
if retval=-1 then                                    
say 'record not written, error codes' errno errnojr  
'close' fd                                           
 

Have more solutions? Or remarks? Please let me know below.

Running a MVS or TSO Rexx program from the z/OS Unix environment

  • Post category:Rexx
  • Reading time:2 mins read

You probably know that you can use Rexx programs in z/OS Unix.

What you may not know is that you can also run a TSO or MVS Rexx program from the z/OS Unix environment.

There is a unix command called tso for this. It works as simple as this:

tso –t “exec ‘YOUR.MVS.REXXPDS(TESTREXX)’ EXEC”

will execute your TESTREXX program.

You may want or need to allocate TSO datasets or other datasets in order to execute the Rexx.

You can simply allocate these through the export command.

export ddname=YOUR.MVS.DATASET

You can add these exports to you shell script, or add them to your .profile.

$ZOOM – Mother of all EDIT macro’s

  • Post category:ISPF
  • Reading time:2 mins read

The most useful ISPF EDIT macro ever. I think it was written by Paul van Goethem from Belgium, somewhere before 1993. It has quickly spread through many sites.

Point your cursor at at dataset name in a file your are editing en executing the macro will launch an EDIT session of that file.
I always put in under PF key PF4 which by default has the not very useful default value RETURN.

Note the value of the variable INVALID in the below may be corrupted. It should contain any character that is not valid as part of a dataset. The binary values it can contain are not very portable.

/****************************REXX***********************************/
/* FUNCTION: RECURSIVE EDIT OF BROWSE VIA DSNAAM AND,OR MEMBER     */
/*  SPECIFIED VIA CURSOR SENSITIVE EDIT MACRO                      */
/* FORMATS ACCEPTED:                                               */
/*  DATA.SET.NAME   : EDIT/BROWSE OF THIS                          */
/*  DATA.SET.NAME(MEMBER) : EDIT/BROWSE THIS                       */
/*  MEMBER    : EDIT/BROWSE IN SAME LIBRARY AS INDEX               */
/****************************REXX***********************************/  
ADDRESS ISPEXEC    INVALID= ",'\<\>,:;+��▖!�%�-="
ADDRESS ISREDIT 'MACRO (FUNCTIE)'
FUNCTIE = TRANSLATE(FUNCTIE)  
IF SUBSTR(FUNCTIE,1,1)='B'
THEN FUNCTIE='BROWSE'
ELSE FUNCTIE='EDIT' 
LIN=0 
ADDRESS ISREDIT '(LIN,COL) = CURSOR'  
ADDRESS ISREDIT '(CLINE) = LINE 'LIN   
/* FIND CURRENT WORD */ 
T=SUBSTR(CLINE,1,COL)  
T =TRANSLATE(T,' ',INVALID)    
Y=LASTPOS(' ',T) 
IF Y=0
THEN T=CLINE    
ELSE T=SUBSTR(CLINE,Y+1)
PARSE VAR T WOORD  .   
WOORD =TRANSLATE(WOORD,' ',INVALID)
"CONTROL ERRORS RETURN"
IF INDEX(WOORD,'(') /= 0 THEN DO /* TAKE DSN IF SPECIFIED */
  PARSE VAR WOORD  DSNAME '('  MEMBER ')' 
  FUNCTIE" DATASET('"SPACE(DSNAME)"("MEMBER")')" 
  FRC=RC
  END
ELSE DO
  IF INDEX(WOORD,'.')/=0 THEN DO   
    PARSE VAR WOORD  DSNAME . 
    FUNCTIE" DATASET('"SPACE(DSNAME)"')" 
    END  
  ELSE DO         
    ADDRESS ISREDIT "(DSNAME) = DATASET"  
    WOORD = SPACE(TRANSLATE(WOORD,' ','.()'))
    FUNCTIE" DATASET('"DSNAME"("WOORD")')"  
    END    
  FRC=RC   
  END  
ADDRESS ISPEXEC "CONTROL ERRORS CANCEL"  
IF FRC> 4 & SYMBOL(ZERRMSG)/= 'LIT' THEN DO      
  MSG= ZERRMSG':'ZERRLM            
  "SETMSG MSG(ZOM000A)"            
  END                           
RETURN

Ways get utc / gmt time zone (offset) versus local time in Rexx on z/OS

  • Post category:Rexx
  • Reading time:2 mins read

Regularly we need to compare local time to absolute time UTC (or GMT) programmatically.

This can be done in various ways.

The cleanest way is to use the static system symbols that z/OS defines. See also section “Static System Symbols” in the z/OS Initialization and Tuning Reference.You can easily use this in a Rexx program. For example: 

/* Rexx */  
/* Display UTC Time elements */
say  mvsvar('SYMDEF','HR')      
say  mvsvar('SYMDEF','MIN')     
say  mvsvar('SYMDEF','SEC')     
say  mvsvar('SYMDEF','HHMMSS')  
say  mvsvar('SYMDEF','LHHMMSS') 

It is also possible through Unix System Services date command to obtain UTC:

date -u
Wed Aug 21 15:20:42 GMT 2019 

A more complex way (old fashioned) to achieve the same is addressing the CVT extension block:

                   
cvt = c2d(storage(d2x(16),4))                                
cvtext2 = c2d(storage(d2x(cvt + 328 ),4))
offset  = ((c2d(storage(d2x(cvtext2+56+2),4))) * 16) /3600000000 
timezone = "+0"||offset||"00"                   

Thanks to Henk for the latter two solution alternatives.

— Niek de Greef

Compare Disk contents with Catalogs – a custom Rexx and JCL solution

  • Post category:Rexx
  • Reading time:2 mins read

This one is untested since 1997. A little warning, though I believe it will still work.

During a z/OS migration (probably still MVS/ESA or maybe OS/390) we needed to restructure the catalog layout. The client did not have a good catalog structure in place and almost everything had ended up in the master catalog. A small nightmare, especially for a smooth upgrade. BEtter worded: they made a mess of their catalogs. (The company does not exist anymore.)

I created some custom programs to compare catalog contents with contents on disks.

The job in CMPLCLVJ does the following:

CMPLCLVJ

  • Step INTRPOLD – Interpret an existing LISTCAT result for easier handling during the compare
  • Step LIST: Create LISTVTOC of desired volumes
  • Step INTRPLV – Interpret the LISTVTOC output for easier handling during the compare
  • Step COMPLCLV – Compare the Listcat and LISTVTOC

The following Rexx programs are used in this job:

INTLISTC – interprets the LISTCAT output.

INTLISTV – interprets the LISTVTOC results

CMPLCLV – compares the interpreted (transformed) listcat and listvtoc results and reports the results.

// Judd Froam

A simple Rexx program to find matches / unmatches in file contents

  • Post category:Rexx
  • Reading time:3 mins read

The problem were are solving here:

You have 2 files, one has records (lines) with “key” values in the first word, the second has records (lines) “key” values in the second word. (A Word here is defined as a string delimited by blanks – similar to the definition in Rexx – See Rexx Reference)

For all of the key entries in file1 you want to know if key entries exist in file2. If the key entry does not exist the record in file2 is written to the output file.

The solution in Rexx below works as follows:

Build a simple hash table of key entries in file1. For each record in file2, check if the key value has an entry in the hash table. If not, write the record to the outfile file.

BTW in Rexx programs for files that are not excessively large, I have the habit of reading them fully into a stem variable before processing. Similarly I use a stem variable to capture the output data, and write that in one go after processing is complete. Not sure if that is a good habit, but it makes programming easy.

/* Rexx */
trace off
/* Fill InpRec1. and InpRec2. */
Call ReadInput
/* Fill filter.     */
Drop filter.Do N = 1 To InpRec1.0  
entryname = Word(InpRec1.N,1)  
   filter.entryname = 1
End /* Do */
/* Compare old file with new and write output */
Drop OutRec1.OutRec1.0 = 0
Do N = 1 To InpRec2.0  
   entryname = Word(InpRec2.N,2)  
   If filter.entryname = 1  
   Then Do
      NOP /* This entry exists in both, that's ok */      
      Say 'To be skipped : ' entryname    
      End  
    Else Do /* Write this line, this entry has to be processed */
       help = OutRec1.0 + 1      
       OutRec1.help = InpRec2.N      
       OutRec1.0 = help    
       End
End /* Do */
 Call WriteOutput
Exit
/*******************************************************************/
/* Routines ********************************************************/
/*******************************************************************/
/*******************************************************************/
ReadInput:
Address Tso
'EXECIO * DISKR FILTER  (Stem InpRec1. Finis'
If RC <> 0
Then Do
    Say 'Error reading input file FILTER, Rc = ' RC
    Exit 69  
End
'EXECIO * DISKR INPLIST (Stem InpRec2. Finis'
If RC <> 0
Then Do
    Say 'Error reading input file INPLIST, Rc = ' RC
    Exit 69  End
Return /* ReadInput */
/*******************************************************************/
WriteOutput:
Address Tso
'EXECIO * DISKW OUTLIST (Stem OutRec1. Finis'
If RC <> 0
Then Do
    Say 'Error writing output file OUTLIST, Rc = ' RC
    Exit 69
  End
Return /* WriteOutput */