Current issue

Vol.26 No.4

Vol.26 No.4

Volumes

© 1984-2024
British APL Association
All rights reserved.

Archive articles posted online on request: ask the archivist.

archive/16/2

Volume 16, No.2

This article might contain pre-Unicode character-mapped APL code.
See here for details.

Note that this article contains quite a bit of APL code - this is in APL2741 font, downloadable from this site (32K). There is a new problem in showing the {match} symbol in IE5 (it is treated as an optional hyphen), so it has now been duplicated in the font at position ch(166) which will paste into APL*PLUS as the split-stile character. If you already have the font, please check the build date (double-click the font in your fonts folder) and re-install it if you don't have the October 29th 1999 version.

SHARP APL vs. APL2 coding style

by Dan Baronet (danb@dsuper.net)

Introduction

Following Soliton’s announcement to unleash their APL into the Linux community I decided to review the differences between SHARP APL and APL2 style APLs (IBM’s APL2, Dyalog, APL+Win). I have divided the report into several articles, each with a different topic.

This article is the first of the series. It should be read before any of the others.

Not having a current version of IBM’s APL2 on hand I have been making my observations based on Dyalog’s APL using Œml=2, which, like APL+Win, follows APL2 closely.

When reading this text keep in mind the date it was written (September 1999) as languages change and may render this information incorrect in the future.

Conventions

In the text italicized words have a special meaning and often precede their definition.

SAPL refers to SHARP APL, including SAM which is SAPL under MVS and SAX which is SAPL under Unix. SAX is the one also running under Linux and compared to APL2 here.

Variables and workspace names are enclosed in ‘quotes’. Functions and files are enclosed in <angle brackets>.

The term atom refers to a numeric or character scalar only. The term item refers to any scalar.

Whenever possible I will show examples in SAPL and APL2 side by side.

A bit of history

SHARP APL (SAPL) used to be a mainframe product only until a PC version appeared in 1984 (release V17 of SAM and rel V20 later on). It remained pretty much so as the PC version never took off. The PC version ran under DOS and lacked many features. Because it was emulating the S/370 it was also very slow.

SAPL really is a product as opposed to a language. There are various components including a batch scheduler, a file system, many shared variable processors, sorting utilities, etc. More importantly, SAPL tasks may spawn and control other APL tasks with system functions, something no other APL has ever achieved. Very large secure systems can be (and have been) written in SAPL.

By contrast, in IBM’s APL21, everything but the language is external and only available through auxiliary processors (APs). There are no quad functions, for example, to perform file operations.

There are pros and cons for using each APL and the purpose of this article is not to take sides but rather to show the differences between them as objectively as possible.

SAX came to life in the early 90’s and is a more flexible version of SAM. It is based on “the Dictionary of APL” by Ken Iverson. It extends SAM V21. It more closely resembles J. (Think of J on APL char set.) The Linux version is the same as the Unix version.

At some point there was a shift in philosophy using the first versus the last axis in function operations (ex: / vs. š ) and some newer functions were defined in terms of the latter. APL2 has remained pretty much a “last axis favoured” language.

Enclosed Arrays

In SAPL the term “enclosed array” is used. In APL2 the term used is “nested array”. They are, practically, the same thing. The term “boxed array” (SAX) is also sometimes seen but won’t be used here.

Let’s assume we have the following variables on hand:

a„'text'ª b„1 2 3 ª c„2 3½a ª d„2 4 3½¼33

The simplest way to create an enclosed item is to use the expression

SAX APL2APL2
x„<anyvalue x„›anyvalue

In SAPL there is no maximum level (depth) of enclosure. Thus <<<a is ‘a’ enclosed 3 times. In IBM’s APL2 there is a limit.

Items must be opened before applying a function to them. If x„<2 3 4 then

  +/>x                  +/œx

will result in the sum of the values in ‘x’.

To create a list (vector) of enclosed items we can use the usual catenate function (, ):

   x„(<a),(<b),<c       x„(›a),(›b),›c

This will ALWAYS work in all interpreters I know. But there is an easier (incompatible) way to do this:

   x„aœbœc              x„ a b c

Which brings us to the way things are presented to the interpreter.

Notation

