A Proposal for Calling Conventions for APL Defined Functions

by Vincent Lin (vlin@ix.netcom.com)

Abstract

This paper will touch on the lack of mechanisms to pass arguments back from defined functions other than return values, if return values are already used as error codes. An extreme case is the use of call-back functions, or event procedures, to the events of GUI objects. In Dyalog APL/W, functionality of arguments and return values of call-back functions are already well-defined. The way you can pass information back from a call-back function, or event procedure, is by storing it as a global variable or by storing it into the Data property of an GUI object, which is also a global variable. This paper proposes a solution - utilize a Call-by-Reference mechanism of function arguments passing, in addition to return values of defined function, to pass results of defined functions back to calling functions. The programming environment is in Dyalog APL/W Version 7.1.3. This interpreter is robust itself and is feature-rich in terms of the integration of APL and MS Windows GUI environment. This paper starts with a description of problems encountered when programming in a GUI environment with call-back functions as well as the difference in design logic of programming styles among procedural programming and event-driven programming. Secondly, this paper presents a brief description of two different mechanisms to pass arguments into and out of defined functions. Thirdly, this paper presents a design solution to the problems mentioned above based on the Call-by-Reference mechanism described in second part. Lastly, a conclusion is made and potential pitfalls are explored.

All code segments demonstrated here are implemented and tested in Dyalog APL/W Version 7.1.3.

PART I: GUI Design, Defined Functions, and Definitions of Two Calling Conventions

GUI Design and Procedural Programming

Modern operating systems provide the Graphical User Interface, GUI in short, to ease the learning efforts and daily work of users. Programs that use GUI environments run in event-driven fashion. In other words, your programs lay out GUI objects on screen, such as push buttons, edit fields, combo boxes, and grids. Your programs also define the actions to take when your users interact with these objects. One action acting upon an object generates a specific event associated with such an object. This event can be taken care of by the GUI environment with default actions if there is no action associated with it, or this event can be taken care of by call-back functions if you have already defined such a call-back function associated with the event. In this event-driven fashion, the design and execution of program logic is simple enough — you define all the objects and the behaviors of objects associated with user actions. You give these objects to users. They interact with these objects and these objects respond with pre-defined and proper behaviors. On the other end as in traditional and procedural programming language, you set up loops and traps to deal with users’ actions so that user interaction is well handled. You have to define the logic to assure that the information among users and programs is interchanged in proper order. Program maintenance is also a painful process, even if you’ve written the codes yourself with documentation. In comparison, GUI design is a dream for programmers. It is simple and elegant. When equipped with the help of visual tools, you can finish the design of user interface and complete program logic as if you were drawing. The only challenges for programmers to tackle are the design of the interface and the writing of call-back functions.

As a full-time APL/W programmer, I encountered an awkward situation while developing a portfolio management system by utilizing GUI objects. Here are the program layouts for both procedural and GUI styles. Note that for the purpose of re-usage modules, the modular design of program blocks is heavily emphasized.

Portfolio Management System in Procedural Programming Style

   R„Initialize.            /* initialize user and database setup, return error code */
Error_Check R               /* check Error code, and prompt user to determine what to do  */
Portfolio„Pick_Portfolio    /* create a form to query portfolio name,  */
                            /* pricing date, and holding date, by giving users the options */
                            /* to choose from */
Error_Check Portfolio       /* check return value to determine whether the user gives a good*/
                            /* selection and data availability */
Holding„Load_portfolio portfolio  /* Load holdings based on selected portfolio  */
Error_Check Holding         /* check return value to see data requested is available   */
R„Display_Holding           /* display holdings of current selected portfolio on screen  */
Error_Check R               /* check return value of previous function, there might be */
                            /* resource problem so that holding screen could not be created  */

After the portfolio is loaded, the on-screen display provides other functionality such as scenario analysis and report printing. The concept and layout is clear enough and it really fosters the re-usage of program codes. The maintenance of APL codes is also amazingly easy, except that it is very difficult to construct each block in APL/W with actual return values1. The reason and the solution are what this paper is all about.

