This ambiguity does not arise in APL2. The A (O P) B parsing is invalid because an operator (O) can't be the operand of another operator (P).
Jay. On Sat, 28 Nov 2020, 12:59 Dr. Jürgen Sauermann, <mail@jürgen-sauermann.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. > > 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) > 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: image.png] >> > And then: > >> [image: 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> 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 >> >> >> > > >