Difference between revisions of "User-Defined Functions/Operators/Hyperators"

From NARS2000
Jump to navigationJump to search
 
Line 52: Line 52:
 
<apll>∇ Z←(LO mop) R</apll>
 
<apll>∇ Z←(LO mop) R</apll>
  
<p>a del symbol in the body of the operator is a shorthand for <apll>(LO mop)</apll>, and for a dyadic operator whose header looks like</p>
+
<p>a <apll>∇</apll> in the body of the operator is a shorthand for <apll>(LO mop)</apll>, and for a dyadic operator whose header looks like</p>
  
 
<apll>∇ Z←(LO dop RO) R</apll>
 
<apll>∇ Z←(LO dop RO) R</apll>
  
<p>a del in the body of the operator is a shorthand for <apll>(LO dop RO)</apll>, etc.</p></li>
+
<p>a <apll>∇</apll> in the body of the operator is a shorthand for <apll>(LO dop RO)</apll>, etc.</p></li>
  
       <li><p>Within a recursive user-defined operator/hyperator, two del symbols (<apll>∇∇</apll>) refer to the operator/hyperator name with bound hyperand(s), but no bound operands.  For example, in the monadic operator case above in the body of the operator, <apll>∇∇</apll> refers to <apll>mop</apll>, and in the dyadic operator case above, <apll>∇∇</apll> refers to <apll>dop</apll>, and in both cases without having to know the actual name.</p></li>
+
       <li><p>Within a recursive user-defined operator/hyperator, two del symbols (<apll>∇∇</apll>) refer to the operator/hyperator name with bound hyperand(s), but no bound operands.  For example, in the monadic operator case above in the body of the operator, <apll>∇∇</apll> refers to <apll>mop</apll>, and in the dyadic operator case above, <apll>∇∇</apll> refers to <apll>dop</apll>, and in both cases without having to know the actual name.  Within a recursive user-defined hyperator whose header looks like <apll>∇ Z←L (LO (LH mhdo) RO) R</apll>, <apll>∇∇</apll> refers to <apll>(LH mhdo)</apll>.</p></li>
 
       <li><p>Within a recursive user-defined hyperator, three del symbols (<apll>∇∇∇</apll>) refer to the hyperator name with no bound operands/hyperands.</p></li>
 
       <li><p>Within a recursive user-defined hyperator, three del symbols (<apll>∇∇∇</apll>) refer to the hyperator name with no bound operands/hyperands.</p></li>
 
     </ul>
 
     </ul>
Line 65: Line 65:
 
   <li><p>'''User-defined Operators'''</p>
 
   <li><p>'''User-defined Operators'''</p>
 
     <ul>
 
     <ul>
       <li><p>A user-defined <font color=purple><b>operator</b></font> is distinguished from a user-defined <b>function</b> by its <font color=purple><b>header</b></font>, such that in the place where the function <font color=purple><b>name</b></font> normally appears, it contains a left operand name, an operator name, and an optional right operand name (for dyadic operators only), all enclosed in <font color=purple><b>a single set of parentheses</b></font>.  For example, the operator part of the header for a monadic operator looks like <font color=purple><b><apll>(LO MonOp)</apll></b></font>, and a dyadic operator looks like <font color=purple><b><apll>(LO DydOp RO)</apll></b></font> where <apll>LO</apll> and <apll>RO</apll> are the left and right operands (a function, variable, or jot).</p>
+
       <li><p>A user-defined <font color=purple><b>operator</b></font> is distinguished from a user-defined <b>function</b> by its <font color=purple><b>header</b></font>, such that in the place where the function <font color=purple><b>name</b></font> normally appears, it contains a left operand name, an operator name, and an optional right operand name (for dyadic operators only), all enclosed in <font color=purple><b>a single set of parentheses</b></font>.  For example, the operator part of the header for a monadic operator looks like <font color=purple><b><apll>(LO mop)</apll></b></font>, and a dyadic operator looks like <font color=purple><b><apll>(LO dop RO)</apll></b></font> where <apll>LO</apll> and <apll>RO</apll> are the left and right operands (a function, variable, or jot).</p>
 
<font color=purple><b>
 