Portfolio Management System in True GUI Style

R„INITIALIZE   © initialize user and database setup, return error code
ERROR_CHECK R  © check the result of Initialization
LOAD_PORTFOLIO © give user the selections of portfolio, and call creation of
               © on-screen portfolio display in call-back functions
ŒDQ '.'        © give user the control

It is a very clean design at first glance. The problem of this style lies inside the LOAD_PORTFOLIO function, which branches into a very complex call-back function tree2. Maintenance is a nightmare even if you’ve written the codes yourself.

It is clear that the first method is preferred if current APL implementation is equipped with extensions, the most obvious among those is the mechanism to return values back to calling functions other than formal return values of functions. Let’s first look at the creation of defined functions in APL.

Defined Functions

User written functions in APL are called defined functions, to distinguish them from APL system functions and APL primitive functions. Defined functions in APL allow a great flexibility in terms of calling conventions. Defined functions can either return values, or not. Defined functions can be monadic or dyadic. Defined functions can have shy arguments and, even shy return values. This kind of flexibility creates greater possibilities in programming style. For example, you can write a defined function to run differently depending on whether it has a left argument 3 or not, simply by defining its left argument as shy. If the left argument does not exist, it can assign its value internally in the function, which allows the program to initialize default values if not given by user. Another example is the shy return value. This type of defined function will return a value, or not, depending on whether there is another variable assigned the return value of such defined function.

Following are some code segments expressing this idea. Note that it is assumed that Dyalog APL/W Version 7.1.3 is the running interpreter.

’RETURN’                                                     
     ’ {R}„RETURN ARG © Function defined with a right argument and shy return value
[1]    R„ARG          © Return a value the same as input argument if it returns    
[2]    ARG„ARG×3      © Modify input argument                    
     ’                                                             
      RETURN 3        © Run the function without assigning return value
      RETURN 4        © Same as above run
      T„RETURN 3      © Run the function with return value assigned to T
      T               © The value of T is assigned as input value of the function
3                     © 
      T„RETURN 4      © Try another value
      T               ©
4                     © 
      I„3             © Use a variable as the input argument
      T„RETURN I      © Assign the return value to T again
      I T             © Check both input and return value
3 3                   © Input is not changed since it is using Call-by-Value convention

By inspecting this APL code segment, it is clear that APL defined functions are powerful and unique in terms of their ability and flexibility to define shy arguments and return shy results. However, the ability to pass back modified values from APL defined functions is restricted as using return values only. It is not possible to define a variable as a place holder and pass it into defined functions as an argument so that the defined functions can hold the value of the variable after its execution. The later fashion of argument passing is commonly seen in API functions for developing GUI applications in modern GUI environments such as MS-Windows or Motif. For now, it is essential to make clear the different concepts of function calling conventions mentioned above. There are basically two mechanisms to pass values into defined functions.

Definition of Call-by-Value

The definition of Call-by-Value arguments is that the actual values passed into defined functions as arguments are only copies of original values, or the actual values of arguments. The scopes of these new copies/variables are strictly inside the functions. Memory used by local variables is actually allocated dynamically by the programming language runtime environments, either from the interpreter itself when programs run or by the operating system during runtime, if the environment is a compiled language. After the completion of the running of defined functions, even though you modify the values of these variables inside defined functions, these variables are destroyed and memory used is freed. The original values of these variables outside the function are not touched/changed. It is the default argument passing method for most programming languages except BASIC. BASIC’s default argument passing method is Call-by-Reference, which will be discussed later, and can be modified into this style by “ByVal” modifier of arguments. Another exception is, of course, APL, which has a Call-by-Value style only. The advantage of Call-by-Value is localization. The scope and life of local variables are absolutely restricted inside defined functions. If well defined, object name clashes never occur. This frees programmers of the burden of keeping track of the uses of object names. The disadvantage is not that clear if you don’t care too much about the efficiency of the program. Some programs will definitely suffer, in terms of efficiency, in Call-by-Value only solution. A good example is a matrix transformation program. This program takes a matrix and returns another matrix, calculated/transformed, with the same shape as the given matrix. The logical actions taken from interpreter or compiler are like this:

