I just realised that ⎕LC is the line counter; I should have written ⎕LCL.

Louis

> On 14 Aug 2016, at 01:37, Louis de Forcrand <[email protected]> wrote:
> 
> 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
> 
>> 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