Thank you for this totally lucid explanation. It is bookmarked and saved in my APL reference notes.
respect… > On Nov 28, 2020, at 7:59 AM, Dr. Jürgen Sauermann > <m...@xn--jrgen-sauermann-zvb.de> wrote: > > Hi Hans-Peter, > > this kind of surprises has puzzled me since the early days of APL. > They already existed in APL1 but never occurred in practice since > the number of constructs affected, for instance +//'ABC' was small > and did not make much sense at that time. > > The proliferation of operators in APL2 then not only increased the > number of affected constructs but also included constructs that could > make sense. Your examples are instances of these constructs. > > In C/C++ the order in which functions/operators are evaluated is > unambiguously defined by two attributes of each operator: its precedence > and its associativity. The precedence defines in which order different groups > of operators (like × or ÷ versus + or -) are computed while the associativity > defines the order (like left-to-right or right-to-left) in which operators > with > the same precedence are computed. > > In APL, however, the situation is rather different. The ISO standard > indirectly > specifies the well-known right-to-left evaluation of APL expressions, but does > not specify an order when it comes to APL functions versus APL operators. > Hybrids like /, ⌿, \, and ⍀ make matters even worse. IBM APL2 is more specific > about that by essentially defining that: > > (1) /, ⌿, \, and ⍀ are (monadic) operators (even though their (single) left > argument could > be a value), and > > (2) arguments of operators bind stronger than arguments of functions. > > (3) the left operand of an operator can be a value or a function, > > Although these rules determine the order of evaluation in most cases they do > not, > at least as I understand the matter, catch all cases. The missing piece is > how two > handle the pattern A O P B where A and B are values and O and P are monadic > operators (of which O allows a value as left argument). This pattern has two > valid evaluations: > > (A O) P B and A (O P) B > > The first evaluation binds A to O, the derived function (A O) is then bound > to P, > giving another derived function ((A O) P) which is then evaluated with > argument B. > > The second evaluation binds O to P, and the derived function (O P) is then > evaluated with arguments A and B. > > As already mentioned this this can only occur if an operator allows a value > as left > argument, which is fortunately only the case for a few pathological operators, > (in particular /, ⌿, \, and ⍀). > > I have tried to explain this in earlier versions of the GNU info manual, but > have removed > it recently due to a somewhat incorrect and misleading wording in the manual. > > With the above explanation in mind, I believe that GNU APL behaves correctly > even > though a different behaviour (with unfortunately different resuilts) would be > equally correct. > > You can, BTW, watch the GNU parser at work by enabling logging facility 32 > (note > that the program counter PC of the virtual APL machine counts from right to > left). > > ]LOG 32 > > 1 2 3 / ¨ 'ABC' > > changed to Prefix[si=2]) ============================================ > [si=2 PC=0] Read token[0] (←0←) VALUE1«≡⊏3⊐ABC» TC_VALUE > fifo[si=2 len=1 PC=1] is now : TC_VALUE at Prefix.cc:564 > [si=2 PC=1] Read token[1] (←0←) ¨ TC_OPER1 > fifo[si=2 len=2 PC=2] is now : TC_OPER1 TC_VALUE at Prefix.cc:564 > [si=2 PC=2] Read token[2] (←0←) / TC_OPER1 > fifo[si=2 len=3 PC=3] is now : TC_OPER1 TC_OPER1 TC_VALUE at Prefix.cc:564 > phrase #297: M M matches, prio 42, calling reduce_M_M__() > reduce_M_M__() returned: RA_CONTINUE > fifo[si=2 len=2 PC=3] is now : TC_FUN12 TC_VALUE at Prefix.cc:564 > [si=2 PC=3] Read token[2] (←0←) VALUE3«≡⊏3⊐1 2 3» TC_VALUE > fifo[si=2 len=3 PC=4] is now : TC_VALUE TC_FUN12 TC_VALUE at Prefix.cc:564 > phrase #234: A F B matches, prio 33, calling reduce_A_F_B_() > reduce_A_F_B_() returned: RA_CONTINUE > fifo[si=2 len=1 PC=4] is now : TC_VALUE at Prefix.cc:564 > [si=2 PC=4] Read token[1] (←0←) ENDL TC_END > fifo[si=2 len=2 PC=5] is now : TC_END TC_VALUE at Prefix.cc:564 > phrase #46: END B matches, prio 2, calling reduce_END_B__() > A BB CCC > reduce_END_B__() returned: RA_PUSH_NEXT > [si=2 PC=5] Read token[0] (←0←) RETURN_STATS TC_RETURN > fifo[si=2 len=1 PC=6] is now : TC_RETURN at Prefix.cc:564 > phrase #13: RETC matches, prio 1, calling reduce_RETC___() > - end of ◊ context > reduce_RETC___() returned: RA_RETURN > Prefix::reduce_statements(si=2) returned VOID in StateIndicator::run() > 1 2 3 / ¨ 'ABC' > > Finally, if you need GNU APL to behave differently, then you can > enforce a different order by means of { and }, similar to ( and ) for > values. > > The default behaviour of GNU APL is this: > > 1 2 3 /¨ 'ABC' ⍝ / bound to ¨ > A BB CCC > > which corresponds to pattern A (O P) B above. If you prefer (A O) P B instead, > then you can do this: > > {1 2 3/⍵} ¨ 'ABC' ⍝ 1 2 3 bound to / > AAAAAA BBBBBB CCCCCC > > which corresponds to pattern (A O) P B above. This is almost as easy as > using parentheses for values. > > Best Regards, > Jürgen > > > > On 11/26/20 1:28 PM, Hans-Peter Sorge wrote: >> Hi, >> >> I thought so, APL is fun:-) >> >> The following 4 expressions are just a repeat: >> ⍝1 - a vector replicates a scalar. The result is a simple vector >> 1 2 3/'A' >> AAAAAA >> >> ⍝2 - scalar by scalar - simple vector as result >> 1 2 3/'ABC' >> ABBCCC >> >> ⍝3 - as in ⍝1 but for each scalar a vector replicates a scalar. The result >> is a nested vector of simple vectors >> (⊂1 2 3)/¨'ABC' >> AAAAAA BBBBBB CCCCCC >> >> ⍝4 - is consistent with ⍝2 the each-operator introduces one level of depth >> 1 2 3/¨'ABC' >> A BB CCC >> >> The next result would be "surprising" to me as it is somewhere between 2 and >> 3 and logic asside, "feels" inconsistent: >> ⍝4 >> ⍝ 1 2 3/¨'ABC' >> ⍝ AAAAAA BBBBBB CCCCCC >> >> >> Going a little further. The simple vector 'ABC' is being turned into a >> nested vector. >> ⍝5,6 >> 1 2 3/,¨'ABC' >> A B B C C C >> 1 2 3/∊¨'ABC' >> A B B C C C >> >> ⍝9 - scalar applied to simple vector >> 2/'ABC' >> AABBCC >> 2/¨'ABC' >> AA BB CC >> >> ⍝ 10 - as expected having a nested vector: >> 2/,¨'ABC' >> A A B B C C >> >> Here comes my irritation. Or some missing knowledge .... >> ⍝ 11 - if this is true ( from ⍝3 ) >> (⊂1 2 3)/¨'ABC' >> AAAAAA BBBBBB CCCCCC >> >> ⍝ 12 - then this schould be different >> (⊂1 2 3)/¨,¨'ABC' >> AAAAAA BBBBBB CCCCCC >> ⍝ expected >> A AA AAA B BB BBB C CC CCC >> >> >> ⍝ 13 - instead of domain error .. >> (⊂1 2 3)/'ABC' >> DOMAIN ERROR >> (⊂1 2 3)/'ABC' >> ^ ^ >> ⍝ the result could be >> AAAAAABBBBBBCCCCCC >> >> ⍝ 14 - like in case of a simple vector, the nested vector results are >> accordingly: >> 1 2 3/'AA' 'BB' 'CC' >> AA BB BB CC CC CC >> >> ⍝like ⍝4 >> 1 2 3/¨'AA' 'BB' 'CC' >> AA BBBB CCCCCC >> >> ⍝ 15 - and , analogous to 12 >> (⊂1 2 3)/¨'AA' 'BB' 'CC' >> LENGTH ERROR >> (⊂1 2 3)/¨'AA' 'BB' 'CC' >> ^ ^ >> ⍝ could then be >> AA AA AA AA AA AA BB BB BB BB BB BB CC CC CC CC CC CC >> >> Just my thoughts.. >> >> Best Regards >> Hans-Peter >> >> >> Am 24.11.20 um 17:17 schrieb Dr. Jürgen Sauermann: >>> Hi Adam, >>> >>> thanks, see below. >>> >>> Best Regards, >>> Jürgen >>> >>> >>> On 11/23/20 11:07 PM, Adám Brudzewsky wrote: >>>> For the sake of compatibility with IBM APL2 >>>> >>>> Speaking of which, what is GNU APL's official policy? >>>> >>> GNU APL's general policy regarding standards and the like is to consider, >>> (in that order): >>> >>> 1. the IBM APL2 language reference manual, >>> 2. the IBM APL2 implementation (PC demo version, can't aford the commercial >>> version), >>> 3. the ISO standard, >>> 4. other APL implementations and suggestions from bug-apl@gnu.org >>> <mailto:bug-apl@gnu.org>. >>> >>> Sometimes, however, this can have undesirable consequences and then >>> some sort of common sense is applied to change the order. >>> >>>> I noticed that the info manual >>>> (https://www.gnu.org/software/apl/apl.html#APL-symbols-that-can-be-functions-or-operators >>>> >>>> <https://www.gnu.org/software/apl/apl.html#APL-symbols-that-can-be-functions-or-operators>) >>>> is factually wrong about APL2, claiming that: >>>> the ambiguity related to / ⌿ \ and ⍀ is not resolved by these rules. >>> I see. That statement is probably a left-over from the early days of GNU >>> APL. When I started >>> with GNU APL, all I had was some vague recollection of APL1 from the 1970s >>> (my first APL >>> computer was an IBM 5110 desktop, a precursor of the IBM PC). At that time >>> functions were >>> functions and values were values. At some later time, triggered by the >>> ⍤-operator (which was >>> not implemented in IBM APL2 but defined in ISO), I changed to the APL2 way >>> of handling / >>> and \. >>> >>> I have updated the documentation, SVN 1363. >>>> The APL2 language reference does in fact make it perfectly clear how / and >>>> friends are treated, namely as operators. Always. Note: >>>> <image.png> >>>> And then: >>>> <image.png> >>>> Note that this makes APL2 ISO non-compliant. Indeed, here, GNU APL follows >>>> Dyalog and NARS2000: >>>> 1 2 3/¨'ABC' >>>> A BB CCC >>>> While APL2 and APLX give: >>>> 1 2 3/¨'ABC' >>>> AAAAAA BBBBBB CCCCCC >>>> This is because 1 2 3/ is a derived monadic function and ¨ maps the entire >>>> function to each letter. >>>> >>> I believe older GNU APL versions would have given the APL2/APL X results, >>> while newer versions >>> give the other result. This is one of the examples where the general GNU >>> APL policy is not being >>> followed. If an incompatibility with APL2 exists long enough with no >>> complaints from the users, >>> then I believe backward compatibility with GNU APL is more important than >>> compatibility with IBM >>> APL2. >>> >>>> On Mon, Nov 23, 2020 at 9:21 PM Dr. Jürgen Sauermann >>>> <mail@jürgen-sauermann.de <mailto:mail@j%C3%BCrgen-sauermann.de>> wrote: >>>> Hi Kacper, Adam, >>>> >>>> thanks. For the sake of compatibility with IBM APL2 I have changed ⎕UCS so >>>> that >>>> it accepts float and complex numbers that are near to integers. My >>>> initial thinking was >>>> that e.g. ⎕UCS of a complex number is most likely a programming mistake so >>>> that a DOMAIN ERROR would be more helpful than being a burden. But APL2 >>>> compatibility is an even stronger argument in this case. >>>> >>>> I have also adjusted the integer domain which is now -$80 ... $7FFFFFFF >>>> so that no conflicts with signed bytes from ⎕FIO should arise. >>>> >>>> SVN 1362. >>>> >>>> Best Regards, >>>> Jürgen >>>> >>>> >>>> >>>> On 11/22/20 11:11 PM, Kacper Gutowski wrote: >>>>> On Sun, Nov 22, 2020 at 03:19:19PM +0100, Dr. Jürgen Sauermann wrote: >>>>>> Floating point and complex numbers are not allowed as to avoid >>>>>> interference with ⎕CT (i.e. how should rounding be performed?). >>>>> >>>>> I share your sentiment regarding the upper bound of the ⎕UCS domain, but >>>>> throwing a domain error on ⎕UCS1E2 looks like a bug to me too. 1E2 is >>>>> clearly an integer regardless of the implementation details, and I would >>>>> be surprised if APL2 didn't accept it. I would expect rounding to be the >>>>> same as in all the other places that require near-integers, like array >>>>> indices. >>>>> >>>>> The negative ones are also a bit weird. I wasn't aware of their >>>>> existence, and they seem to work in surprising ways when passed to >>>>> various variants of ⎕CR. >>>>> >>>>> -k >>>> >>> >> >