Outside Matrix Transformation
   Matrix =: malloc(sizeof(Matrix)) (* the allocation of memory to store input matrix    *)
   Result =: malloc(sizeof(Matrix)) (* the allocation of memory to store output matrix   *)
Enter program
   Matrix =: malloc(sizeof(Matrix)) (* the allocation of memory to store local variable  *)
   Result =: malloc(sizeof(Matrix)) (* the allocation of memory to store local result    *)
   Result =: process process …      (* assign calculation result into matrix *)
   Push(Result)          	    (* to keep the result in stack used outside program  *)
   Free(Matrix)		            (* free the memory which stores local input matrix   *)
   Free(Result) 		    (* free the memory which stores local result matrix  *)
Exit program
   Result =: pop()		    (*  pop up result stored before *)
   memcopy(Result, Matrix)	    (*  copy the contents from Result to Matrix *)
   Free(Result)

At least four memory allocations are required to finish this task. We will have similar actions from the Call-by-Reference convention for comparison later.

Definition of Call-by-Reference

Though the handling of arguments and return values is powerful and unique enough in APL, another mechanism to pass arguments into and return values from defined functions, which is commonly seen in other programming languages such as C or Pascal, is missing. The missing part of the function calling mechanism is the Call-by-Reference (or Call-by-Address) convention, in comparison with Call-by-Value convention used among APL and other programming languages.

The definition of Call-By-Reference is different. The arguments passed into defined functions are addresses of those variables. That is, arguments are only the memory locations/addresses where the values are stored. Inside defined functions, you can reference to the values by pointing to the addresses instead. If you modify the values stored at the memory pointed to or referenced by the addresses passed in, you actually change the contents of these addresses. Values of such variables are changed irrelevant to whether inside or outside of this function. The Call-by-Reference convention of argument passing serves a couple of purposes. The first, this mechanism still provides a way to pass values between calling functions and those called, by means of referencing the same addresses. Second, Call-by-Reference convention provides place-holders for return values. By the method of creating empty/null variables with blanks or empty contents, you can pass in the addresses of these empty/null variables into a function and allow the calculated results of this function to fill the blanks. This usage is commonly seen in modern GUI developing environments as described before. Third, by using the arguments as a place-holder for return values in the Call-by-Reference convention, you can reserve function return values as error codes for error checking. Last, Call-by-Reference eliminates the overhead of memory re-allocations because only the pointers/references are passed into defined functions.

Difference of Using Different Conventions

Let’s take a look at the Matrix Transformation Problem again. The actions required for Call-by-Reference mechanism are:

Outside Matrix Transformation
   Matrix =: malloc(sizeof(Matrix))  (* the allocation of memory to store input matrix *)
Enter program
   Matrix =: process process......   (* the result is put to the memory directly *)
Exit program
	

The difference in terms of efficiency is huge if the matrix we are talking about is really large.

As long as the programming environment provides users with flexibility in calling conventions for argument passing for defined functions, programmers can always determine the best way to pass arguments.

PART II: APL GUI Environments and Call-back Functions

Dyalog APL/W GUI environments

Dyalog APL/W is currently the most advanced APL interpreter in terms of the integration of APL interpreter with Windows GUI environment. Dyalog APL/W facilitates the concept of Objects and builds the link between the APL interpreter and the GUI environment elegantly. All objects provided with Windows can be built/created from APL code. You can associate functions in DLL libraries provided by third party software vendors and integrate them as native APL functions. Each object has its own set of properties, which define the look and feel of this object. Properties include Size, FCol, Bcol, Caption, Font, and others. Each object also has various events, which define the relation between actions from users and reactions from this object. Events include MouseUp, Select, Changed, and others. APL programmers create objects, and define the reactions responding to these events in the form of call-back functions or, in another term, event procedures. Events are actually recorded by Windows and passed back to the APL interpreter as event messages. The APL interpreter receives these event messages and checks to see if any call-back functions/event procedures are associated with them. If no event procedures are defined, APL will pass event messages back to Windows and give back control to Windows so that Windows can update the object status with default actions 4.