<font color=purple><b>
<p>Both types of user-defined operators may be called monadically or dyadically, as in</p>
+
<p>Both types of user-defined operators may be called niladically, monadically or dyadically, as in</p>
  
 
<table border="1" cellpadding="5" cellspacing="0" summary="">
 
<table border="1" cellpadding="5" cellspacing="0" summary="">
 
<tr>
 
<tr>
 
   <td></td>
 
   <td></td>
 +
  <td align="center">Niladic derived function</td>
 
   <td align="center">Monadic derived function</td>
 
   <td align="center">Monadic derived function</td>
 
   <td align="center">Dyadic derived function</td>
 
   <td align="center">Dyadic derived function</td>
 
</tr>
 
</tr>
 +
 
<tr>
 
<tr>
 
   <td>Monadic operator</td>
 
   <td>Monadic operator</td>
   <td><apll>∇ Z←(LO MonOp) R</apll></td>
+
   <td><apll>∇ Z←(LO mop)</apll></td>
   <td><apll>∇ Z←L (LO MonOp) R</apll></td>
+
  <td><apll>∇ Z←(LO mop) R</apll></td>
 +
   <td><apll>∇ Z←L (LO mop) R</apll></td>
 
</tr>
 
</tr>
 +
 
<tr>
 
<tr>
 
   <td>Dyadic operator</td>
 
   <td>Dyadic operator</td>
   <td><apll>∇ Z←(LO DydOp RO) R</apll></td>
+
   <td><apll>∇ Z←(LO dop RO)</apll></td>
   <td><apll>∇ Z←L (LO DydOp RO) R</apll></td>
+
  <td><apll>∇ Z←(LO dop RO) R</apll></td>
 +
   <td><apll>∇ Z←L (LO dop RO) R</apll></td>
 
</tr>
 
</tr>
 
</table>
 
</table>
Line 93: Line 98:
 
<p>A header using all these features might look like</p>
 
<p>A header using all these features might look like</p>
  
<p><apll>∇ {(Z<sub>1</sub> Z<sub>2</sub>)}←{(L<sub>1</sub> L<sub>2</sub> L<sub>3</sub>)} (LO DydOp[X] RO) (R<sub>1</sub> R<sub>2</sub> R<sub>3</sub> R<sub>4</sub>)</apll></p></li>
+
<p><apll>∇ {(Z<sub>1</sub> Z<sub>2</sub>)}←{(L<sub>1</sub> L<sub>2</sub> L<sub>3</sub>)} (LO dop[X] RO) (R<sub>1</sub> R<sub>2</sub> R<sub>3</sub> R<sub>4</sub>)</apll></p></li>
 
       <li>A jot (<apll>∘</apll>) may be used as an operand to a user-defined operator in which case the corresponding name in the header is undefined, that is <apll>⎕NC</apll> returns <apll>0</apll>.  For example,
 
       <li>A jot (<apll>∘</apll>) may be used as an operand to a user-defined operator in which case the corresponding name in the header is undefined, that is <apll>⎕NC</apll> returns <apll>0</apll>.  For example,
  
 
<apll><pre>
 
<apll><pre>
     ∇ (Z1 Z2)←(LO DydOp RO) R
+
     ∇ (Z1 Z2)←(LO dop RO) R
 
[1]  :select ⍬⍴⎕NC 'LO'
 
[1]  :select ⍬⍴⎕NC 'LO'
[2]   :case 0 ⋄ Z1←'LO is undefined'
+
[2]     :case 0 ⋄ Z1←'LO is undefined'
[3]   :case 2 ⋄ Z1←'LO is a variable'
+
[3]     :case 2 ⋄ Z1←'LO is a variable'
[4]   :case 3 ⋄ Z1←'LO is a function'
+
[4]     :case 3 ⋄ Z1←'LO is a function'
 
[5]  :end
 
[5]  :end
 
[6]
 
[6]
 
[7]  :select ⍬⍴⎕NC 'RO'
 
[7]  :select ⍬⍴⎕NC 'RO'
[8]   :case 0 ⋄ Z2←'RO is undefined'
+
[8]     :case 0 ⋄ Z2←'RO is undefined'
[9]   :case 2 ⋄ Z2←'RO is a variable'
+
[9]     :case 2 ⋄ Z2←'RO is a variable'
[10] :case 3 ⋄ Z2←'RO is a function'
+
[10]   :case 3 ⋄ Z2←'RO is a function'
 
