Skip to content

Ambivalent Operators...

Vector 6:2, page 117

language design programming techniques

Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 117

With reference to David Piper’s letter in VECTOR 5.4 ... The right operand to David’s operator must be parenthesized to force the value rather than the ⎕NC function itself to become the operand:

  [2] →(↑(RUN AVE)←(⍴NUMS)(AVERAGE ∆MONADIC(⎕NC 'SIZE'))NUMS)/0
                                           ↑          ↑

Once this is done, it works! However both the operator itself and the convoluted expression required to call it are perfectly described by the editorial from the same edition! Nevertheless, if we’re after a tricksy solution, the following avoids all conditional code, be it branch or execute, it tells you what it’s doing, and it works faster:

      ∇
[0]     AVE←SIZE AVERAGE NUMS
[1]    ⍝ MOVING OR NORMAL AVG DEPENDING ON EXISTENCE OF SIZE
[2]     AMBIVALENT 'SIZE'
[3]     AVE←(SIZE+/NUMS)÷↑SIZE,⍴NUMS
      ∇

      ∇
[0]     AMBIVALENT AMBIVALENT
[1]    ⍝ DCL CALLING FN AMBIVALENT WITH NAME OF ITS LEFT ARG.
[2]     AMBIVALENT←⎕FX('R←',AMBIVALENT,' B')('R←B')
      ∇

The function AMBIVALENT, given the name of the left argument to its calling function, attempts to fix a function with that name which returns its only argument. In the example, this would be:

[0]   R←SIZE B
[1]   R←B

This can only be fixed if SIZE does not already exist, in which case the call to plus reduction is genuinely monadic and the right argument to divide defaults to the shape of NUMS.

Phil Last