One example of such behavior is an EDIT field. An EDIT field allows the user to type characters into the field. Whenever a character is typed inside EDIT field, Windows reacts, depending on whether there is a call-back function associated with ‘KeyPress’ event. If no action is associated with this event, APL does nothing and passes control back to Windows to update the field with the user input charcacter. If this event is associated with a function UPPER, which translates lower case characters into upper case characters, APL invokes UPPER function when the user types a character. UPPER translates this character into the correct format and returns an updated/modified event message. Windows picks up the returned event message and updates the content of this EDIT field. The listing of function UPPER follows 5.

’ MSG„UPPER MSG;I
[1]   © Converts lower-case alphabets to upper-case
[2]    I„'abcdefghijklmnopqrstuvwxyz'¼3œMSG
[3]    …(I>26)/0
[4]    MSG[3]„IœŒA
     ’

Note that each event has a different event message format. An event message serves as a record to keep track of the object name, event name, contents of user action, and other information, associated with each action upon an object .

APL/W offers great flexibility in terms of event processing. It allows immediate execution as the response to user events. You can have APL execute a literal string such as GOTO command or Assignment as the action of events. You can also use an integer number to prompt for APL and Windows to perform default actions to user events. Please refer to APL/W Programming Reference and Manual, and online tutorial for details.

Call-back Functions

A call-back function, or event procedure, is a defined function associated with any event of GUI objects. A call-back function is associated with an object’s event by assigning this object’s EVENT property. It can be assigned during the creation of such object or it can be assigned later after the object has already been created. Here is the syntax of the assignment of call-back functions:

('EVENT' 33 'START')
	or 
('EVENT' 'SELECT' 'START')
	or
('EVENT' 'SELECT' 'START' 2)
The first line associates START as the call-back function of event number 33, which is SELECT as well. The second line performs the same as the first line. The third line adds an optional argument 2 to call-back function START. Here is the header line syntax of call-back functions in APL/W environment.
{Return}„ {Given Optional Arguments} CALL_BACK_FUNCTION  {Event_Message}
Note that developers of APL/W decided to implement a different syntax when writing programs to call call-back functions. Each of the following examples of START can serve as a call-back functions.
’ START
[1]   ©     Dyalog APL/W allows a call-back function without the definition 
[2]   ©     of return value and formal event message passed in.
     ’
’ START MSG
[1]   ©     Dyalog APL/W allows a call-back function without the definition 
[2]   ©     of return value.
     ’
’ R„START MSG
[1]   ©     The regular format for a call-back function.
[2]   ©             
[3]    R„MSG ©    Just send the message back to Windows for default processing
’
’ MSG„{STATUS}START MSG
[1]   ©   Dyalog APL/W allows a call-back function with an optional left argument
[2]   ©      
[3]    R„-1  ©      Inform Windows to do nothing responding to this event
’
’ R„{STATUS}START MSG
[1]   ©    The return value depends on the existence of left argument.
[2]   ©    If left argument exists, return it to Windows for processing.
[3]   ©    If left argument dose not exist, return event message to Windows for 
[4]   ©    processing.
[5]    R„(1+0¹ŒNC'STATUS')œSTATUS MSG  
’

Note that if there is no return value defined inside START, APL just lets Windows perform default actions. It works the same way as if the return value is assigned the same value as the event message. The shy return value can also be assigned another event message composed by the programmer, so that Windows can pass back to APL and start another event process loop 6. The shy return value can also be numerical such as 0, 1, or -1, which directs Windows to perform either the default action, or not. Please also refer to APL Programming Manual or online tutorial for more information.