[11]  :end
 
[11]  :end
 
     ∇
 
     ∇
  
       ∘DydOp⍴ 12
+
       ∘dop⍴ 12
 
LO is undefined&nbsp;&nbsp;RO is a function
 
LO is undefined&nbsp;&nbsp;RO is a function
       ⍴DydOp∘ 12
+
       ⍴dop∘ 12
 
LO is a function&nbsp;&nbsp;RO is undefined
 
LO is a function&nbsp;&nbsp;RO is undefined
       ∘DydOp∘ 12
+
       ∘dop∘ 12
 
LO is undefined&nbsp;&nbsp;RO is undefined
 
LO is undefined&nbsp;&nbsp;RO is undefined
 
</pre></apll>
 
</pre></apll>
Line 123: Line 128:
 
   <li><p>'''User-defined Hyperators'''</p>
 
   <li><p>'''User-defined Hyperators'''</p>
 
     <ul>
 
     <ul>
       <li><p>A user-defined <font color=purple><b>hyperator</b></font> is distinguished from a user-defined <b>operator</b> by its <font color=purple><b>header</b></font>, such that in the place where the operator <font color=purple><b>name</b></font> normally appears, it contains a left hyperand name, a hyperator name, and an optional right hyperand name (for dyadic hyperators only), all enclosed in <font color=purple><b>a single set of parentheses</b></font>.  For example, the hyperator part of the header for a monadic hyperator looks like <font color=purple><b><apll>(LO (LH MonHyp))</apll></b></font> or <font color=purple><b><apll>(LO (LH MonHyp) RO)</apll></b></font>, and a dyadic hyperator looks like <font color=purple><b><apll>(LO (LH DydHyp RH))</apll></b></font> or <font color=purple><b><apll>(LO (LH DydHyp RH) RO)</apll></b></font> where <apll>LO</apll> and <apll>RO</apll> are the left and right operands (a function, variable, or jot) and <apll>LH</apll> and <apll>RH</apll> are the left and right hyperands (an operator, function, variable, or jot).</p>
+
       <li><p>A user-defined <font color=purple><b>hyperator</b></font> is distinguished from a user-defined <b>operator</b> by its <font color=purple><b>header</b></font>, such that in the place where the operator <font color=purple><b>name</b></font> normally appears, it contains a left hyperand name, a hyperator name, and an optional right hyperand name (for dyadic hyperators only), all enclosed in <font color=purple><b>a single set of parentheses</b></font>.  For example, the hyperator part of the header for a monadic hyperator looks like <font color=purple><b><apll>(LO (LH mhmo))</apll></b></font> or <font color=purple><b><apll>(LO (LH mhdo) RO)</apll></b></font>, and a dyadic hyperator looks like <font color=purple><b><apll>(LO (LH dhmo RH))</apll></b></font> or <font color=purple><b><apll>(LO (LH dhdo RH) RO)</apll></b></font> where <apll>LO</apll> and <apll>RO</apll> are the left and right operands (a function, variable, or jot) and <apll>LH</apll> and <apll>RH</apll> are the left and right hyperands (an operator, function, variable, or jot).</p>
 
<font color=purple><b>
 
<font color=purple><b>
<p>All four types of user-defined hyperators may be called monadically or dyadically, as in</p>
+
<p>All four types of user-defined hyperators may be called niladically, monadically or dyadically, as in</p>
  
 
<table border="1" cellpadding="5" cellspacing="0" summary="">
 
<table border="1" cellpadding="5" cellspacing="0" summary="">
 
<tr>
 
<tr>
 
   <td></td>
 
   <td></td>
 +
  <td align="center">Niladic derived function</td>
 
   <td align="center">Monadic derived function</td>
 
   <td align="center">Monadic derived function</td>
 
   <td align="center">Dyadic derived function</td>
 
   <td align="center">Dyadic derived function</td>
Line 136: Line 142:
 
<tr>
 