APL2 uses what is known as strand notation. Using this notation, arrays are created by putting items together side by side, without using catenate (‘,’) as in the example above. Sometimes it is handier than using ‘,’. SAX does not support that notation and requires the use of functions ‘,’ to catenate items together or ‘œ’ to link them if they are to be enclosed.

Link

Link is a specific SAPL function to ‘enclose and catenate’ with a twist. To understand its use let’s look at the monadic case first:

Monadic ‘link’

This is another function specific to SAPL. The formal definition is: ‘enclose the argument IF it does NOT contain already enclosed item(s)’. Sort of a conditional enclose. In fact conditional enclose is its real name. See its usage2:

   x„œvar           –(1<|¦x„var)/'x„›var'

Determining if an array is enclosed

An application of this is to determine whether we are dealing with an enclosed array or not:

   x¦œx              1<|¦x

will return 1 if ‘x’ is enclosed. There is no depth function in SAPL.

Dyadic ‘link’

aœb will enclose ‘a’ and catenate it to the enclosure of ‘b’ if ‘b’ does NOT contain enclosed elements. Formally,

aœb is the same as (<a),œb

Why not use (<a),<b ? The reason is to avoid enclosing a list repeatedly. Imagine what would happen if it were to always enclose the right argument in the expression aœbœc. This would result in (<a) ,<(<b),<c , a two-element list. This is not what we want. A consequence of this is that one must explicitly code the enclosure of the last item if the last value MUST be enclosed, as in x„aœbœ<m (with m„2 3½<a), to get a three-element list.

On the other hand, if we want to, say, catenate <a before each row of ‘m’ then aœm will do whereas (›a),m is required in APL2.

Heterogeneous arrays

Both APLs support arrays containing a mixture of items of different data types, namely characters, numbers and enclosures although they must be explicitly catenated in SAX:

   x„1,'s'                   x„1 's'
   x„1,'s',<'sa'             x„1 's' 'sa'
   x„1,'s','sa'œ2 3          x„1 's' 'sa'(2 3)

Disclosing multiple items at a time

Entire arrays can be disclosed in one fell swoop with only space and maximum rank (127) restrictions:

   2 3 ¦ ½>1œ'dsa'    2 3 ¦ ½œ1'dsa'

In Dyalog there is a “same rank” restriction3. Not in SAX:

4 2 4 4 ¦½>aœbœcœd (RANK ERROR in Dyalog and APL+PLUS II)

Disclosing an array results in another array of the shape of the array disclosed, followed by the largest of the shapes of ALL items disclosed with proper fill elements to fill where necessary.

Atom enclosure/disclosure

A major difference between SAPL and APL2 is in the handling of atoms (simple scalars) upon enclosing them. In SAPL enclosing ANYTHING adds a level of enclosure. Not so in APL2 where an atom can NEVER be enclosed. Thus:

   ~2¦<2         2¦›2

This has several implications as we shall see in a later article.

The disclosure of an atom is permissible in both APLs. Thus

   2¦>2          2¦œ2

Operations on arrays

SAPL offers a few operators to work with (enclosed) arrays. I will discuss only the basics in this article. The next article will cover the subject in more depth (no pun intended).

With, Under, Each (¨)

Although Under is the official name under SAX, people often refer to it as With. APL2 uses the term Each.

With ‘/ ’ this is the most used operator in ALL APLs. It is probably best explained starting with an example:

   ½¨>x          ½¨x

Here we wish to return the shape of each item by first disclosing (each) cell of ‘x’, getting its shape and re-enclosing it, ending with a result of the same shape as the original argument.

In SAPL ¨ is dyadic, allowing for a different right function. The people at APL2 probably felt that since disclose/enclose is used most of the time it was better to make ¨ monadic and include these functions implicitly whereas at I.P.Sharp (where SAPL came from) people tried to be more general.

Some interesting combinations can be made with 2 functions and ¨ although 99% of the time disclose (> ) is used.

An example is multiplication:

A×B is *(µA)+(µB) or A+¨µB

The real APL2 definition is: “for each cell:

  • disclose the cell
  • apply the (ambivalent) function of ¨
  • enclose the cell ”

The real SAPL definition is: “for each cell:

  • apply the right function of ¨ (usually >)
  • apply the left (ambivalent) function of ¨
  • apply the inverse of the right function of ¨ (usually <)”

Or, given f ¨g y, for each cell: “g-1 f g y[j]”.