What’s Wrong with Call-back Functions

Programs would never see the return values of call-back functions because they are in event message format and they are consumed internally by APL and Windows. The left and right arguments passed into call-back functions are both in the Call-by-Value mechanism. That is, only the values are passed into call-back functions without being able to pass back to the function which define the graphical objects, events, and call-back functions. The way that call-back functions work would make it impossible for programmers to write codes utilizing return values of call-back function directly or pass back any values from call-back function to defining functions. In Dyalog APL/W, luckily, if a simple action is needed to respond to a user event, you can associate an Execute Expression to the event. When APL receives an event message at such object/event, APL can execute the expression directly so that overhead is avoided as much as possible. This usage can be expanded to an extreme level where no call-back functions are used but instead, Execute Expressions only. One of the examples listed below is a general purpose program PROMPT, which demonstrates the Execute Expression method and also demonstrates the need for a Call-by-Reference mechanism:
’PROMPT’
     ’ R„TITLE PROMPT PRMPT
[1]   © a modal dialog box, prompt a message (* given PRMPT *) 
[2]   © R is 1 if user selects Yes and R is 0 if user selects No.
[3]    'PROMPTMSG'ŒWC'MSGBOX'('Caption'TITLE)('Text'PRMPT)('STYLE' 'QUERY')
      ('EVENT' 'MSGBTN1' '–R„1')('EVENT' 'MSGBTN2' '–R„0')
[4]    ŒDQ'PROMPTMSG' ª ŒEX'PROMPTMSG'
     ’

Please note that this function works as a cover function for the standard APL/W GUI object ‘MsgBox’ in ‘Query’ style. Note also that the way this program was written is only to make it more modular. Programmers can simply plug in a line like the following to give the user a prompt and to receive the user’s reaction, without extra coding:

RESULT„'Prompt Test:' PROMPT 'Do you want to save the results?'

This is the modal window when it is run:
screen snap

The shortcomings of this implementation for the GUI environment is that functions executed inside Execute Expressions do not have the rich information passed in as in event messages for call-back functions. For the purpose to emulate call-back functions to process event, you have to pass the event information into Execute Expressions, the same information as is passed into call-back functions in event messages. Unfortunately, most of the information is simply not available because it is directly reported from Windows GDI interface.

If Call-by-Reference is allowed in APL/W programming, the running program might look like this:

’PROMPT’
     ’ R„TITLE PROMPT PRMPT
