Function styles
In APL's history many ways to create functions and operators (as opposed to using existing primitive and system functions) have been introduced, with each APL dialect supporting one or more of these styles. The three major branches are defined functions, which use a header declaring the function and argument names, anonymous functions such as dfns, which also consist of a list of statements but have no header and use fixed argument names, and tacit functions, which are created by manipulating existing functions with no reference to arguments.
Defined functions
- Main article: Defined function
Early APLs such as APL\360 provided only one way for a user to make a named function, which was called a defined function. Later APLs have sometimes offered more specific terminology to distinguish this type of definition from other types: when writing about SHARP APL, Ken Iverson called it the "canonical form",[1] and John Scholes named these functions "tradfns" to contrast with dfns in Dyalog APL. Most APLs with this type of function syntax share almost all details of function implementation, although A+ has a very different header-based function definition that is not discussed here.
A defined function is written with a header which gives the function, argument, and result names with a syntax matching the way a function is called. The operation of the function is then defined in the function body, which should assign the result if there is one. Because arguments and results are written out explicitly, this style allows omitting all arguments to define a niladic function, or omitting the result.
In a defined function, variables created are global by default. Local variables, which use dynamic scoping, must be declared in the header.
Direct definition
- Main article: Direct definition (notation)
Although the term "direct definition" has been used in various ways by different authors, one of the more notable uses is that described by Ken Iverson in Elementary Functions, published 1974.[2] Initially called "formal function definition", this style was called "direct definition" by Iverson and others at IPSA when they used it to describe new language features in SHARP APL.[1] It was never implemented as part of SHARP APL, although utilities to translate it to SHARP's function definition, or the "canonical form", were provided. Iverson's direct definition required the name of the function like existing defined functions, but not those of the arguments: instead the left argument was named ⍺
and the right argument ⍵
.
Various implementations and proposals changed direct definition into an anonymous function syntax, typically modifying other details in the process. The direct definition operator ∇
discussed by Iverson and implemented in NARS created a function from source code strings, and eventually led to J's explicit definition operator :
. John Bunda proposed a syntax using curly braces[3] while J. Philip Benkard proposed another using parentheses.[4] This line of investigation eventually found success in John Scholes' dfns, which shared the use of ⍺
and ⍵
with direct definition, as well as the general concept of :
indicating a condition, but differed in many details.
Anonymous functions
In the 1990s array language designers began experimenting with forms that allowed a function to be created without ever giving it a name, often influenced by Lisp's lambda expressions. Such anonymous forms appeared in several languages, including an early but less influential form in NARS:
- 1981: NARS defines its own type of direct definition written with two strings joined by the operator
∇
- 1990: J uses the
:
operator for "explicit definition"; in 2020 it adds a more dfn-like direct definition syntax with doubled curly braces - 1994: K's functions are written with curly braces
- 1996: Dyalog APL adds dfns, another kind of functions written with curly braces
Although tacit functions also are unnamed when created, "anonymous function" refers to an explicit anonymous function, that is, one that has a function body referring to arguments but no header defining its name.
By far the most influential of these definitions within APL has been Dyalog's dfns, which have also been included in most APLs created since: NARS2000 includes them in addition to traditional function definition, and GNU APL includes a limited variant. Dialects such as ngn/apl, APL\iv, dzaima/APL, and RAD use only dfns, with no other explicit function style.
The varieties of anonymous function definition given above can be grouped into two categories. NARS and J have an operator-based definition, where an operator is applied to arrays with the function defined being the result (J's version also uses the special right operand 0 to indicate that a multi-line definition follows). K and Dyalog have syntax-based anonymous functions, which use dedicated syntax rules like older defined functions do in Dyalog.
Tacit functions
- Main article: Tacit programming
Another kind of function which can be created by the programmer are tacit functions, so named because they do not include any mention of their arguments, leaving them unsaid. Languages with tacit functions call the other types of functions, which do refer to arguments as part of a function body, "explicit" functions. Tacit functions are created as values: derived functions and trains are two kinds of tacit function. For example +/
, Plus Reduce, is a derived function that can be created in any APL. However, early APLs usually did not allow assigning a name to such functions: the only ways to call them were to write the function out explicitly and to define an equivalent explicit function. Function assignment, allowing derived functions to be used directly, began to be supported in the 1980s.
References
- ↑ 1.0 1.1 Ken Iverson. SATN-36: Direct Definition. 1980-04-20.
- ↑ Ken Iverson. Elementary Functions chapter 10. IBM. 1974.
- ↑ John Bunda. APL function definition notation. APL Quote Quad Volume 17, Issue 4. 1987-01-01.
- ↑ J. Philip Benkard. Nonce functions at APL90.