<tr>
 
   <td>Monadic Hyperator, Monadic Operator</td>
 
   <td>Monadic Hyperator, Monadic Operator</td>
   <td><apll>∇ Z←(LO (LH MonHypMonOpr)) R</apll></td>
+
   <td><apll>∇ Z←(LO (LH mhmo))</apll></td>
   <td><apll>∇ Z←L (LO (LH MonHypMonOpr)) R</apll></td>
+
  <td><apll>∇ Z←(LO (LH mhmo)) R</apll></td>
 +
   <td><apll>∇ Z←L (LO (LH mhmo)) R</apll></td>
 
</tr>
 
</tr>
  
 
<tr>
 
<tr>
 
   <td>Monadic Hyperator, Dyadic Operator</td>
 
   <td>Monadic Hyperator, Dyadic Operator</td>
   <td><apll>∇ Z←(LO (LH MonHypDydOpr) RO) R</apll></td>
+
   <td><apll>∇ Z←(LO (LH mhdo) RO)</apll></td>
   <td><apll>∇ Z←L (LO (LH MonHypDydOpr) RO) R</apll></td>
+
  <td><apll>∇ Z←(LO (LH mhdo) RO) R</apll></td>
 +
   <td><apll>∇ Z←L (LO (LH mhdo) RO) R</apll></td>
 
</tr>
 
</tr>
  
 
<tr>
 
<tr>
 
   <td>Dyadic Hyperator, Monadic Operator</td>
 
   <td>Dyadic Hyperator, Monadic Operator</td>
   <td><apll>∇ Z←(LO (LH DydHypMonOpR RH)) R</apll></td>
+
   <td><apll>∇ Z←(LO (LH dhmo RH))</apll></td>
   <td><apll>∇ Z←L (LO (LH DydHypMonOpr RH)) R</apll></td>
+
  <td><apll>∇ Z←(LO (LH dhmo RH)) R</apll></td>
 +
   <td><apll>∇ Z←L (LO (LH dhmo RH)) R</apll></td>
 
</tr>
 
</tr>
  
 
<tr>
 
<tr>
 
   <td>Dyadic Hyperator, Dyadic Operator</td>
 
   <td>Dyadic Hyperator, Dyadic Operator</td>
   <td><apll>∇ Z←(LO (LH DydHypDydOpR RH) RO) R</apll></td>
+
   <td><apll>∇ Z←(LO (LH dhdo RH) RO)</apll></td>
   <td><apll>∇ Z←L (LO (LH DydHypDydOpr RH) RO) R</apll></td>
+
  <td><apll>∇ Z←(LO (LH dhdo RH) RO) R</apll></td>
 +
   <td><apll>∇ Z←L (LO (LH dhdo RH) RO) R</apll></td>
 
</tr>
 
</tr>
  
 
</table>
 
</table>
 
</b></font>
 
</b></font>
<p>Hyperators exist to modify behaviors of operators as well as functions and data.  An hyperator may be applied to an operator, function, or data to derive a ''different'' operator or function.  An attribute of hyperators are their precedence '''over''' operators and functions; hyperators are executed '''before''' operators and functions.  Like operators, hyperators have short right scope, but unlike operators they have '''short left scope''' so as to allow an '''operator''' to be passed as a '''left hyperand'''.</p>
+
<p>Hyperators exist to modify behaviors of operators as well as functions and data.  An hyperator may be applied to an operator, function, or data to derive a ''different'' operator or function.  An attribute of hyperators are their precedence '''over''' operators and functions; hyperators are executed '''before''' operators and functions.  Like operators, hyperators have '''short right scope''', but unlike operators they have '''short left scope''' so as to allow an '''operator''' to be passed as a '''left hyperand'''.</p>
 
<p>Just like user-defined functions and operators, user-defined hyperators may have multiple names in the result, left, and right arguments (but not the left and/or right hyperands/operands), an optional left argument, an axis operator, and a non-displayable result.</p>
 
<p>Just like user-defined functions and operators, user-defined hyperators may have multiple names in the result, left, and right arguments (but not the left and/or right hyperands/operands), an optional left argument, an axis operator, and a non-displayable result.</p>
  
 
<p>A header using all these features might look like</p>
 
<p>A header using all these features might look like</p>
  