[1]  © a modal dialog box, prompt a message (* given PRMPT *) and provide
[2]  © R is 1 if user selects Yes and R is 0 if user selects No.
[3]  'PROMPTMSG'ŒWC'MSGBOX'('Caption'TITLE)('Text'PRMPT)('STYLE' 'QUERY')
     ('EVENT' 'MSGBTN1' 'QUERY_USER_SELECTION' R)('EVENT' 'MSGBTN2' 'QUER
     Y_USER_SELECTION' R)
[4]  ŒDQ'PROMPTMSG' ª ŒEX'PROMPTMSG'
     ’

Now, R works as value passed back to user action to MsgBox, which is a more consistent and logical way of program coding.

PART III: Using Call-by-Reference as Solutions

Advantage of Call-by-Reference

As described above, the Call-by-Reference mechanism allows programmers to write functions or procedures with more flexibility in argument passing. The way a variable is modified in a function or procedure is clearly indicated, as it is shown as an argument passed in either Call-by-Reference or Call-by-Value fashion. It also provides another method to return a value in addition to return values of any procedure. It is most useful when the usage of return values is pre-defined, such as call-backs in the Dyalog APL environment. Actually, the usage of return values is more universally and consistently pre-defined in C programming language. C language assumes every function or procedure is actually a function that returns something every time. It’s up to the programmer to determine whether to assign a return value explicitly inside defined functions, and whether to explicitly use the return value or not. Combined with Call-by-Reference mechanism, C programming language provides users with extreme flexibility.

This mechanism also benefits programmers to program in modular style. Since return values are always treated as error codes, it would be much easier to write general purpose modules to fit into different programming tasks. Actual arguments needed by sub-routines and return values needed by calling programs can be handled elegantly by the combination of Call-by-Value and Call-by-Reference mechanisms.

Proposed Solution

It is an excellent solution to utilize Call-by-Reference mechanisms for call-back functions in Dyalog APL GUI environments. Left arguments passed into call-back functions, provided by programmers as the arguments, can be modified inside call-back functions. After the call-back function exits, arguments would be passed back to calling functions with modified values. Programmers don’t have to implement global variables or put modified values inside the DATA property of any objects. If the values passed into call-back functions are not intended to change, just don’t change them in call-back functions. Applications with call-back functions written with Call-by-Value only fashion in mind would not need to change at all.

This solution can be expanded further into a formal specification for APL defined functions. The specification states: The left argument of a defined function can be either explicit or shy. If the left argument exists, it is passed into defined function in Call-by-Reference convention. The outcome of such addition in specification is tremendous. It provides with the solutions to the problems described above for call-back functions. It also provides with a great flexibility for programmers in terms of argument passing mechanism. The effort to adopt this new specification into existing APL codes written without Call-by-Reference mechanism is minimum. If your existing programs never change the values of left arguments inside defined functions, you don’t have to change any code at all.

There is a requirement when implementing value passing from inside call-back functions back to the function that defines the associated object in Call-by-Reference fashion. Programmers have to issue QuadDQ explicitly after all GUI objects have been created to make sure that the program is not terminated after all GUI objects are given to users to interact 7 with. There are more considerations on this issue and they will be discussed later.

Sample Problems and Solutions

Example I

A simple function to increment any variable with given interval. The concept is similar to ‘++’ operator in C language. Here are the code segment and how it works(assuming Call-by-Reference is available):

>’ {R}„VAR INCREMENT INC
[1]   © return value R is 0 if operation fails, 1 if succeeds
[2]   © set TRAP to check DOMAIN ERROR only as an example
[3]    R„1 ª ŒTRAP„11 'e' '…R„0'
[4]    VAR„VAR+INC
     ’

And here is how it works:

      A„3
      ERROR„A INCREMENT 1
      ERROR
1
      ERROR„A INCREMENT 3
      ERROR
1
      A„'TEST'
      ERROR„A INCREMENT 1
      ERROR
0
      A„3
      A INCREMENT 1
      A„'TEST'
      A INCREMENT 3

In the above test runs, you can notice that it is very easy to perform error checking without bringing up the session window. The value of A is updated after the completion of the program if Call-by-Reference mechanism is used.

Example II

A special form with Push Buttons is set up to increment or decrement a number as the record. It allows the user to select/click on one of the buttons. The call-back function will calculate a new record number and pass the result back to the calling function, which will then update the display screen of record counts or update the internal data structure.

Example III

A function as a call-back function that changes the state of a running program with pre-defined finite states. The call-back function simply passed back new state based on user actions as the Call-by-Reference argument and program running state are modified. Other functions can reference to this program state easily. A very practical usage of this type of function is to keep track of Graphical Context (or GC in short) in modern GUI programming APIs.

Example IV

A function uses Call-by-Reference convention of arguments as a place holder for requested information. You click on a button, then the requested information is passed back as an argument you pass into the function. Your running program then has the variable with a good value in it. This concept is very useful in implementing Client/Server architecture for database access. First, the call-back function checks the availability of the server and database, and returns a flag for it. Another call-back function requests total record counts that satisfy some given query criteria’s based on the result of server availability check. The third function can then request real information from those satisfied records.

Additional Considerations

Before we put any real efforts into work, some other points are noted here:

  1. The implementation of the Call-by-Reference mechanism can be done without any further complication if we restrict the scope of application for Call-by-Reference mechanisms to call-back functions for Dyalog APL/W only. Every given left argument of call-back functions is in Call-by-Reference fashion. Firstly, it works and it solves some of the problems I have encountered. Secondly, since the Dyalog APL/W implementation of QuadNA has already shown this possibility, it should not be too difficult to implement this. As described above, most existing programs don’t have to change at all.
  2. The expanded version of specification for defined functions suffers when the format of arguments are simple enough but contents of such arguments are large so that they are without left arguments. Matrix Transformation Program mentioned previously serves as a very good example of this limit. One hacker solution is to create dummy right argument. Then programmers can pass the pointer to large data matrix into defined functions as left argument without performance penalty.
  3. The solution proposed in the previous section can not be done without support from interpreter vendors. Dyadic for Dyalog APL/W, as well as IBM for APL/2, can both serve as the major driving force for this improvement. The ISO APL Committee can also play a major role here. One of the key issue is to define an operator denoting “take the address of” and another operator for “get the referenced/pointed value”.
  4. APL is never a strong type casting programming language. It means that there is no declaration for any variable types at all. How can you tell if the contents starting from a given address are integers or text strings? One possible solution is to restrict the usage of the Call-by-Reference convention of arguments to be left arguments only, which is stated above as the expanded solution. APL is not responsible for type checking at all because data type of arguments matters only when programmers apply operations onto these arguments.
  5. Another possible solution is to define the use of pointers in APL. Pointers are most common in other programming languages such as C or Pascal. Pointers allow programmers to implement complex data structures and algorithms. Please refer to other programming languages’ manuals to get a more detailed and concise definition of their implementation. For APL, we have to define a monadic operator that works as “take the address/pointer of” and another monadic operator that works as “take the referenced/pointed value of”. By definition, the arguments passed into defined functions with the Call-by-Reference mechanism are the results of any applicable variables being applied to the “take the address/pointer of” operator. Inside defined functions, we can apply the “take the referenced/pointed value of” operator to those arguments passed in in Call-by-Reference fashion. The header lines of defined functions are not affected and do not need to change at all because programmers take the responsibility of managing the consistency of their arguments. However, APL has to validate the pointer while applying “take the referenced/pointed value of” operator or APL has to define another name class for pointers.
  6. You cannot apply the Call-by-Reference convention to variables such as constants, literal numeric, and anything that can not be assigned values. However, this restriction is not APL specific. It is universal to all programming languages that have Call-by-Reference mechanisms for arguments.
  7. Currently implementation of Dyalog APL/W allows programmers to create “live” GUI objects without issuing QuadDQ. That means that all GUI objects can take user input at the time they are created in the session. Programmers are required to issue QuadDQ once to enter user interaction mode. To take advantage of Dyalog APL/W’s run-time interpreter, it is required for Dyalog APL/W programmers to put the following line into QuadLX for each workspace:
           ŒLX„'MAIN_PROGRAM ª ŒDQ ''.'' ª ŒOFF'

    This line directs APL run-time environment to do three things while it starts and loads the workspace. 1). Start MAIN_PROGRAM. 2). Give control to user. 3). After the execution of whole program, log off of APL.

    That means it is impossible to return any value into calling functions since calling functions are already finished running in this programming style. Another program structure has to be implemented so that the Call-by-Reference mechanism can be used everywhere.

    In a similar situation, where your program is implemented in procedural fashion and some steps in the whole program flow require user interactions with GUI objects, you must issue QuadDQ explicitly right after the creation of GUI objects to give GUI objects to users. Or more precisely stated, you have to issue QuadDQ right after the creation of GUI objects to explicitly force your users to respond to GUI objects before users can proceed to next step. The Portfolio Management System mentioned in the first part of this paper serves as a good example.

  8. C or C++ allow you to use Pointer-to-Function as an argument in functions. It is an extended functionality. I can imagine that this is also useful to the implementation of call-back functions.8 The addition of Call-by-Reference mechanism in APL could allow APL to have a better connection with other programming languages. Sometimes your programs have to call procedures/functions/libraries written in other programming languages. Examples of such procedures/libraries are those functions in Windows .DLL files. A good design of a programming language would allow you to treat those external functions as an extension to the existing structure so that programmers could use those external functions as if they were part of the language. Two examples in Dyadic provided workspaces demonstrate the calling of external functions which are in Call-by-Reference fashion. One is in PRORIENT workspace and the other example is in FSCB workspace. Dyadic designed a mini-set of calling conventions to call external functions in Call-by-Reference fashion.
  9. If the Call-by-Reference mechanism or even the Pointer concept are implemented in APL, those calls to external functions could be done directly in APL syntax instead of working through a totally different syntax.

