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 
>>>> 
>>> 
>> 
> 

Reply via email to