<p><apll>∇ {(Z<sub>1</sub> Z<sub>2</sub>)}←{(L<sub>1</sub> L<sub>2</sub> L<sub>3</sub>)} (LO DydOp[X] RO) (R<sub>1</sub> R<sub>2</sub> R<sub>3</sub> R<sub>4</sub>)</apll></p></li>
+
<p><apll>∇ {(Z<sub>1</sub> Z<sub>2</sub>)}←{(L<sub>1</sub> L<sub>2</sub> L<sub>3</sub>)} (LO (LH dhdo[X] RH) RO) (R<sub>1</sub> R<sub>2</sub> R<sub>3</sub> R<sub>4</sub>)</apll></p></li>
 
       <li>A jot (<apll>∘</apll>) may be used as a hyperand to a user-defined hyperator in which case the corresponding name in the header is undefined, that is <apll>⎕NC</apll> returns <apll>0</apll>.  For example,
 
       <li>A jot (<apll>∘</apll>) may be used as a hyperand to a user-defined hyperator in which case the corresponding name in the header is undefined, that is <apll>⎕NC</apll> returns <apll>0</apll>.  For example,
  
 
<apll><pre>
 
<apll><pre>
     ∇ (Z1 Z2 Z3)←(LO (LH H2O1 RH)) R
+
     ∇ (Z1 Z2 Z3)←(LO (LH dhmo RH)) R
 
[1]  :select ⍬⍴⎕NC 'LO'
 
[1]  :select ⍬⍴⎕NC 'LO'
[2]   :case 0 ⋄ Z1←'LO is undefined'
+
[2]     :case 0 ⋄ Z1←'LO is undefined'
[3]   :case 2 ⋄ Z1←'LO is a variable'
+
[3]     :case 2 ⋄ Z1←'LO is a variable'
[4]   :case 3 ⋄ Z1←'LO is a function'
+
[4]     :case 3 ⋄ Z1←'LO is a function'
[5]   :else ⋄ ⎕ERROR 'Left Operand Unknown'
+
[5]     :else ⋄ ⎕ERROR 'Left Operand Unknown'
 
[6]  :end
 
[6]  :end
 
[7]   
 
[7]   
 
[8]  :select ⍬⍴⎕NC 'LH'
 
[8]  :select ⍬⍴⎕NC 'LH'
[9]   :case 0 ⋄ Z2←'LH is undefined'
+
[9]     :case 0 ⋄ Z2←'LH is undefined'
[10] :case 2 ⋄ Z2←'LH is a variable'
+
[10]   :case 2 ⋄ Z2←'LH is a variable'
[11] :case 3 ⋄ Z2←'LH is a function'
+
[11]   :case 3 ⋄ Z2←'LH is a function'
[12] :case 4 ⋄ Z2←'LH is an operator'
+
[12]   :case 4 ⋄ Z2←'LH is an operator'
[13] :else ⋄ ⎕ERROR 'Left Hyperand Unknown'
+
[13]   :else ⋄ ⎕ERROR 'Left Hyperand Unknown'
 
[14]  :end
 
[14]  :end
 
[15]   
 
[15]   
 
[16]  :select ⍬⍴⎕NC 'RH'
 
[16]  :select ⍬⍴⎕NC 'RH'
[17] :case 0 ⋄ Z3←'RH is undefined'
+
[17]   :case 0 ⋄ Z3←'RH is undefined'
[18] :case 2 ⋄ Z3←'RH is a variable'
+
[18]   :case 2 ⋄ Z3←'RH is a variable'
[19] :case 3 ⋄ Z3←'RH is a function'
+
[19]   :case 3 ⋄ Z3←'RH is a function'
[20] :case 4 ⋄ Z3←'RH is an operator'
+
[20]   :case 4 ⋄ Z3←'RH is an operator'
[21] :else ⋄ ⎕ERROR 'Right Hyperand Unknown'
+
[21]   :else ⋄ ⎕ERROR 'Right Hyperand Unknown'
 
[22]  :end
 
[22]  :end
 
     ∇
 
     ∇
  
     ⍪ -(¨¨)H2O1⍤5 6
