4,509
edits
m (Marshall moved page Tradfn to Defined function over redirect: See talk page) |
m (Text replacement - "</source>" to "</syntaxhighlight>") |
||
(42 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
'' | :''This page is about the function form typically written with the Del (<syntaxhighlight lang=apl inline>∇</syntaxhighlight>) character. See [[Function styles]] for an overview of all forms; in particular [[dfn]]s are considered a type of defined function in [[Dyalog APL]] and [[GNU APL]].'' | ||
A '''user-defined function''' (or '''tradfn''', pronounced "trad fun", for "traditional function", in [[Dyalog APL]]) is a function defined using a header that includes the function's name. Introduced in [[APL\360]], function definition was universally supported by APL dialects for much of the language's [[history]], and is still commonly used in mainstream APLs. Since the 1990s other ways to [[Function styles|describe functions]] have appeared, with [[J]] and [[K]] rejecting function definition in favor of [[anonymous function]] description. | |||
{{Anchor|Representations}}The canonical representation form is equivalent to what the user would type into the [[line editor]] to define the function.<ref>[[Dyalog Ltd.]] Programming Reference Guide. [https://help.dyalog.com/latest/#Language/System%20Functions/cr.htm Canonical Representation].</ref> An alternative representation consists of the entire [[session]] log transcript, including [[Del]]s (<syntaxhighlight lang=apl inline>∇</syntaxhighlight>) and line numbers, after having such a definition has been made.<ref>[[Dyalog Ltd.]] Language Reference Guide. [https://help.dyalog.com/latest/#Language/System%20Functions/vr.htm Vector Representation].</ref> However, it should be noted that the <syntaxhighlight lang=apl inline>∇</syntaxhighlight>s are not part of the definition. Indeed, if using the [[Fix Definition]] (<syntaxhighlight lang=apl inline>⎕FX</syntaxhighlight>) [[system function]] to define the function, Dels need not (or must not, depending on implementation) be included. | |||
One of the most noticeable differences from dfns is that tradfns must declare their locals, because assignments are global by default. The declaration is done in a header line which also determines the function's name and calling syntax. Tradfns cannot be nested | Beginning in the 2010s [[Dyalog]]-based APL dialects including [[ngn/apl]], [[dzaima/APL]], and [[APL\iv]] have removed function definition in favor of [[dfn]]s. Wikipedia has a comparison of [[Wikipedia:Direct_function#Dfns_versus_tradfns|dfns versus tradfns]]. | ||
In many dialects the function header syntax of defined functions is adapted to allow user-defined [[operator]]s as well. A tradfn operator can also be called a '''tradop''' (pronounced "trad op"), parallel to how a "dfn" operator can be called a ''dop''. | |||
== Examples == | |||
=== Basics === | |||
A simple [[dyadic function]]: | |||
<syntaxhighlight lang=apl> | |||
∇ r←l Tradfn r | |||
⍝ ...do something | |||
r←l r | |||
∇ | |||
</syntaxhighlight> | |||
{{Works in|[[Dyalog APL]], [[APL2]], [[GNU APL]], [[NARS2000]], [[APLX]], and every older APL from [[APL\360]]}} | |||
=== Semi-colons === | |||
Assignments are global by default. To keep a name local, it must be mentioned in the header, separated from the rest of the header by a semi-colon: | |||
<syntaxhighlight lang=apl> | |||
∇ r←l Tradfn r;intermediate | |||
intermediate←l r | |||
r←intermediate intermediate | |||
∇ | |||
</syntaxhighlight> | |||
{{Works in|[[Dyalog APL]], [[APL2]], [[GNU APL]], [[NARS2000]], [[APLX]], and every older APL from [[APL\360]]}} | |||
=== Braces === | |||
An [[ambivalent function]] with an optional left argument, a conditional [[control structure]], one local variable, and a [[#Shyness|shy]] result: | |||
<syntaxhighlight lang=apl> | |||
∇ {res}←{left} AddMult2 right;local | |||
:If 0=⎕NC'left' ⍝ if variable "left" is not defined already | |||
left←0 | |||
:EndIf | |||
local←left+right | |||
res←2×local | |||
∇ | |||
AddMult2 3 ⍝ result is "shy" | |||
⎕←AddMult2 3 ⍝ coerce display of result | |||
6 | |||
1 AddMult2 3 ⍝ result is "shy" | |||
10×1 AddMult2 3 ⍝ use result anyway | |||
80 | |||
</syntaxhighlight> | |||
{{Works in|[[Dyalog APL]]}} | |||
=== Brackets === | |||
[[GNU APL]] allows functions and operators to accept an [[function axis|axis]] argument:<ref>[[GNU APL community]]. GNU APL Info Manual. [https://www.gnu.org/software/apl/apl.html#Section-3_002e2 Axis argument in defined functions].</ref> | |||
<syntaxhighlight lang=apl> | |||
∇ Z←Average[X] B | |||
Z←(+/[X]B) ÷ (⍴B)[X] | |||
∇ | |||
Average[1] 5 5⍴⍳25 | |||
11 12 13 14 15 | |||
Average[2] 5 5⍴⍳25 | |||
3 8 13 18 23 | |||
</syntaxhighlight> | |||
{{Works in|[[GNU APL]]}} | |||
=== Operators === | |||
A [[monadic operator]] and a [[dyadic operator]], both deriving [[monadic function]]s: | |||
<syntaxhighlight lang=apl> | |||
∇ res←(Function SELF) right | |||
res←right Function right | |||
∇ | |||
×SELF 1 2 3 4 5 | |||
1 4 9 16 25 | |||
∇ res←(FunctionF HOOK FunctionG) right | |||
res←right FunctionF FunctionG right | |||
∇ | |||
÷HOOK|2 0 ¯7 | |||
1 1 ¯1 | |||
</syntaxhighlight> | |||
{{Works in|[[Dyalog APL]], [[APL2]], [[GNU APL]], [[NARS2000]], [[APLX]]}} | |||
A monadic operator and a dyadic operator, both deriving [[dyadic function]]s: | |||
<syntaxhighlight lang=apl> | |||
∇ res←left (Function SWAP) right | |||
res←right Function left | |||
∇ | |||
3 2 -SWAP 10 | |||
7 8 | |||
∇ res←left (FunctionF OVER FunctionG) right | |||
res←(FunctionG left) FunctionF (FunctionG right) | |||
∇ | |||
2 ¯7 2+OVER|¯3 1 4 | |||
5 8 6 | |||
</syntaxhighlight> | |||
{{Works in|[[Dyalog APL]], [[APL2]], [[GNU APL]], [[NARS2000]], [[APLX]]}} | |||
== Properties == | |||
Tradfns allow both functional and procedural programming, and are essential for [[object-oriented programming]]. They support a full set of [[keyword]]s for flow control and object declarations. | |||
One of the most noticeable differences from dfns is that tradfns must declare their locals, because assignments are global by default. The declaration is done in a header line which also determines the function's name and calling syntax. [[Dyalog APL]] adds a handful of extensions this (see below). | |||
Tradfns cannot be nested but ''can'' contain dfns. A tradfn can dynamically create another tradfn by [[Fix|"fixing"]] its source, and if the function thus created has a name which has been localised, the inner function will only exist the scope of the outer function. Nested functions are less necessary due to tradfns using [[wikipedia:dynamic scoping|dynamic scoping]] as opposed to the lexical scoping of dfns. In other words, a tradfn can "see" locals of its caller. | |||
A tradfn can be [[niladic function|niladic]] which causes it to behave syntactically like an array. However, every time its name is referenced, it will run to create a result (if any). Such methods are often used to return a cache or as an entry point for the user. | A tradfn can be [[niladic function|niladic]] which causes it to behave syntactically like an array. However, every time its name is referenced, it will run to create a result (if any). Such methods are often used to return a cache or as an entry point for the user. | ||
=== Dyalog APL extensions === | |||
Dyalog APL's tradfns are enhanced in various ways compared to most other dialects.<ref>[[Dyalog Ltd.]] Programming Reference Guide. [https://help.dyalog.com/latest/#Language/Defined%20Functions%20and%20Operators/TradFns/Model%20Syntax.htm Model Syntax].</ref> | |||
==== Dynamic localisation ==== | |||
Names can be localised dynamically, while a tradfn is running, using the [[Shadow Name]] (<syntaxhighlight lang=apl inline>⎕SHADOW</syntaxhighlight>) [[system function]].<ref>[[Dyalog Ltd.]] Language Reference Guide. [https://help.dyalog.com/latest/#Language/System%20Functions/shadow.htm Shadow Name].</ref> | |||
<syntaxhighlight lang=apl> | |||
name←1 2 3 | |||
∇ res←Dummy | |||
⎕SHADOW'name' | |||
name←42 | |||
res←name | |||
∇ | |||
Dummy | |||
42 | |||
name | |||
1 2 3 | |||
</syntaxhighlight>{{Works in|[[Dyalog APL]]}} | |||
==== Locals lines ==== | |||
Additional local names can also be declared on separate lines following the header line:<ref>[[Dyalog Ltd.]] Programming Reference Guide. [https://help.dyalog.com/latest/#Language/Defined%20Functions%20and%20Operators/TradFns/Locals%20Lines.htm Locals Lines].</ref> | |||
<syntaxhighlight lang=apl> | |||
name←1 2 3 | |||
∇ res←Dummy | |||
;name | |||
name←42 | |||
res←name | |||
∇ | |||
Dummy | |||
42 | |||
name | |||
1 2 3 | |||
</syntaxhighlight>{{Works in|[[Dyalog APL]]}} | |||
==== Explicit ambivalence ==== | |||
The the header syntax can explicitly specify that a function is [[ambivalent]] by enclosing the left argument name in curly braces (for example <syntaxhighlight lang=apl inline>result←{left} Function right</syntaxhighlight>). Others dialects treat all functions that declare a left argument name as ambivalent and leave it up to the programmer to check for the presence of a value. | |||
==== Function results ==== | |||
A tradfn can return a function value as result. The returned function will replace the function and its arguments (if any) in the calling expression: | |||
<syntaxhighlight lang=apl> | |||
∇ Fn←Apply name | |||
:If name≡'plus' | |||
Fn←+ | |||
:ElseIf name≡'times' | |||
Fn←× | |||
:EndIf | |||
∇ | |||
3(Apply'plus')4 | |||
7 | |||
3(Apply'times')4 | |||
12 | |||
</syntaxhighlight>{{Works in|[[Dyalog APL]]}} | |||
==== Shyness ==== | |||
By default, functions in APL will print their result to the session log even without using <syntaxhighlight lang=apl inline>⎕←</syntaxhighlight> unless their results are shy. Shy results are declared by putting curly braces around the result name (for example <syntaxhighlight lang=apl inline>{result}←left Function right</syntaxhighlight>). Assignment (<syntaxhighlight lang=apl inline>name←array</syntaxhighlight>) exhibits the same behaviour as a shy function in that, by default, no result is printed when the function terminates, but attempting to use the result still succeeds. | |||
==== Namelists ==== | |||
The right argument and the result can be a name list instead of single name. The interpreter will unpack the right argument when the function is called, and collect the result when the function returns.<ref>[[Dyalog Ltd.]] Programming Reference Guide. [https://help.dyalog.com/latest/#Language/Defined%20Functions%20and%20Operators/TradFns/Namelists.htm Namelists].</ref> | |||
<syntaxhighlight lang=apl> | |||
∇ (c b a)←Rev(a b c) | |||
∇ | |||
Rev 1 2 3 | |||
3 2 1 | |||
</syntaxhighlight>{{Works in|[[Dyalog APL]]}} | |||
=== A+ differences=== | |||
[[A+]] uses a reworked style of function and operator definition than maintains the principle of a header that matches the way the function will be used, but differs in many details: | |||
* The result name is not included in the header; instead, the result of the last executed statement is returned (and so functions that do not return a result cannot be defined). | |||
* The header is separated from the body with a colon, and the body of a multi-line function is enclosed in curly braces. | |||
* Functions have lexical scope. Variables assigned are local by default, and can be made global by enclosing their names in parentheses when assigning. | |||
==External links== | ==External links== | ||
===Tutorials=== | ===Tutorials=== | ||
* APL Cultivation: [https://chat.stackexchange.com/rooms/52405/conversation/lesson-31-tradfns tradfns] | * APL Cultivation: [https://chat.stackexchange.com/rooms/52405/conversation/lesson-31-tradfns tradfns] | ||
* Bernard Legrand. [https://www.dyalog.com/uploads/documents/MasteringDyalogAPL.pdf#page=176 Mastering Dyalog APL (page 176)]. [[Dyalog Ltd]]. November 2009. | |||
=== Documentation === | === Documentation === | ||
* [ | * Dyalog: [https://help.dyalog.com/latest/#Language/Introduction/Functions.htm Functions], [https://help.dyalog.com/latest/#Language/Introduction/Operators.htm Operators] | ||
* [http://microapl.com/apl_help/ch_020_010_070.htm | * APLX: [http://microapl.com/apl_help/ch_020_010_070.htm User-defined Functions], [http://microapl.com/apl_help/ch_020_010_090.htm User-defined Operators] | ||
{{APL syntax}}[[Category:Kinds of functions]][[Category:Defining functions]] | |||
=== References === | |||
<references/> | |||
{{APL syntax}} | |||
[[Category:Kinds of functions]] | |||
[[Category:Defining functions]] |