This, of course, implies that someone in the interpreter department goes over all the suitable right hand argument functions and determines an inverse for each one of them. And it was done. For example, < and > are inverses of each other. ³ is its own inverse.

Dyadic With reviewed

This is the same operator except that f (the left function) is used dyadically4. In more complicated terms, x f ¨ g y is, for each corresponding cell:

g-1 (g x[j]) f (g y[j])”.

Where ‘x’ is the left argument.

Examples:

   p ½¨> q      p ½¨ q    (reshape each)
   t1,¨>t2      t1,¨ t2  (catenate each)

Scalar functions

In APL2, the use of the each operator is assumed for scalar functions (like + ) and derived functions, enclosed or not. There is no need to specify it. Ex:

   x+¨>y        x+y

Moreover, the function is applied recursively so long as the lengths are respected at each (nested) level. This is not possible in SAX.

The reason is that since disclose is implied and that an atom can NEVER be enclosed in APL2 then the each specification can be omitted. Structural functions like take must use each to remove ambiguities.

This is also why +/x and +/¨x mean two different things in APL2. In SAX those would be coded as +¨>/x and +/¨>x respectively.

On (ð)

This operator is similar to with except that the result of each cell is not modified by the inverse of g.

¨ and ð are called composition operators. The only difference between them is in the absence of inverse for the right argument function of ð. For example, using fð > y is the same as doing

   >f¨> y       œf¨ y

This may seem trivial but I will show in a subsequent article, along with another operator, the implications of using this operator.

Other differences

SAPL supports the use of alpha (¸) and omega (¾) as APL identifiers for variables, functions and labels. These were introduced when the ¸/¾ “direct definition” notation was popular (late seventies). The wisdom of their usage in code is debatable but they are available. Also SAPL literature often refers to the left argument as alpha and the right argument as omega. Something to keep in mind.

Complex numbers

These are not available in SAX yet.

Control structures

These are not APL2 but are worth a mention anyway. They do not exist in SAX. In a subsequent article I will show how to emulate them in a control version system that Soliton provides.

Defined operators

SAPL does not allow you to define your own operators.

Error trapping

Similar to Dyalog APL. Even the event numbers are almost the same. A notable difference: the ability to trap value errors “in line” and resume after solving the error. This allows you to easily do “demand paging” of objects.

File operations

In SAPL those are more like APL+Win. System functions don’t start with an ‘F’ ( Œread , not Œ fread ). All file operations return a result, that is val Œreplace tc returns 0 0½0 . This allows someone to use them with operators.

Format by example

SAX allows the usage of a character left argument to the format primitive . This is the same as IBM’s APL2 (not found in Dyalog or APL+Win).

Multiple assignments

It is possible, in both APLs, to “assign with disclose” several values to several variables by using quotes around the variables5:

   'a b'„2 5œ'cxz'         (a b)„(2 5)'czx'

There is a peculiarity using this technique where the number of variables is 1:

   'a b c'„1œ1 2œ1 2 3     ('c' is 1 2 3)
   'b c'„1 2œ1 2 3         (again, 'c' is 1 2 3)
   'c'„œ1 2 3              (now 'c' is <1 2 3, NOT 1 2 3)

This behaviour is found on ALL APLs (also in J!).

Personally, I think this is inconsistent. If there are no quotes (or parentheses) it should be a direct assignment. If there are some it should ALWAYS remove one level of nesting before assigning the value(s).

From

From is an alternative to bracket indexing. The beauty with from is that since it IS a function it does not suffer bracket syntax problems and can be used with operators.