+
     ⍪ -(¨¨)dhmo⍤5 6
 
  LO is a function   
 
  LO is a function   
 
  LH is an operator  
 
  LH is an operator  
 
  RH is an operator
 
  RH is an operator
       ⍪ -(¨¨)H2O1∘5 6
+
       ⍪ -(¨¨)dhmo∘5 6
 
  LO is a function   
 
  LO is a function   
 
  LH is an operator  
 
  LH is an operator  
 
  RH is undefined
 
  RH is undefined
 +
      ⍪ +/dhmo⍤5 6
 +
LO is a function 
 +
LH is an operator
 +
RH is an operator
 
</pre></apll>
 
</pre></apll>
 
       </li>
 
       </li>

Latest revision as of 19:34, 3 April 2019

  • User-defined Functions, Operators, and Hyperators

    • Within a user-defined function/operator/hyperator header, the left and right arguments may consist of one or more names each separated by one or more blanks and enclosed in parentheses. In this context, the caller of the function/operator/hyperator must pass a scalar (which is extended to each name) or anappropriate length vector argument. Upon invocation of the function/operator/hyperator, these values are assigned one item per name.

      For example, a function whose header looks like

      ∇ Z←FOO (R1 R2)

      can be called with a two-element vector (or a scalar which is extended to a two-element vector) right argument only. If the right argument is of rank greater than one, a RANK ERROR is signaled. If the right argument is not of the proper length, a LENGTH ERROR is signaled.

      Note that if only one name appears within parentheses in the left or right argument, the caller must supply a value for this argument which is a scalar or one-element vector.

    • Within a user-defined function/operator/hyperator header, the result may consist of two or more names each separated by one or more blanks and enclosed in parentheses. In this context, when the function exits, the individual names must all have a value (else a VALUE ERROR is signaled), the names are joined together in a strand, and the resulting vector is returned as the result. If the header contains only one name for the result, it may not be enclosed in parentheses.

    • Thanks to Dyalog APL for proposing and implementing the above features.

    • Within a user-defined function/operator/hyperator header, the result may be marked as shy or non-displayable by enclosing it in braces, as in ∇ {Z}←FOO R. If the result part of the header consists of multiple names, either
      ∇ {Z1 Z2}←FOO R,
      ∇ ({Z1 Z2})←FOO R, or
      ∇ {(Z1 Z2)}←FOO R
      may be used to mark the result as shy.

    • Within a user-defined function/operator/hyperator header, the left argument may be marked as optional (a.k.a. ambivalent) by enclosing it in braces, as in ∇ Z←{L} FOO R. If the left argument part of the header consists of multiple names, either
      ∇ Z←{L1 L2} FOO R     ⍝TWO optional left arguments
      ∇ Z←({L1 L2}) FOO R
      ∇ Z←{(L1 L2)} FOO R
      Braces {} are used to mark the left argument as optional. System function ⎕NC may be used to detect the presence/absence of a left argument(0=Not Used/Missing Arg, 2=Used/Yes Arg - for {ArgName} e.g. {L} by calling   ⎕NC 'L'   within the user function itself, here FOO).

    • A user-defined function/operator/hyperator may accept the axis operator as an additional argument, just as primitive function/operator/hyperators do. The axis operator may be specified in the header as in
      ∇ Z←FOO[X] R for a function,
      ∇ Z←(LO FOO[X]) R for a monadic operator, and
      ∇ Z←(LO FOO[X] RO) R for a dyadic operator, etc.

    • A user-defined function/operator/hyperator may define a separate entry point for when it is called on a prototype — use the line label ⎕PRO:. For example, the monadic function FOO when used in FOO¨R where R is an empty array is entered at the line labeled ⎕PRO:. If there is no such line with that label, a DOMAIN ERROR is signaled.

    • The local names to a user-defined function/operator/hyperator appear in the header to the right of the syntax part as above. The first local name is separated from the start of the header by a single semicolon; the second and subsequent local names are separated from each other by either a single semicolon or one or more blanks depending upon your own preference. For example

      ∇ Z←FOO R;g1 g2 g3 g4;h1 h2 h3
    • Within a recursive user-defined function, a del symbol () refers to the user-defined function without having to name it. For example,

          ∇ Z←fibonacci R
      [1]   :if R≤1 ⋄ Z←1 ⋄ →0 ⋄ :end
      [2]   Z←(∇R-1) + ∇R-2
          ∇
      
    • Within a recursive user-defined operator/hyperator, a del symbol () refers to the derived function of the user-defined operator/hyperator with the current operands/hyperands bound to the operator/hyperator name without having to name it. For example, with a monadic operator whose header looks like

      ∇ Z←(LO mop) R

      a in the body of the operator is a shorthand for (LO mop), and for a dyadic operator whose header looks like

      ∇ Z←(LO dop RO) R

      a in the body of the operator is a shorthand for (LO dop RO), etc.

    • Within a recursive user-defined operator/hyperator, two del symbols (∇∇) refer to the operator/hyperator name with bound hyperand(s), but no bound operands. For example, in the monadic operator case above in the body of the operator, ∇∇ refers to mop, and in the dyadic operator case above, ∇∇ refers to dop, and in both cases without having to know the actual name. Within a recursive user-defined hyperator whose header looks like ∇ Z←L (LO (LH mhdo) RO) R, ∇∇ refers to (LH mhdo).

    • Within a recursive user-defined hyperator, three del symbols (∇∇∇) refer to the hyperator name with no bound operands/hyperands.

  • User-defined Operators

    • A user-defined operator is distinguished from a user-defined function by its header, such that in the place where the function name normally appears, it contains a left operand name, an operator name, and an optional right operand name (for dyadic operators only), all enclosed in a single set of parentheses. For example, the operator part of the header for a monadic operator looks like (LO mop), and a dyadic operator looks like (LO dop RO) where LO and RO are the left and right operands (a function, variable, or jot).

      Both types of user-defined operators may be called niladically, monadically or dyadically, as in

      Niladic derived function Monadic derived function Dyadic derived function
      Monadic operator ∇ Z←(LO mop) ∇ Z←(LO mop) R ∇ Z←L (LO mop) R
      Dyadic operator ∇ Z←(LO dop RO) ∇ Z←(LO dop RO) R ∇ Z←L (LO dop RO) R

      Operators exist to modify behaviors of functions as well as operate on data. An operator may be applied to a function or data to derive a different function. An attribute of operators are their precedence over functions; operators are executed before functions. One indication an Operator should be used instead of a function is - when a function always includes parentheses during its call. Proper structuring of commonly used operators prevents, for instance, multiple layers of parentheses, thus clarifying code, speeding execution and increasing parallelization. Operator usage situations: Statisticians - regression operators (power, multiple, growth, natural, cubic, cylical, etc.); Astronomers - integration and differentiation operators; Engineers - curve fitting, approximating, equation root derivations.

      Just like user-defined functions, user-defined operators may have multiple names in the result, left, and right arguments (but not the left and/or right operands), an optional left argument, an axis operator, and a non-displayable result.

      A header using all these features might look like

      ∇ {(Z1 Z2)}←{(L1 L2 L3)} (LO dop[X] RO) (R1 R2 R3 R4)

    • A jot () may be used as an operand to a user-defined operator in which case the corresponding name in the header is undefined, that is ⎕NC returns 0. For example,
          ∇ (Z1 Z2)←(LO dop RO) R
      [1]   :select ⍬⍴⎕NC 'LO'
      [2]     :case 0 ⋄ Z1←'LO is undefined'
      [3]     :case 2 ⋄ Z1←'LO is a variable'
      [4]     :case 3 ⋄ Z1←'LO is a function'
      [5]   :end
      [6]
      [7]   :select ⍬⍴⎕NC 'RO'
      [8]     :case 0 ⋄ Z2←'RO is undefined'
      [9]     :case 2 ⋄ Z2←'RO is a variable'
      [10]    :case 3 ⋄ Z2←'RO is a function'
      [11]  :end
          ∇
      
            ∘dop⍴ 12
      LO is undefined  RO is a function
            ⍴dop∘ 12
      LO is a function  RO is undefined
            ∘dop∘ 12
      LO is undefined  RO is undefined
      
  • User-defined Hyperators

    • A user-defined hyperator is distinguished from a user-defined operator by its header, such that in the place where the operator name normally appears, it contains a left hyperand name, a hyperator name, and an optional right hyperand name (for dyadic hyperators only), all enclosed in a single set of parentheses. For example, the hyperator part of the header for a monadic hyperator looks like (LO (LH mhmo)) or (LO (LH mhdo) RO), and a dyadic hyperator looks like (LO (LH dhmo RH)) or (LO (LH dhdo RH) RO) where LO and RO are the left and right operands (a function, variable, or jot) and LH and RH are the left and right hyperands (an operator, function, variable, or jot).

      All four types of user-defined hyperators may be called niladically, monadically or dyadically, as in

      Niladic derived function Monadic derived function Dyadic derived function
      Monadic Hyperator, Monadic Operator ∇ Z←(LO (LH mhmo)) ∇ Z←(LO (LH mhmo)) R ∇ Z←L (LO (LH mhmo)) R
      Monadic Hyperator, Dyadic Operator ∇ Z←(LO (LH mhdo) RO) ∇ Z←(LO (LH mhdo) RO) R ∇ Z←L (LO (LH mhdo) RO) R
      Dyadic Hyperator, Monadic Operator ∇ Z←(LO (LH dhmo RH)) ∇ Z←(LO (LH dhmo RH)) R ∇ Z←L (LO (LH dhmo RH)) R
      Dyadic Hyperator, Dyadic Operator ∇ Z←(LO (LH dhdo RH) RO) ∇ Z←(LO (LH dhdo RH) RO) R ∇ Z←L (LO (LH dhdo RH) RO) R

      Hyperators exist to modify behaviors of operators as well as functions and data. An hyperator may be applied to an operator, function, or data to derive a different operator or function. An attribute of hyperators are their precedence over operators and functions; hyperators are executed before operators and functions. Like operators, hyperators have short right scope, but unlike operators they have short left scope so as to allow an operator to be passed as a left hyperand.

      Just like user-defined functions and operators, user-defined hyperators may have multiple names in the result, left, and right arguments (but not the left and/or right hyperands/operands), an optional left argument, an axis operator, and a non-displayable result.

      A header using all these features might look like

      ∇ {(Z1 Z2)}←{(L1 L2 L3)} (LO (LH dhdo[X] RH) RO) (R1 R2 R3 R4)

    • A jot () may be used as a hyperand to a user-defined hyperator in which case the corresponding name in the header is undefined, that is ⎕NC returns 0. For example,
          ∇ (Z1 Z2 Z3)←(LO (LH dhmo RH)) R
      [1]   :select ⍬⍴⎕NC 'LO'
      [2]     :case 0 ⋄ Z1←'LO is undefined'
      [3]     :case 2 ⋄ Z1←'LO is a variable'
      [4]     :case 3 ⋄ Z1←'LO is a function'
      [5]     :else ⋄ ⎕ERROR 'Left Operand Unknown'
      [6]   :end
      [7]   
      [8]   :select ⍬⍴⎕NC 'LH'
      [9]     :case 0 ⋄ Z2←'LH is undefined'
      [10]    :case 2 ⋄ Z2←'LH is a variable'
      [11]    :case 3 ⋄ Z2←'LH is a function'
      [12]    :case 4 ⋄ Z2←'LH is an operator'
      [13]    :else ⋄ ⎕ERROR 'Left Hyperand Unknown'
      [14]  :end
      [15]  
      [16]  :select ⍬⍴⎕NC 'RH'
      [17]    :case 0 ⋄ Z3←'RH is undefined'
      [18]    :case 2 ⋄ Z3←'RH is a variable'
      [19]    :case 3 ⋄ Z3←'RH is a function'
      [20]    :case 4 ⋄ Z3←'RH is an operator'
      [21]    :else ⋄ ⎕ERROR 'Right Hyperand Unknown'
      [22]  :end
          ∇
      
           ⍪ -(¨¨)dhmo⍤5 6
       LO is a function  
       LH is an operator 
       RH is an operator
            ⍪ -(¨¨)dhmo∘5 6
       LO is a function  
       LH is an operator 
       RH is undefined
            ⍪ +/dhmo⍤5 6
       LO is a function  
       LH is an operator 
       RH is an operator