PART IV: Conclusions

Conclusions

The mechanism to pass arguments back from defined functions by the Call-by-Reference calling convention definitely gives a reasonable solution to avoid the problems from not being able to return values in addition to error checking codes. Programmers can avoid the usage of global variables or avoid the need of double error checking by implementing functions in Call-by-Reference fashion. But it also brings up some other issues as noted above. I hope that other APL vendors in addition to Dyadic, such as IBM, could come out with some solutions for argument passing mechanisms. It would be even better if Dyadic and IBM could work together to come out with a specification that can be included in ISO APL specifications. Every vendor could implement this mechanism accordingly. However, upon considering the potential problems we might have, it is still too early to jump to a conclusion yet. Overall, any additional features for programmers to program in APL in terms of flexibility and functionality are always welcomed.

Footnotes

  1. The major difficulty of this programming style is that you can not avoid performing double error check for each sub-routine. From main program, you have to perform error check on return values to make sure that each sub-routine has performed as expected. From inside sub-routine, you still have to check each user action to make sure that input by the user is meaningful. In addition, sometimes it is just impossible to pass anything back to main program as error code, and global variables have to be implemented to keep track of the running status of sub-routines.
  2. Imagine that the call-back functions for all the on-screen objects have to keep track of current status of program, pass the portfolio selection information among different modules, and still maintain modular fashion, i.e. all modules are still re-usable.
  3. Dyalog APL/W allows shy arguments to show as left arguments only. This posts a limited usage of shy arguments.
  4. From the workspace WTUTOR provided by Dyadic, in Event Processing section, Dyalog APL/W performs “default processing” if 0 is given to a specific event; and it ignores the event if -1 is given to such an event. Obviously these behaviors are quite different from those when invoking UPPER workspace. Any comments from Dyadic?
  5. Note that a simple character check on line 3. UPPER will modify event message only if the character is a small cap letter.
  6. This mechanism applies to user-defined events also. My company actually implemented such mechanism to pass program control among many modules. The only concerns which I have from such programming style are program complexity and runtime performance. I haven’t discovered any benchmark numbers for performance issues yet. It is for sure more complex than other styles though.
  7. The reasons that Dyalog APL/W requires programmers to issue QuadDQ command after GUI objects have been created are 1), for the program to run with Run-time interpreter without the presence of APL session; 2), for the program to give specific object(s) only to users to respond, examples are those modal dialog boxes; 3), to flush out the buffers which contains those objects created in programs. It is an excellent design for performance.
  8. As footnote #6 states, the implementation of user-events and the mechanism to pass event messages other than the ones passed into call-back functions back to Windows performs functionally equivalent to pointer to functions.

References

This list of publications provide general background reference.

Donnelly, P. [1995]. Dyalog APL/W 7.x User Guide and Windows Interface Reference Manuals, Dyadic Systems Limited.

Aho, A. V. and Sethi, R. and Ullman, J. D. [1986]. Compilers – Principles, Techniques, and Tools. Addison-Wesley.

Eklof, M. D. and Mcdonnell, E. [1993] Programming Language APL, extended International Standards Organization. Committee Draft 1.

Marcotty, M. and Ledgard, H. [1986]. Programming Language Landscape – Syntax , Semantics, Implementation. Second Edition. SRA.

Vincent Lin
Jennison Associates
Boston, MA