Precedence
In APL, there is no precedence hierarchy within a given name class — the role which a semantic object fulfils — for example, Arrays, Functions, and Operators have consistent binding strength and scope. Therefore, the functions ÷
, ×
, *
, +
are evaluated in a precisely identical fashion, unlike other languages, which choose to follow the traditional mathematical rules for order of operations.
Details
Relative precedence differs between name classes. For example, an operator binds tighter to its operand than a function does to its argument. These differences can be enumerated in a table, like the following simplified example of binding strengths:
When ↓ is adjacent to → | Array | Function | Monadic operator |
---|---|---|---|
Array | 4 | 2 | 3 |
Function | 1 | 3 | |
Dyadic operator | 3 | 3 |
In this example, Array–Array binds strongest, to produce a new array through stranding. Operator–Operand (Array or Function) binding follows, to produce a derived function (note that Dyadic operator binds its right operand, deriving a monadic operator). Finally, functions are applied to their arguments. Functions have long right scope and short left scope, that is, everything to the right of a function (up until the statement or bracket end) is taken as a right argument, while only an immediately adjacent array on the left becomes the left argument to its left (and thus, functions are said to evaluate right to left). It is therefore often necessary to parenthesise left arguments. Operators have long left scope and short right scope, that is, the entire function phrase to the left of an operator becomes its left operand, while only the right-hand function to the immediate right can become the right operand (of a dyadic operator). It is therefore often necessary to parenthesise right operands.
Minor differences exist in binding strengths between APL implementations. For example, in APL2 and its derivatives (e.g. APLX and GNU APL), Operator–Array binds stronger than Array–Array, which means that a literal vector right-operand must be parenthesised. This is opposed to Dyalog APL and its derivatives (e.g. ngn/apl and dzaima/APL) where stranding is stronger than operand binding, which means that adjacent operands and arguments must be separated by parenthesis or function application. APL2 et al. also have bracket indexing bind stronger than stranding, while the opposite is true in Dyalog APL et al. Such differences can be illustrated with the following examples:
GNU APL | Dyalog APL |
---|---|
⊖⍤2 2 3 4⍴⍳23 |
(⊖⍤2) 2 3 4⍴⍳23 or ⊖⍤2 ⊢ 2 3 4⍴⍳23
|
1 2 3 4⊖⍤(1 2) 2 3 4⍴⍳23 |
1 2 (⊖⍤0 2) 2 3 4⍴⍳23 or 1 2⊖⍤0 2 ⊢ 2 3 4⍴⍳23
|
(1 2 3)(4 5 6)[2](7 8 9) |
(1 2 3)((4 5 6)[2])(7 8 9)
|
((1 2 3)(4 5 6))[2](7 8 9) |
(1 2 3)(4 5 6)[2](7 8 9)
|
See also
External links
Documentation
Other
- dfns workspace: parse — Bunda-Gerth parsing
- Jim Brown: A development of APL2 syntax