Defined function (traditional): Difference between revisions

From APL Wiki
Jump to navigation Jump to search
Line 32: Line 32:
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.
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]] also allows dynamic localisation of names while a tradfn is running.<ref>[[Dyalog Ltd.]] Language Reference Guide. [https://help.dyalog.com/latest/#Language/System%20Functions/shadow.htm Shadow Name].</ref>
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 two extensions to this:


# Dynamic localisation of names while a tradfn is running.<ref>[[Dyalog Ltd.]] Language Reference Guide. [https://help.dyalog.com/latest/#Language/System%20Functions/shadow.htm Shadow Name].</ref>
# The declaration of additional local names on separate lines following the header line.<ref>[[Dyalog Ltd.]] Programming Reference Guide.  [https://help.dyalog.com/latest/#Language/Defined%20Functions%20and%20Operators/Locals%20Lines.htm Locals Lines].</ref>
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.
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.


Some dialects have let the header syntax explicitly specify that a function is [[ambivalent]] by enclosing the left argument name in curly braces (for example <source lang=apl inline>result←{left} Function right</source>) while others treat all functions that specify a left argument name as ambivalent and leave it up to the programmer to check for the presence of a value.
=== Dyalog APL extensions ===
In addition to the two above-mentioned extensions for localising names, Dyalog APL adds a few features to tradfn.<ref>[[Dyalog Ltd.]] Programming Reference Guide. [https://help.dyalog.com/latest/#Language/Defined%20Functions%20and%20Operators/Model%20Syntax.htm Model Syntax].</ref>


Some dialects allow a tradfn to return a function value as result. The returned function will replace the function and its arguments (if any) in the calling expression:
The the header syntax can explicitly specify that a function is [[ambivalent]] by enclosing the left argument name in curly braces (for example <source lang=apl inline>result←{left} Function right</source>). 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.
 
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:
<source lang=apl>
<source lang=apl>
     ∇  Fn←Apply name       
     ∇  Fn←Apply name       
Line 54: Line 59:
12
12
</source>
</source>
A tradfn can be declared as shy, that is, it exhibits the same behaviour as an assignment, in that by default, no result is printed when the function terminates, but attempting to use the result still succeeds. This declaration is done by putting curly braces around the result name (for example <source lang=apl inline>{result}←left Function right</source>).
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/Namelists.htm Namelists].</ref>


== A+ ==
== A+ ==

Revision as of 12:06, 14 July 2020

A user-defined function (or tradfn, 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 describe functions have appeared, with J and K rejecting function definition in favor of anonymous function description. Beginning in the 2010s Dyalog-based APL dialects including ngn/apl, dzaima/APL, and APL\iv have removed function definition in favor of dfns.

In many dialects the function header syntax of defined functions is adapted to allow user-defined operators as well.

Examples

Ambivalent function with optional left argument and one local variable (Dyalog APL):

∇ res←{left} AddMult2 right;local
  :If 0=⎕NC'left'
      left←0      ⍝ define variable "left" with value 0 if it's not defined already
  :EndIf
  local←left+right
  res←2×local
∇

GNU APL allows functions and operators accept an axis argument:[1]

∇ 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

Representations

The canonical representation form is equivalent to what the user would type into the line editor to define the function. An alternative representation consists of the entire session log transcript after having such a definition has been made. A tradfn operator can also be called a tradop (pronounced "trad op").

Properties

Tradfns allow both functional and procedural programming, and are essential for object-oriented programming. They support a full set of keywords 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 two extensions to this:

  1. Dynamic localisation of names while a tradfn is running.[2]
  2. The declaration of additional local names on separate lines following the header line.[3]

Tradfns cannot be nested but can contain dfns. A tradfn can dynamically create another tradfn by "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 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 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

In addition to the two above-mentioned extensions for localising names, Dyalog APL adds a few features to tradfn.[4]

The the header syntax can explicitly specify that a function is ambivalent by enclosing the left argument name in curly braces (for example result←{left} Function right). 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.

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:

    ∇  Fn←Apply name       
[1]    :If name≡'plus'     
[2]        Fn←+            
[3]    :ElseIf name≡'times'
[4]        Fn←×            
[5]    :EndIf              
    ∇                      
       3(Apply'plus')4
7
       3(Apply'times')4
12

A tradfn can be declared as shy, that is, it exhibits the same behaviour as an assignment, in that by default, no result is printed when the function terminates, but attempting to use the result still succeeds. This declaration is done by putting curly braces around the result name (for example {result}←left Function right).

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.[5]

A+

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.

Comparison to dfns

Wikipedia has a comparison of dfns versus tradfns.

External links

Tutorials

Documentation

References

  1. 3.2 Axis argument in defined functions – GNU APL Manual
  2. Dyalog Ltd. Language Reference Guide. Shadow Name.
  3. Dyalog Ltd. Programming Reference Guide. Locals Lines.
  4. Dyalog Ltd. Programming Reference Guide. Model Syntax.
  5. Dyalog Ltd. Programming Reference Guide. Namelists.


APL syntax [edit]
General Comparison with traditional mathematicsPrecedenceTacit programming (Train, Hook, Split composition)
Array Numeric literalStringStrand notationObject literalArray notation (design considerations)
Function ArgumentFunction valenceDerived functionDerived operatorNiladic functionMonadic functionDyadic functionAmbivalent functionDefined function (traditional)DfnFunction train
Operator OperandOperator valenceTradopDopDerived operator
Assignment MultipleIndexedSelectiveModified
Other Function axisBracket indexingBranchStatement separatorQuad nameSystem commandUser commandKeywordDot notationFunction-operator overloadingControl structureComment