Question

I have to code in APL. Since the code is going to be maintained for a long time, I am wondering if there are some papers/books which contain heuristics/tips/samples to help in designing clean and readable APL programs.

It is a different experience than coding in other programming language. Making a function, for example. Small will not help: such a function can contain one line of code, which is completely incomprehensible.

Was it helpful?

Solution

First, welcome to the wonderful world of APL.

Writing readable and maintainable APL code is not much different than writing readable and maintainable code in any language. Any good book on writing clean code is as applicable to APL as any other language, perhaps even more so. I recommend Clean Code by Robert C. Martin.

Consider the guideline in this book that all code in a function should be at the same level of abstraction. This applies to APL 100 times over. For example, if you have a function named DoThisBigTask it should have very few APL primitive symbols in it, and certainly no long complex one-liners. It should just be series of calls to other, lower level functions. If these higher-level functions are all well-named and well-defined, the general drift should be easily determined by someone who does not even know APL. The lowest level functions will be nothing but primitives and will be inscrutable to the non-APLer. Depending on how they are written they may even initially appear inscrutable to a seasoned APLer. However, these low level functions should be short, have no side effects, and can easily be re-written rather than modified if the maintaining programmer is unable to understand the original coding technique.

In general, keep your functions short, well-named, well-defined, and to the point. And keep the lines of code even shorter. It is much more important to have well-defined and well-documented functions than it is to have well-written or well document lines of code.

OTHER TIPS

Since you asked for books and other references, I can suggest:

  • APL2 in Depth by Norman D. Thomson and Raymond P. Polivka. I worked with Ray Polivka for years and he was one of the best APL teachers I have ever known.
  • The classic A. P. L.: An Interactive Approach by Leonard Gilman and Allen J. Rose is good for the core language, but is rather outdated and doesn't contain much that is truly relevant on readability.
  • APL 2 at a Glance by James A. Brown and Sandra Pakin serves in some ways as an update to Gilman and Rose. It covers nested operations and other updates to APL, but has not much specifically directed at readability. Still, if you follow the examples here you will be writing readable code.
  • APL is Easy by STSC and Jerry R. Turner is an intro directed specifically at the APL*Plus line. Again, not much specifically on readability, but the models are generally well-designed readable code.
  • Mastering Dyalog APL: A Complete Introduction to Dyalog APL by Bernard Legrand is quite good if you are specifically workign in Dyalog APL, not so much if you are working in one of the other versions such as APL*Plus (from APL2000)

It is my view that the reputation of APL as a "write-only language" is much overstated. One does need to get used to the primitives and the symbols used to represent them. But then one needs to get used to the syntax and the various library functions in many other language environments. I have seen convoluted code in C, C++, and Java as hard to follow as any APL. Of course, it isn't good C, C++, or Java, even if it is clever.

Some advice:

  • Writing 'one-liners' is a way to test one's mastery of the language, but is very poor practice for production code.
  • Comment to make the algorithm and especially the data structure being used clear. As with any code, comments should add something that cannot be easily read from the code itself, or call attention to complex or obscure code.
  • If possible avoid obscure code so there is no need to explain it. It is usually possible.
  • Make each function do one and only one job, with a clear interface. Avoid global variables for the most part, and document any that are needed.
  • Document the interface, purpose, and efect of any function at the top. Make utilities black boxes without side-effects if possible. If side-effects are essential, document those as part of the interface. Develop a standard header comment structure.
  • Dynamic code built on-the-fly can add flexabiliy to a solution, but is often much harder to debug if problems occur. Make such code bullet-proof to the extent you can, and build in optional logging to help when it turns out to have problems anyway.

You can use an OOP-like style if you wish. But there is no need to do so. If you do, it should IMO be used fairly pervasively through an application, except perhaps for low-level utilities. But OOP-style code can be at least as convoluted as non-OOP code, and APL doesn't have built-in inheritance or other OOP-supporting syntax.

(I'll use here "A" instead of comment, "'" instead of symbol sign.)


Well, I was developing APL for a year, I have only used Aplusdev.org.

You don't even need more. The trick is to try to think OOP-like. You should have -- if I remember well -- structured fields used as class data, sth like {'attribute1 'attribute2, {value,value2}}, so you can easily pick them out like obj.attribute1 in c++. (here 'attribute Pick object, use only in class functions :) )

Moreover, use namespaced functions:

namespace_classname.method(this, arg1)
namespace_classname._private_method(this, arg1, arg2)

and lots of simple tool functions instead of nifty, long lines. The performance drop is not substantial, you can optimize later for say arrays once you see something could be faster.

And before anything: think matlab and mathematica without for loops! :) It helps a lot.

My suggestions for robust, maintainable code:

  • use extensive set of utility functions instead of trickery with those unreadable symbols to make your code always to the point.

  • try-catch blocks there is a built in exception handling, which can be utilized here,

    try_begin();
    A tried code, maybe in extra brackets not to forget try_end() at the end.

    try_end();
    catch(sth, function_here);

    can be nicely implemented. (You'll see, catching errors is very important)

  • crude type checking : implement a standard and use for not-so-many times called functions... (you can put a function with flexible parameters right after a function definition)
    Syntax:

    function(point2i, ch): {
    typecheck({{'int, [1 2]}, 'char}); A do some assertions in typecheck...
    // your function goes here
    }

  • lambda functions can be very effective, you can do some reflections to achieve lambdas.

  • always declare returns with saying "return"!

  • Unit tests based on try-catch testing each and every function you write.

  • I also used a lot of 'apply' and 'map' from mathematica, implementing my own version, they are very-very effective here.

  • I wrote matlab thinking since you can here have a list of structured fields (=class data) in a variable. You will write lots of those if you wanna keep things for-loop-less (and you wanna, trust me). For that you need to have a standard naming convention say indicate with plurals:

    namespace_class.method(objects, arg1, arg2)

To the end: also, I wrote inputBox and messageBox like the ones in Javascript or VisualBasic, they will make very easy hacking together simple tools or checking states. The only catch of messageBox, that it can't put the function-flow on hold, so you need

 AA documentation of f1
 f1():
 {
     A  do sth

     msgbox.call("Hi there",{'Ok, {'f2}}); 
 }
 f2():
 {
     A  continue doing stuff
 }

You can write auto-docs in bash with a gawk/sed combination to put it into a webpage. Also creating HTML formatted code helps in printing. ;)

I hope this was good outline for a proper build-up. Before writing own tools, try to dig up the available tools from the legacy codebase... functions are often even 4 times implemented with different names due to the mess that time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top