Function: Difference between revisions
Line 25: | Line 25: | ||
The traditional way of defining functions in APL, and the most common way to define functions currently, is to create a [[defined function]], which consists of a sequence of APL statements. This is the only way to create a [[niladic function]], although not all ways to define a function support creating niladic functions. There are three major families of function definition: | The traditional way of defining functions in APL, and the most common way to define functions currently, is to create a [[defined function]], which consists of a sequence of APL statements. This is the only way to create a [[niladic function]], although not all ways to define a function support creating niladic functions. There are three major families of function definition: | ||
* [[Direct definition]], introduced by [[Ken Iverson]] in [[A Programming Language]] but rarely implemented. Direct definition might be considered a kind of APL [[wikipedia:pseudocode|pseudocode]]. | * [[Direct definition]], introduced by [[Ken Iverson]] in [[A Programming Language]] but rarely implemented. Direct definition might be considered a kind of APL [[wikipedia:pseudocode|pseudocode]]. | ||
* [[Tradfn]]s (often simply called "defined functions"), introduced by [[APL\360]]. In these functions, a header line describes the way the function is called and the result is placed in a variable whose name is given in the header. | * [[Tradfn]]s (often simply called "defined functions"), introduced by [[APL\360]]. In these functions, a [[function header|header]] line describes the way the function is called and the result is placed in a variable whose name is given in the header. | ||
* [[dfn]]s, developed by [[John Scholes]] and introduced in [[Dyalog APL]]. In a dfn, the arguments are given the fixed names <source lang=apl inline>⍺</source> and <source lang=apl inline>⍵</source>, and the result of the first non-assignment statement is returned. | * [[dfn]]s, developed by [[John Scholes]] and introduced in [[Dyalog APL]]. In a dfn, the arguments are given the fixed names <source lang=apl inline>⍺</source> and <source lang=apl inline>⍵</source>, and the result of the first non-assignment statement is returned. | ||
{{APL syntax}} | {{APL syntax}} |
Revision as of 10:28, 13 March 2020
In APL syntax, a function applies to array arguments to produce an array result (although some APLs allow functions to return other syntactic elements). Unlike many programming languages which use parentheses or brackets for function calls, function application in APL is written simply by writing the function next to its arguments. Functions may be primitive functions, derived functions (including trains), or defined functions. They can be used as operands to operators; in early APLs operands were always functions, but nearly all modern APLs allow array operands, for example to the Power operator.
A key feature distinguishing APL from functional programming languages such as Lisp is that APL functions are not first class objects: they cannot be passed directly as arguments to other functions like arrays. Instead, functions might be considered "second class" objects while operators are "third class" and hyperators, if present, are "fourth class" or more. In a few APLs, most prominently A+, a mechanism is provided to pass functions as arguments, making functions first class if a special function call syntax is used.
Function valence
Functions may take zero, one, or two arguments when applied (to pass more arguments, combine them into a single list argument). Which of these possibilities applies is known as the function's valence:
- A niladic function takes no arguments: it is evaluated immediately when execution reaches it.
- A monadic function or prefix function takes one argument on its right.
- A dyadic function or infix function takes two arguments: a left argument and a right argument.
The monadic and dyadic cases are distinguished during execution by checking to see whether there is an array to the function's left, but there is no way to determine from context whether a function should be niladic. It must be a property of the function itself. Thus functions are divided into niladic functions, which are always evaluated immediately with no arguments, and non-niladic functions, which may be monadic or dyadic. Niladic functions lack some of the properties expected of functions—they cannot be passed as operands and cannot be produced as derived functions—so they are often considered to be a special kind of syntactic element rather than a function, and "function" sometimes indicates a non-niladic function.
APL's syntax allows a non-niladic function to be called either monadically or dyadically. However, one or both of these cases may give a SYNTAX ERROR regardless of the argument. In this case the function is called
- Monadic if a one-argument call can be valid but a two-argument call cannot
- Dyadic if only a two-argument call can be valid
- Ambivalent if both cases are possible
- no name, if neither case is possible (for instance
3∘+∘4
)
while the last case can be produced, it is unlikely to be useful, and almost never discussed.
Function definition
- Main article: Function styles
Every APL comes with primitive functions, and almost always system functions, which are defined by the language. Derived functions can also be created by applying operators to operands. 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 defined function. Function assignment became more common in the 1980s, and after the advent of tacit programming in the 90s it is present in all new APLs.
The traditional way of defining functions in APL, and the most common way to define functions currently, is to create a defined function, which consists of a sequence of APL statements. This is the only way to create a niladic function, although not all ways to define a function support creating niladic functions. There are three major families of function definition:
- Direct definition, introduced by Ken Iverson in A Programming Language but rarely implemented. Direct definition might be considered a kind of APL pseudocode.
- Tradfns (often simply called "defined functions"), introduced by APL\360. In these functions, a header line describes the way the function is called and the result is placed in a variable whose name is given in the header.
- dfns, developed by John Scholes and introduced in Dyalog APL. In a dfn, the arguments are given the fixed names
⍺
and⍵
, and the result of the first non-assignment statement is returned.