Home > Coding, Mainframe, REXX > Anonymous functions in REXX

Anonymous functions in REXX

In this blog post https://www.ibm.com/developerworks/community/blogs/MartinPacker/entry/dragging_rexx_into_the_21st_century?lang=en Martin Packer was experimenting with modernizing REXX on the mainframe. One topic he mentioned but did not resolve was the use of anonymous functions in REXX.

An anonymous function is a block of code that is not associated with an identifier like a function name. It’s just a block of code you can pass to something else (another function) to run. It’s used a lot in things like jQuery to implement ‘callbacks’ from the invoked function back into your own code.

So I got to thinking about this and did a little experimenting. The following is ‘close’ in that I can pass a block of code into a called function and have it execute there. It could implement some sort of ‘callback’ by for example returning data to the original caller on the stack or via an external data set but I did not go that far. I just wanted to see how hard it would be to run some code passed in by the caller. So here’s my solution:

This first program is the caller of some function that will use the anonymous function code block I pass to it. I define the anonymous function in a comment block in the program (makes it easier to write anything longer than a couple of lines) and load it into a variable using sourceline. Notice that each line of the anonymous function has to end with a semicolon since all the lines get concatenated together into one big string.

/* rexx */                                                             

func=loadfunc('MYANONFUNC')                                                                                                               
rc=z67('parm for z67',func,'This is a message')                        
return 0                                                               

/*-------------------------------------------------------------*/      
loadfunc: procedure                                                    
parse arg reqdname                                                     

code=''                                                                

indata=0                                                               
do i = 1 to sourceline()                                               
   line = sourceline(i)                                                
   select                                                              
      when substr(line,1,11)='/*FUNCTION ' then do                      
         parse var line . name .                                       
         if name=reqdname then do                                      
            indata=1                                                   
            end                                                        
         end                                                           
      when substr(line,1,2)='*/' & indata=1 then leave                 
      otherwise do                                                     
         if indata then code = code||line                              
         end                                                           
      end /* select */                                                 
   end /* do i=1 to sourceline() */                                    

return code   
/*-------------------------------------------------------------*/      

/*FUNCTION MYANONFUNC                                                      
trace "I";                                                             
parse arg msg;          
say msg;   
trace "O";              
return 0;                
*/

The following code is the called function (called z67 in this case), It accepts a parameter for its own use (myparm) which is just displays to demo the ability, the function string itself (func) and any data (funcdata) to be passed to the anonymous function from the caller.

/* rexx */                           
parse arg myparm, func, funcdata     
say "myparm is ("myparm")"           
rc=x(funcdata)                       
return rc                            

x: procedure expose func             
interpret func                       
return 0

The code above parses out the three arguments passed in, displays the first one and then calls an internal function (x) passing it the function data for the anonymous function (funcdata). That allows the passed code to parse any arguments passed to it by the original caller. The ‘x’ routine gets to the function code itself by exposing the ‘func’ variable and just executes it using interpret.

Notice that the anonymous function code can also accept arguments from the original caller and do things like turn on trace. It would be quite easy to modify this code so that a variable number of parameters could be passed to the invoked passed function.

Advertisements
Categories: Coding, Mainframe, REXX Tags:
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: