I think that's really nice. How about using ⟻ or ⇐ for that? I know that a common argument against it that Jürgen has raised in the past is the limitations of ⎕AV being 256 characters in length. I obviously disagree with that, and feel that ⎕AV provides nothing that ⎕UCS doesn't.
Regards, Elias On 14 August 2016 at 13:40, 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 > > 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]> > 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]> > 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 >> >> >