From selects elements along the first dimension. Used with list arguments it selects individual items:

   n{list                 nœ¨›list

Pick (dyadic œ in APL2) and First (monadic ) are not available under SAX. You can still use > with brackets [x] or use from ({):

   x„>atom{list           x„atomœlist

Note that from is Œio independent. It uses an offset instead of an origin dependent position (index). from also allows you to select items from the end of the array by supplying negative offsets. Ex:

   't'=3{a                't'=(3+Œio)œa
   't'^.=0 3{a            't'^.=a[1 4] (in Œio 1)
   'x'=¯2{a               'x'=a[Œio+(½a)+¯2]

Prototyping

In APL2 prototypes are used to fill holes created by \ or . Ex: 2 2¦½†0½›2 2½5 . SAPL has no prototype. If ‘x’ is an item, the expression ‘0\x ’ always returns either 0 for a number, blank for a character or <¼0 for an enclosed object.

Reduce N-wise

IBM’s APL2 allows you to reduce along an axis in sections of length N (N f/ x). Not in SAPL.

Stop, Trace

Those are set using Œstop and Œtrace system functions as in Dyalog APL. IBM’s APL2 uses ‘t‘ ’ and ‘s‘ ’ special name prefixes to do the same.

Take and drop

In SAX these functions work on the leading axis of an array without having to specify them all. Ex (?=½½ m):

   2†m              (2,1‡½m)†m
   2‡m              ((1—½½m)†2)‡m

IBM’s APL2 allows you to use take with one axis as in

   3‡m              3‡[1]m

Scattered indexing

When the argument has a rank higher than 1 then indices should be enclosed:

   (<1 2){d         (›1 2)œ d
   (1 2œ0 1){d      (1 2)(0 1)œd (Œio 0)

But you can pick an entire row (or first dimension elements) by supplying the offset only:

   2 3 ¦ ½ 1 3 { 4 3 ½ ¼12

Swap

This operator merely swaps the arguments to a function. Dyalog uses þ for that. For ex:

   2=7-›9

Unique features in SAX

Here is a list of features not found in any other APL.

Index (iota underbar)

This function returns the index of the first occurrence using epsilon underbar ( º)as primary function:

   2 3¦(4 5½¼20)¥2 2 ½ 8 9 13 14 (Œio 1)

Jot

° is a constant whose value is <¼0 . This is the constant used for overtake and \ with enclosed or heterogeneous arrays.

Nub (monadic take)

This one is not unique to SAX (Dyalog’s equivalent is ž) but it handles higher rank arrays:

   5 2 ¦ † 9 ½ 5 2
   (†m[7½¼3;] ) ¦ m„3 4 ½ 'johnmarypaul'

Nubin (monadic =) , nubsieve (monadic ¬ )

=x is the equivalent of (†x)°.=x for vectors

¬ returns a boolean indicating where each element is first encountered. This is the equivalent of ((v¼v)=¼½v) for vectors. Works on matrices too such that

   1 0 1 0 1 0 ¦ ¬ 2š m

Output redirection

It is possible to send all input/output to a file using Œout 0,tie .

Packages

Packages are unique to SAPL and are very useful. A series of system functions can be used with them, all of which start with Œp as in Œpack , Œpdef , etc. For example, to define variable ‘x’ with objects (variables, functions) ‘a’ and <f> (for example to be stored on file) you would do

   x„Œpack 'a f'

Think of them as static namespaces (found only in Dyalog). You cannot “enter“ a package and run something from within it. For example, if you wish to use its contents in a local environment you must first localize the names. For example, this function <execin> will execute an expression using a package’s contents:

      ’r„exp execin pack;f
   [1]–Œfx>('f',,';',Œpnames pack)œ'Œpdef pack ª r„',exp
      ’

Pass, Stop

These two functions are probably the simplest ever conceived yet very useful.

Stop:

   �Œdl 5                  0 0½Œdl 5
   x„2�y„5                 y„5 ª x„2

Pass:

   ¤x„1 2 3                Œ„x„1 2 3

This last function is more useful than it looks. For example, if space is important and you do not want the interpreter to keep a copy of the argument to a function you could do

   myfn (Œex 'x')¤x

This effectively erases the variable AFTER passing it as an argument to <myfn>. The interpreter is then able to free up the memory space, should the need arise later on (for example after you reassign the argument within <myfn>). I don’t know of any other general way to do this with any other interpreter.

I-beam functions

These are a leftover from the 60’s. If you think you know what they are you probably weren’t there. They are kept for compatibility reasons with SAM (many are no-ops) and will not be explained here.

Less

This one is not unique to SAPL (most APLs handle the vector case) but it accepts higher rank arrays:

   12 7 ¦1 7 12 5 ~ ¼6
   'john' ¦ ,m~m[2 3;]

Raze

This is an interesting monadic function (in terms of raison d’être). Its formal definition is

   ®¨>š

In other words, “working from the first dimension: catenate on the first dimension all items.”

My guess is that this came from a requirement to create in SAPL a function reminiscent of APL2’s monadic ¹ which puts everything in ravel order regardless of structural depth6. Before raze programmers would often need to get text (or numbers) from enclosed lists together, sort of >,¨>/ but SAM wouldn’t allow it resulting in expressions like “, •x” (plus Œfi if numeric) being used resulting in high CPU costs. Hence raze was created. Plus it can be useful.

Shared variables

Œsvs returns the status of a variable

Œsc is used to wait on ANY shared variable event. It can also be assigned a “maximum wait time”.

Œsvn is used to uniquely identify your task when multi-tasking.

System commands

SAX commands are similar to other APLs.

)copy allows the copying of system variables.

)load and )clear allow you to specify initial Œwa. Ex:

)clear 200000000 will give you a workspace of 200M if you have the room!

System functions

Workspace reporting

Various workspace elements (name, stack) can be found using Œws .

Function definition

Œfd can be used to manipulate function representations (similar to Œdef , Œvr in APL+Win).

Of course ISO standard functions like Œcr and Œfx also exist.

System variables

Œps controls the formatting of enclosed arrays. It is a four-elements integer list of

  1. where to position each item in its own box (¯ 1=left, 0=centre, 1=right)
  2. where to position each item in its own box (¯ 1=up, 0=centre, 1=down)
  3. horizontal spacing between items
  4. vertical spacing between items

The default ¯1 ¯1 0 1 fits most cases.

Œsp is used to store values. It stays the same between )loads . Probably one of the most valuable system variables ever created.

10{Œav is the character used as line delimiter. Not 13{Œav. One should exercise caution with this.

Table (monadic comma bar, ®)

This function restructures any structure into a matrix, something like

   (2†(½t),1 1)½t

Table turns a scalar into a 1 by 1, a vector into a 1 column table, anything else into a table.

Task spawning

This is possible in SAX and will be the subject of another article.

Conclusion

SAPL and APL2 are quite different in many respects but each (!) has its own merits. For anyone wishing to delve into the APL/Linux world there is, right now, little choice but to examine SAPL. Personally I am comfortable with both. I found SAPL to be fast, reliable and, with the tools Soliton is providing, a serious product.

The next article will deal with special SAPL operators (hoof, rank, cut, numeric with, }). Another one will deal with multi-task operations. If time permits, another one will talk about intrinsic functions and one of Soliton’s products, logos.

Footnotes

  1. Dyalog and APL+Win do include system functions for APL files operations
  2. The | is necessary only in Dyalog where ¦ can be negative if the structure doesn’t have a constant depth.
  3. I do not know what IBM’s APL2 and APL+Win do here.
  4. This adverb can’t be found in the English dictionary. Yet.
  5. In Dyalog the parentheses are not necessary around the variables leading to potential conflicts.
  6. The design of raze had nothing to do with monadic epsilon in APL2. It is much superior, as it preserves lower-level structure. Some consider the design of monadic epsilon to be largely useless in real applications.

References

  1. Bernecky, R: An Introduction to Function Rank in APL88 Conference Proceedings, ACM SIGAPL Quote Quad 18:2, 1987, pp. 39–43
  2. Bernecky, R and Iverson, K E: Operators and Enclosed Arrays, (APL) Users Meeting 1980, I.P. Sharp Associates Limited

Please direct questions/remarks to danb@dsuper.net.

Dan Baronet
Montreal
Canada

script began 9:18:27
caching off
debug mode off
cache time 3600 sec
indmtime not found in cache
cached index is fresh
recompiling index.xml
index compiled in 0.1954 secs
read index
read issues/index.xml
identified 26 volumes, 101 issues
array (
  'id' => '10000760',
)
regenerated static HTML
article source is 'HTML'
source file encoding is ''
read as 'Windows-1252'
URL: ../../resource/apl2741.zip => trad/v162/../../resource/apl2741.zip
URL: mailto:danb@dsuper.net => mailto:danb@dsuper.net
URL: #footnote1 => art10000760#footnote1
URL: #footnote2 => art10000760#footnote2
URL: #footnote3 => art10000760#footnote3
URL: #footnote4 => art10000760#footnote4
URL: #footnote5 => art10000760#footnote5
URL: #footnote6 => art10000760#footnote6
URL: mailto: => mailto:
completed in 0.2222 secs