And a third email about lambda locals.

IMHO, a solution could be to introduce an extra assignment arrow which denotes 
explicit
global assignment, and make the usual assignment arrow denote assignment which 
is
local to lambdas (or have it the other way around).
If the standard doesn’t allow something like this, maybe something along the 
lines of ⎕FX
like:

        ‘A’ ⎕LC data
        ‘A’ ⎕GL data

to denote explicit global or local assignment useful in lambdas or other 
places, whichever
is not chosen to be denoted by the already existing arrow, could be used.
I would argue that the current arrow be used for local assignment, because 
(aside from
personal taste) global assignment is more “dangerous” if inadvertently used. As 
in,
a person who wants to just throw together a quick lambda doesn’t usually want
or need the effects of global assignment unless they can explicitly say so.

Louis

Sorry if I’m sending these twice; my mailer automatically sends them only to 
you Jürgen,
so I end up forwarding them to the mailing list.


> On 13 Aug 2016, at 10:19, Juergen Sauermann <[email protected] 
> <mailto:[email protected]>> wrote:
> 
> Hi,
> 
> the problem is that there is no syntactical means to "state otherwise".
> 
> I personally find it convenient to assign to variables outside the lambda, 
> for example
> to increment a counter on every iteration of the lambda. Of course one can 
> criticize the way
> APL handles variables, but the limited number of function arguments and 
> return values
> makes the scoping rules of APL almost inevitable. And I still believe that it 
> is a bad thing
> if the scoping rules of lambdas are different from the scoping rules of 
> "normal" defined functions.
> 
> So the only room for changes that remains is to have a way of adding local 
> variables to the header
> line of lambdas. Something along the lines of:
> 
>       FUN←'A B C' ⎕LOCALIZE { ... }
> 
> where A B and C would become local variables in the named lambda FUN.
> 
> I would also argue that lambdas are only a quick-and-dirty hack for 
> specifying the function arguments
> of the EACH operator and friends; for serious functions ⎕FX and ∇ have all 
> the features that are missing
> in GNU APL lambdas.
> 
> /// Jürgen
> 
> 
> On 08/13/2016 02:11 PM, Elias Mårtenson wrote:
> 
>> With regards to lack of local variables for lambda functions, I've observed 
>> that local is the typical case, and nonlocal is somewhat rare.
>> Wouldn't it make sense to make all variable assignments local for lambda 
>> functions local, unless stated otherwise?
>> Regards, 
>> Elias
>> 
>> On 13 Aug 2016 8:05 pm, "Juergen Sauermann" <[email protected] 
>> <mailto:[email protected]>> wrote:
>>> Hi Louis,
>>> 
>>> a quick answer to your question beforehand, I will look into the bugs later.
>>> 
>>> GNU APL has implemented the power operator according to the description
>>> in the book "Mastering Dyalog APL". The ISO standard says nothing about this
>>> operator, it is simply not defined there.
>>> 
>>> In "Mastering Dyalog APL" I haven't found the monadic case for the right 
>>> function argument
>>> G of the power operator. In that book G seems to be always dyadic. So the 
>>> monadic case looks
>>> like a new Dyalog invention. And, if it is defined like you say, IMHO not 
>>> the ultimate wisdom.
>>> 
>>> What I do not like at all is the fact that in the dyadic case F is being 
>>> computed before G (it has to,
>>> because you need the result ⍺F⍵ or F⍵ as left argument of G. And, as you 
>>> say, in the monadic
>>> case F is being computed after G. 
>>> 
>>> I could imagine to implement the monadic G if it were always computed after 
>>> F so that the order
>>> of execution is consistent for the monadic and dyadic cases. But if Dyalog 
>>> really has different orders
>>> then I would prefer to not implement the monadic case in GNU APL at all 
>>> because then I would only
>>> have the choice between an inconsistent execution order (which is, in my 
>>> opinion, bad) or an
>>> incompatibility with Dyalog APL (which is also bad).
>>> 
>>> Actually in GNU APL lambdas can be ambivalent, but monadic functions 
>>> (lambda or not) cannot be
>>> ambivalent. Localizing variables assigned in lambdas automatically is 
>>> technically possible but would
>>> break backward  compatibility of existing workspaces. There was a 
>>> discussion on this topic earlier this
>>> year, but no progress lately. I was thinking of some ⎕-function (like ⎕FX 
>>> but with {} syntax that would
>>> allow you to created lambdas with more control over the localization of 
>>> variables).
>>> 
>>> BTW, I read the word until in your description below as F being called 
>>> before G and not after G,
>>> even in the monadic case.
>>> 
>>> /// Jürgen
>>> 
>>> 
>>> 
>>> On 08/13/2016 08:24 AM, Louis de Forcrand wrote:
>>> 
>>> I’ll start with the question:
>>> 
>>>  The Dyalog 15.0 manual states that the power operator can take a
>>>  function right argument. In this case, that function can be
>>>  either monadic or dyadic, and can be a lambda.
>>>  If it’s monadic:
>>> 
>>>    (F⍣G) ⍵  ←→  ⍵ ←   F ⍵  until          G ⍵
>>>  ⍺ (F⍣G) ⍵  ←→  ⍵ ← ⍺ F ⍵  until          G ⍵
>>> 
>>>  If it’s dyadic:
>>> 
>>>    (F⍣G) ⍵  ←→  ⍵ ←   F ⍵  until  (  F ⍵) G ⍵
>>>  ⍺ (F⍣G) ⍵  ←→  ⍵ ← ⍺ F ⍵  until  (⍺ F ⍵) G ⍵
>>> 
>>>  (Note that G is checked before the first time F is executed.)
>>> 
>>>  I don’t know what the ISO standard says on this, but in GNU APL,
>>>  dyadic G works as in Dyalog. However, “monadic” lambda G has to
>>>  be a weird function that takes both a left and a right argument,
>>>  and discards the left one. That is:
>>> 
>>>  Dyalog: GNU:
>>>  F⍣{G ⍵} F⍣{⍺⊢G ⍵}
>>> 
>>>  Is this because lambdas can’t be ambivalent? If so, I see two
>>>  solutions:
>>> 
>>>  - Make ⍣ check G’s valence.
>>> 
>>>  - Better: I know it’s possible to write an ambivalent tradfn
>>>    (function defined with the ∇-editor) by using ⎕NC on the
>>>    left argument; wouldn’t it be possible to implement lambdas
>>>    containing only ⍵ as ambivalent, so ⍺ is simply never used
>>>    even if it is defined (or defined even if it isn’t used)?
>>>    In fact, dyadic tradfns work in this way.
>>> 
>>>  Not only would this allow for cleaner use of ⍣, but it would
>>>  also allow for “cleaner” case statements in lambdas:
>>> 
>>>  {⍎(‘case0’ ‘case1’ ‘case2’ ‘etc.’)[condition]}
>>> 
>>>  which is probably the only place one would use this.
>>> 
>>>  As of now, if ⍺ is present in one of the case statements but
>>>  not in the rest of the function, then ⍺⊢ must be prepended to
>>>  the lambda.
>>> 
>>>  While on the subject of lambdas, IMHO variables assigned inside
>>>  lambdas should be made local. More than once I’ve used a named
>>>  lambda in a tradfn and have found that one of its local variables
>>>  was modified by the lambda. Although I imagine named lambdas must
>>>  be a pain to implement.
>>> 
>>>  Also, I noticed that the assignment of a lambda to a name
>>>  returns a vector of the name of the lambda. It would be
>>>  interesting if it could return the actual lambda (of course this
>>>  probably isn’t feasible, since it would require function
>>>  returning expressions, a.k.a. tacit programming).
>>> 
>>> 
>>> Now on to the bugs:
>>> 
>>> 
>>>       (g d)←'ATCTGAT' 'TGCATA'
>>>       {((1↓X)Y((⊃X),Z)),[¯.5]X(1↓Y)((⊃Y),Z)⊣(X Y Z)←⍵}g d ⍬
>>>  TCTGAT  ATCTGAT 
>>>  TGCATA  GCATA   
>>>  ATCTGAT TGCATA  
>>>       {((1↓X)Y((⊃X),Z)),[.5]X(1↓Y)((⊃Y),Z)⊣(X Y Z)←⍵}g d ⍬
>>>  TCTGAT  ATCTGAT 
>>>  TGCATA  GCATA   
>>>  ATCTGAT TGCATA
>>> 
>>> These should be transposed. ⎕IO ←→ 0, so ,[¯.5] should give a two row,
>>> three column matrix.
>>> 
>>> 
>>> ←———————            -            -            -            ———————→ 
>>> 
>>> 
>>>       )SI
>>> ⋆⋆  
>>> 
>>> ==============================================================================
>>> Assertion failed: idx < items_valid
>>> in Function:      operator[]
>>> in file:          ./Simple_string.hh:140
>>> 
>>> Call stack:
>>> 
>>> ----------------------------------------
>>> -- Stack trace at ./Simple_string.hh:140
>>> ----------------------------------------
>>> 0xa @@@@
>>> 0xa  @@@@
>>> 0xa   @@@@
>>> 0xa    @@@@
>>> 0xa     @@@@
>>> 0xa      @@@@
>>> 0xa       @@@@
>>> 0xa        @@@@
>>> 0xa         @@@@
>>> ========================================
>>> 
>>> SI stack:
>>> 
>>> Depth:      9
>>> Exec:       0x7f98db4177b0
>>> Safe exec:  0
>>> Pmode:    ⍎  (1↓R)((=/0⌷¨V)↓⍵⊃⍨~⍺)((2⊃⍵),1↑R←⍺⊃V)
>>> PC:       27 /
>>> Stat:     (1↓R)((=/0⌷¨V)↓⍵⊃⍨~⍺)((2⊃⍵),1↑R←⍺⊃V)
>>> err_code: 0x50005
>>> thrown:   at Value.cc <http://value.cc/>:1051
>>> e_msg_1:  'INDEX ERROR+'
>>> e_msg_2:  '      (1↓R)((=/0⌷¨V)↓⍵⊃⍨∼⍺)((2⊃⍵),1↑R←⍺⊃V)'
>>> e_msg_3:  '               ^           ^'
>>> 
>>> Depth:      8
>>> Exec:       0x7f98db41b9f0
>>> Safe exec:  0
>>> Pmode:    ∇ 
>>> ==============================================================================
>>> Assertion failed: idx < items_valid
>>> in Function:      operator[]
>>> in file:          ./Simple_string.hh:140
>>> 
>>> Call stack:
>>> *** do_Assert() called recursively ***
>>> ==============================================================================
>>> *** immediate_execution() caught other exception ***
>>> 
>>> I’m sorry I couldn’t include the input preceding that )SI, it's long and 
>>> very
>>> hard to reproduce. I hope this is enough to help :-⌈
>>> 
>>> ~———~
>>> 
>>> I’d like to thank you for your very hard work. I don’t know of any other APL
>>> which adheres to the standard while being as bug free as yours, and is a
>>> one-man project. Let alone all three!
>>> Keep in mind everything I suggest is the personal opinion of someone with 
>>> very
>>> little experience with C++ish languages. I’m sure you know better than I do 
>>> how
>>> to shape your APL. After all, you’re the one writing it!
>>> 
>>> Best of luck,
>>> Louis
>>> 

Reply via email to