« first day (1490 days earlier)      last day (1182 days later) » 
00:00 - 20:0020:00 - 00:00

ngn
12:45 AM
@Bubbler not much signal÷noise unfortunately
 
@ngn which parts would you consider to be "signal"?
 
Well, zero is a valid value for "not much"
though at least we know that multiple people have thought of introducing typing into APL, and they have some disagreements
 
@ngn objectively, there has been much less actual APL code pasted in the last few hours
in fact, I can't find any without pressing load older messages
 
<moon-child> does f←{×⌿⍺∘.+⍵} not count?
 
not really, it was just examples
more subjectively, there has been less helping and more opinions
my font is almost usable for APL now!
 
1:07 AM
cool! looks... interesting
 
but ↑↓ are rendered as double-struck F, a problem from when I was trying to do BQN
@rak1507 I promise it's not that ugly when it's set to the perfect pixel aligned size
 
@Wezl neat, I'd have to look at some real code to see, I don't think it's the type of thing I'd use but I can see why people would
 
 
ok, that does actually look quite cool
 
I use it for the same reason parents put toddler's art on refridgerators
 
1:10 AM
lol
 
gtg now
 
cya
 
 
3 hours later…
4:17 AM
Hi, does anyone know the idiomatic way to check if a string is found within a vector of strings? eg.
v ← 'foo' 'bar' 'baz' 'buzz'

'bar' ≡ 'bar' ⍝ and
'bar' ≡ 'baz'

... return 1 and 0 as expected, but

'bar' ≡ v ⍝ doesn't work

Using GNU APL so APL2-compatible solutions would be appreciated!
 
@Russtopia Something like this? "foo" "bar" "test" ≡¨ ⊂"foo"
 
(⊂'bar') ∊ v I think
 
Aw geez, I had tried variations of that, I knew it must have needed ≡¨ and ⊂ but I guess I just hadn't gotten it right! That gives me the bool vector. Hmm I need to study that and why I didn't get it right.
Thanks!
@Bubbler wow that's even better, all in one step. More studying to do, thanks
Ah, I'd tried applying ⊃ to v, but your solution is from the other side, making the search str into an array -- ok that makes some sense
 
4:37 AM
OK, I apologise for the soapbox, but I now think I have another reason why dfn's are not optimised in Dyalog: It's hard, and I'm not sure it's really that important.
I specifically wanted to make {⍺+⍵}/⍳N roughly the same speed as +/⍳N. After I implemented support for specialised arrays, the latter is significantly faster in both KAP and Dyalog.
Turns out that in order to show that {⍺+⍵} is equvalent to + in the general case (not specifically just a single function) you need to do flow analysis to determine where the arguments are used.
 
<moon-child> @EliasMårtenson have you seen j's 13 :?
 
No. What is that?
 
<moon-child> automatically derives tacit forms from direct ones
 
Hmm, I'm guessing it does that through some kind of pattern matching?
 
<moon-child> not sure how the implementation works, would have to check the source
<moon-child> the problem isn't flow analysis, but name resolution / late binding. E.G. imagine f←{x⍵}. Depending on if you follow that with x←+ or x←5, the 'fast' form looks very different
 
4:51 AM
That's not a problem in KAP though since you cannot reassign functions to values and vice versa.
 
<moon-child> but do you require forward declaration?
 
@EliasMårtenson yeah, sounds like it needs the equivalent of a regex library for tacit
 
<moon-child> if not, then either you don't allow corecursive functions (bad), or you have the same issue as dyalog. Dyalog doesn't allow changing name class either fwiw; x←5⋄x←+ will fail
 
Oh wow... The JVM just gave me the weirdest problem. I mean, dynamic compilation is great and all, but this issue is bizarre. The following code runs in 0.5 seconds in KAP: +/⍳1000000000. I can run that code repeatedly and it consistently takes roughly 0.5 seconds. However, if I change the code around a bit, trying various variations such as +/1+⍳1000000000, then after a while things seems to slow down.
And when that happens, +/⍳1000000000 (the same as the original snippet) will now consistently run for 2 seconds instead of 0.5. No matter what I do, it's now running 4 times slower.
The only explanation I have is that the dynamic compiler recompiled the code in a more inefficient way.
(it's not GC by the way, I forced GC before the test function)
I do allow corecursive functions. You can refdefine a function. You just can't make a function into a value.
 
4:56 AM
But yes, after function redefinition I would have to reanalyse the code using them.
 
5:11 AM
moon-child, thank you. I will read it.
 
6:01 AM
I was reading this, and I don't understand this quote: "The following J example does not use reduction, and is therefore not readily expressed using APL scan:" with the example J code being: <\ 'abcdef'
What does <\ do in J?
 
6:18 AM
<moon-child> monadic < is box, like enclose
<moon-child> and \ applies a verb to every prefix of its argument
<moon-child> so <\'abcdef' is like 'a' 'ab' 'abc' 'abcd' 'abcde' 'abcdef'
 
Yeah. APL's scan is roughly translated to f/\ in J
 
But is it different from APL's ,\'abcdefgh'?
 
6:34 AM
It just happens to be visually same
 
@EliasMårtenson The first element will be a vector in J but a scalar in APL, methinks.
 
^
 
However, this only holds for simple vectors.
 
7:20 AM
@arcfide i first asked chat.stackexchange.com/transcript/52405?m=57112571#57112571 , i don't care of its benefits over standard apl as i suspect it would be rather awful as mentioned by you, rather, i'm wondering how a typed apl would look like, how much do you really need to sacrifice or how many restrictions would really be needed. (for context, i was initially thinking of a calculus of constructions cum apl)
 
RGS
7:34 AM
@ngn At this point I am just confused, can you help me understand what examples help show which way around it is?
 
@Wezl nice fonts! an interactive demo would be nice. here is my take: ktye.github.io/ui.html#ui.k (there should be a black screen you can type on). this is the source that includes the font: ktye.github.io/ui.k
 
7:50 AM
@RGS I can.
 
RGS
Yes, please.
 
 
2 hours later…
9:51 AM
@EliasMårtenson I think it's the compiler is inlining & assuming things while evaluating that because it sees only one thing ever happening, but on the other expressions it's forced to deoptimize
(and a native build is forced to consider all paths from the start, so has that slowdown always)
 
 
1 hour later…
11:02 AM
@dzaima Yeah, I figure it's something like that. The problem in this case is that the initial version runs 4 times faster than whatever the JVM comes up with later. It doesn't realise that its new version is much slower.
I'm hoping this is only a problem with microbenchmarks, or I will have to start digging into how one can tune the JVM bytecode compiler.
And I can think of about 69420 other things that are more entertaining than that.
 
@EliasMårtenson microbenchmarks will stay artificially inflated, yeah. There's not much to tune here - inlining everything is faster than inlining nothing
 
@dzaima Well, here we have a case where whatever the bytecode compiler decided to do, made the code 4 time slower.
 
@EliasMårtenson I think it's out of necessity. When compiling just +/⍳10000 it can assume that + will have both arguments as scalars. But after +/1+⍳10000 it realizes that's not true always, and now has to check on every invocation of + (or something like that idk what your impl actually does)
you'd ideally want the jvm to constantly reoptimize every builtin & function on every new line of KAP code executed, but that's quite a bit of work
 
<moon-child> isn't that, like, the whole point of jits compared with pgo?
 
11:17 AM
moon-child: JVM JIT is pretty much just PGO done dynamically
 
<moon-child> well, yes, exactly
 
except that the JVM doesn't need to generate unlikely code until it's actually needed
while compiling + it can just inline the invocation in whatever pervasion implementation (or even straight into the impl of /), assuming other pervasive builtins don't exist, for example. And when another one's class file is loaded in, it's forced to deoptimize that
@dzaima (and it kind of has to do that in the case of Java - the overwhelming majority of inline-worthy functions aren't marked final and thus can technically be overridden dynamically by loading in another class file (kotlin is better in this aspect with open and final by default))
 
11:34 AM
Yes, that's true
It would be nice if there was a tool that allowed me to see the optimisations that the JVM performed. This is the first time since I started working with Java in 1996 that I have seen such a weird optimisation edge case.
Perhaps there is.
 
@EliasMårtenson there definitely are flags to the JVM to make it spam you with a mess of optimization information. Problem is, it spams you with a mess of optimization information
-XX:+PrintCompilation
 
11:53 AM
@dzaima Thanks. I have seen that flag before. I've never used it though. Have you used it with good effect?
 
@EliasMårtenson not really. I haven't actually tried to micro-optimize for the JVM since I don't intend for it to stay my language of choice forever
I did once try to see the assembly it generated (to see if it vectorized loops), but that's an even bigger mess I got myself into
 
12:14 PM
@dzaima Does it vectorise loops?
It should, no?
 
@EliasMårtenson it does in the simple cases, but when you introduce overflow checking, it obviously breaks
 
@dzaima So somehow the compiler needs to prove that overflows can't happen.
 
@EliasMårtenson but they definitely can
 
Perhaps Java needs annotations similar to Common Lisp where you can tell the compiler to elide bounds checking for performance critical code.
KAP could definitely benefit from that.
 
@EliasMårtenson oh, i mean overflows as in 2 2147483647+5 2147483647 not array length overflow
 
12:17 PM
I mean array length overflow
@dzaima But Common Lisp allows you to assert things like "variable x is guaranteed to always fit in a register, so don't worry about checking if it needs bignum-extending"
 
and similarly for unsafe casts too. If I wanted to hard enough, it might be fun to hack the compiler to not include them, but I don't
@EliasMårtenson but I can't do that in BQN
 
Or you can say: "variable y is an integer between 0 and 10".
 
I have to have 2‿2147483647+5‿2147483647 fall back to a float array
 
@dzaima Same in KAP. We're both hampered by the same limitations.
@dzaima I want to bugnum-extend.
 
@EliasMårtenson right, but same problem - it has to be a dynamic check, and an if in a for loop will make vectorizing nearly impossible
@dzaima therefore, singeli. I definitely plan to try to integrate it into dzaima/BQN
 
12:20 PM
One solution I'm considering is if I have two integers A and B which both fit in a Long, so when adding them the optimised path is called (fun add(a: Long, b: Long): Long), but if the result overflows I throw an exception that contains the result as a bignum.
Because in the JVM, a try/catch is very lightweight if an exception is not thrown.
 
@EliasMårtenson "that contains the result as a bignum" oh that's fun :D
(fwiw i'm currently using Math.addExact and catching and returning null in the loop case, and just don't have scalar integers)
 
I have only thought of two other solutions: One being a special value that is updated in s different place (thread-local perhaps?) and the other being a special integer value (Long.MAX_VALUE perhaps) which can act as a sentinel value indicating that the value is not valid.
@dzaima But that limits your integer size to 56 bits, no?
 
@EliasMårtenson right, I have a completely separate biginteger type
 
My problem with bignum is that I support JS and Native as well, so I have to implement the bignum stuff 3 times :-)
Also, it means brining in a bignum library for JS, which means touching NPM, which means pain and suffering.
 
@EliasMårtenson JS has native bigints (if you restrict yourself to modern JS which you really should anyways)
 
12:25 PM
@dzaima I know no JS since 2001.
 
@EliasMårtenson 3n**100n
 
That's a lie. I know a bit. But I haven't actually written JS in the last 10 years.
@dzaima What about bigdecimal?
 
@EliasMårtenson what is bigdecimal? :p
 
Ideally I'd like to do bigfloats as well.
@dzaima A fraction... yes :-)
 
@EliasMårtenson implementing fractions as a pair of bigints is simple enough
 
12:27 PM
Yeah. True rational numbers are also on the todo list.
 
and you won't get a JS library precisely matcing Java's BigDecimal anyways
 
@dzaima Fair enough. Probably better to add that on a higher level, building it all on a simple bigint library. That allows me to leveral GMP for the native backend.
The thing that scares me though it making sure that all numerical operations support the type tower.
KAP still doesn't do the right thing for complex numbers for certain trignometric functions (I think I only support complex numbers for sin/cos/tan. And I don't even have the hyperbolic functions yet.
The thought of computing the correct result for arctan for a massive rational number is somewhat terrifying
 
@EliasMårtenson oh, I just wouldn't bother allowing (even suggest explicitly disallowing!) trig ops on non-floaing-point types
 
@dzaima Well, Lisp allows it. :-)
I guess for many functions just coercing to the closest double/complex double would be sufficient.
 
1:36 PM
@MortenKromberg /usr/local/bin/dyalogscript is like all xmases came at once.
Now I have to rewrite my workflow chapter.
 
@xpqz ... and it is still only half baked :)
 
Thanks for making it work on the Mac, too.
 
 
1 hour later…
2:39 PM
@Adám Hello, APLers! I made my "unofficial" announcement of the Dyalog's student competition at CodeForces, a large competitive programming platform: codeforces.com/blog/entry/88048 – This post already gained some attention. So let me know if there are any critical mistakes in this post. @MortenKromberg, @Adám
 
2:55 PM
@ktye not exactly interactive, but you can try it at ermineii.github.io/poultre.html > click drop-down > poultreMono
 
@AndriyMakukha Nice! I've always wondered about trying to get codeforces to support APL but I doubt it will ever happen
 
3:10 PM
nice
 
3:22 PM
@ktye how did you make this (the ui.k file)?
 
@rak1507 , yeah, compared to SPOJ.com, AtCoder or even Open Kattis, CodeForces is much more boring in their language choices. But posting some blogs at CodeForces related to APL could be a good first step. For example, if someone posted elegant and concise APL solutions to a few problems from their archive, it could help promote the language, I believe.
 
@AndriyMakukha I'll keep that in mind! I've done a few in APL before but none were particularly interesting, maybe if I spot something that would be nice in it I'll post it
 
@AndriyMakukha Kattis will add APL "soon".
 
3:38 PM
@Adám Yeah, they told me the same 5 months ago. And I'm still waiting for that to happen.
 
3:51 PM
@AndriyMakukha which ones are worth joining?
 
Twitching soon…
 
4:19 PM
@Razetime These platforms are all good for studying algorithms and practicing coding. However, my favorites are CodeForces and Open Kattis.
@Razetime CodeForces publishes all solutions by all participants as open-source. So if you are stuck on a problem, you can learn by reading someone else's code. It also has lots of educational editorials, blogs, useful discussions and even live-streaming.
@Razetime Unlike feature-rich CodeForces, Open Kattis, on the other hand, is extremely spartan and simple. And there is a charm to it. Additionally, this problem archive is covered in a book on competitive programming by a Singaporean professor. (I don't have that book, but it would be handy to get "unstuck" if you can't get some problem right.)
 
4:36 PM
nice
I just joined all the sites I could find links to
 
{{_←⎕DL ⍵ ⋄ ⎕←⍵}&¨⍵} @Razetime
 
ah &
smh not even using rank
 
lol
 
hm, rank doesn't work
 
5:35 PM
Returning to what is probably a lost cause (arguing in this forum that Dynamic Scope is somehow "simpler" than Lexical), I think you provided a clue with your comment that "all dynamic scope does is lose information". I think that is exactly it: there is less information required to understand "what a function does" in Dynamic scope.

I am trying to chose my words carefully here: I am not claiming that dynamic scope makes it easier to predict what the entire system does, only what the individual function is trying to express.
 
'functions shouldn't tamper with the environment' and 'functions should be able to modify values in its caller' are mutually exclusive
 
@rak1507 True, hence the qualification: there has to be a very significant benefit from doing it, that outweighs the potential confusion.
 
I also disagree with 'there is less information required to understand "what a function does" in Dynamic scope. ', as you need to know exactly what every called function does. Can you tell me what {a←⍵ ⋄ _←foo ⋄ a} returns?
 
@rak1507 Yes I can, it returns the value of a after calling foo.
 
∇foo
→
∇
No it doesn't
 
5:47 PM
@rak1507 Naked branches, or branches of any description, are frowned upon in any real APL systems written since about 1990.
@rak1507 I am not sure lexical scope would help you there, would it?
 
Nope, that was just a 'fun' answer, the point is that there's no clear way to analyse exactly what a function returns without knowing exactly how everything it calls works
Dynamic scope requires more information to fully know what something does
 
@rak1507 It depends on the definition of "does". The function calls a function called foo and then returns the value of a. That is a 100% COMPLETE description of what the function does. It depends not only on the "value" of a, but also the "value" of foo - but you can see that in the source.
@rak1507 The same way that you can reason about what an operator does without knowing what the operands are.
(except of course foo could be a variable)
 
I guess my main issue is that with dynamic scope, there's no way of knowing just from the function calls if there are any side effects and what they do
There's no way to call a black box function and be confident it won't change anything you don't want it to without checking beforehand
 
@MortenKromberg Dynamic scope doesn't at all change how much information is required to understand what a function does. It just makes it harder to find, which I guess is what you see as a benefit
 
@rak1507 Anyway, I really just wanted to thank @dzaima for helping me realise what it is that makes Dynamic scope feel simpler TO ME. Not claiming it is better for "programming in the large". I think I might claim that it is better for writing simple models of the style that APL was originally invented for. Like the fact that one of the attractive things about spreadsheets is that you can always refer to a cell, you don't have to pass it to every function that will need access to it.
 
6:00 PM
Cells in spreadsheets are more like globals
 
Yes, and the nice thing about Dynamic scope is you can replace the globals behind the back of some code and still have it work, without having to refactor it (I can hear the screaming echoing down the wires, so I'd better leave now).
 
@MortenKromberg why is ability exclusive to only dynamic scope?
you can change anything you want that given code doesn't touch it with lexical scope too, but at least it's much more clear what could be affected by the change
 
@dzaima OK, I may be ignorant about what is possible with lexical scope systems, but it was my impression that you could not refer to and change values in its caller?
 
@MortenKromberg you can't change things in the caller, but you can change things in the surrounding (as in the source code) function
 
Right, so any values you want to change need to already be in your lexical scope.
 
6:09 PM
often the two are the same (well i guess not in Dyalog as you can't nest -fns)
@MortenKromberg you can add things inside the lexical scope without needing to refactor everything
 
@dzaima I'm not sure we're really disagreeing about anything(?). Lexical scope allows you to group things together and predict how the whole construct will work. Dynamic scope allows you mix stuff up in ways that are ultimately less predicable but require less up-front planning (which you may regret later).
@dzaima @rak1507 Perhaps we do disagree about whether dynamic scope ever has any merit whatsoever :D
 
Maybe, somehow I don't think either of us will convince anyone else. Oh well, always interesting to hear an alternative point of view
 
"require less up-front planning" do you actually change which scope you want a function to read from or mutate often enough for dynamic scope to be beneficial?
 
While we're on scope... this is still weird to me, even after I understand it:
F1←{ ⍝ Can you spot the bug?
    11::nums
    nums←1 ⍺
    nums×÷⍵
}
 
@xpqz The potential VALUE ERROR if ⍵ is 0 (unless nums already existed as a global value)?
 
6:20 PM
Yeah
 
@xpqz dfns create a new scope per statement or something
 
Further, the mere presence of an error guard disables tail call optimisation, apparently
 
@dzaima error guards are like a time machine and roll the state back
 
My expectation (before @Adám explained it) was:
F2←{
    nums←1 ⍺
    0=⍵:nums
    nums×÷⍵
}
 
@dzaima Probably not, but then I also don't modify semi-global values often enough for dynamic scope to be a problem. But believe it or not, lexical scope still feels so hard to accept when writing APL, I think because the fundamental unit of thought for me is the function. Nested functions make my head hurt. Why would you write a function that can only be used in one place, etc...
 
6:29 PM
Why use namespaces then?
 
ngn
@MortenKromberg to sort a vector?
 
..or pass to an operator?
 
no clearly you should do
∇sortvector v
sorted_vector←v[⍋v]
 
@MortenKromberg right, if you only access local variables 99% of the time, lexical and dynamic scope are equally good 99% of the time. We're discussing the 1% here though
 
ngn
@rak1507 is that a recognized idiom?
 
6:32 PM
@ngn I'm kidding if you didn't realise
 
@ngn I am comfortable with small dfns, which I think of as explicit (as opposed to tacit) compositions. Multi-line embedded dfns is where I start to feel uncomfortable.
Please note that I'm not trying to convince any of you that I'm right and you are wrong, that dynamic is better than lexical, I'm trying to explore this feeling that I still have that dynamic scope is simpler, in order to understand it.
APL is a tool of thought, and if it doesn't help me think, it ain't working
 
Me neither, not trying to be too argumentative although it probably comes across like that
 
@dzaima (except when you forget to shadow locals of course; imo it should be the other way around, that you specify non-locals instead)
@MortenKromberg I'm trying to understand your feeling of it being simpler too :p
 
@dzaima Yes: one of the things that I think we SHOULD do is come up with a way to write a tradfn in which all names which are defined using assignment in the body of the function are automatically localised.
 
That would be a great addition
 
6:38 PM
The thing that will shock you is that I'm also wondering whether we need an inline way to write them so you can have "lambdas" with Dynamic scope.
 
IMO, using to close the line editor was among the biggest ever design mistakes of APL. An it isn't even "core language" or even "language".
If it had been then lexical scope would have become an APL thing much earlier, since nesting functions would have been obvious. Without nestable functions, lexical scope can't work.
 
ngn
@MortenKromberg great idea :)
(that would make more apl users switch to k. evil giggle)
 
That said, it bothers me that InnerProcess has to be redefined *for every element of largeData:
OuterProcess←{
    acc←⍬
    InnerProcess←{
        ⍝ long complicated
        ⍝ function that
        ⍝ eventually
        ⍝ computes a
        condition←?2
        ⍝ then does
        condition:acc,←⍵
    }
    acc⊣Process¨⍵
}
OuterProcess¨largeData
I cannot define InnerProcess once and for all, outside OuterProcess because of lexical scoping.
If I write one of the two processing functions as a tradfn, then lexical scoping applies, and I can get away with defining InnerProcess only once.
 
I know it sounds bizarre: The reason for this is that many existing apps are starting to become littered with little dfns, because of the attraction of writing short inline expressions with locals that do not escape. This works fine until you get a mixture of dynamically and lexically scoped things on the stack, at which point the programmers who are used to dynamic scope can get very confused about the situation they have created.
 
@yiyus Interested in APL as well as K?
 
6:46 PM
People who don't like "dynamically scoped lambdas" should not use them
Fortunately for you'll, that was the dinner gong, so I won't subject you to any more retro dynamic thinking today :).
 
@MortenKromberg Help is on the way:
┌─────────┬───────┬───────┐
│↓ calls →│dfn    │tradfn │
├─────────┼───────┼───────┤
│dfn      │lexical│dynamic│
├─────────┼───────┼───────┤
│tradfn   │dynamic│dynamic│
└─────────┴───────┴───────┘
Now, to throw in operators in the mix… that's a whole other can of worms.
 
A tradfn calling a dfn is dynamic?
 
ngn
@RGS ^ not sure if adam got it right
 
@Wezl the glyphs are bitmaps encoded in char vectors. 0x... are char literals in that version of k. the font has been created with the great Windows paint. here are more fonts and converters: github.com/ktye/i/tree/master/_/i2/kui/f
 
ngn
7:07 PM
@rak1507 maybe he was confused because the dfn can see the tradfn's locals but not modify them
"semi-dynamic"?
 
maybe, all confusing
 
@ngn Are you sure?
      ∇ y←Outer y
        Inner⍬
      ∇
      Inner←{y⊢←'inner'}
      Outer 'outer'
inner
 
ah modified assignment
 
@rak1507 Nah, any non-localising thing will do:
      ∇ y←Outer y;F
        F←1∘+
        Inner⍬
        y←F y
      ∇
      Inner←{⎕FX,⊂'F←{2+⍵}'}
      Outer 10
12
Clearly, the dfn is modifying a local name in the tradfn.
 
7:23 PM
ah I don't know what ⎕FX is
looks like it
confusing
 
FiX function, i.e. define function.
That's dynamic scope.
 
ngn
@Adám i meant normal assignment
 
Doesn't this work in dfns as well though?
⋄ {a←1 ⋄ _←{a⊢←2}⍬ ⋄ a} ⍬
 
@rak1507 2
 
@ngn Normal assignment in an inner dfn can't affect a name in its defining scope either.
 
ngn
7:25 PM
@Adám but in a tradfn it can affect the calling tradfn's locals
 
@ngn but modified assignment still allows mutating dynamic scope, so it's dynamic scope
 
⋄ {f←1∘+ ⋄ _←{⎕FX,⊂'f←{2+⍵}'}⍬ ⋄ f ⍵} 2
 
@rak1507 Illegal code
 
curse you bot!
 
@rak1507 That's lexical. And no: ⋄ I←{a⊢←2} ⋄ a←0 ⋄ {a←1 ⋄ _←I⍬ ⋄ a} ⍬
 
7:25 PM
@ngn why does normal assignment and normal assignment only dictate what is static vs lexical assignment?
 
@DyalogAPL Hey?
@ngn Not if that name is localised in the callee.
Always remember that plain name← in a dfn really means name←(⎕SHADOW'name')⊢
 
ngn
@dzaima no good reason. it's just what i used when testing.
 
@ngn so you were the confused one, not Adám
 
And if you do the latter in a tradfn, then it won't touch the caller's variable either.
@ngn Turns out you were testing the auto-shadowing rather than the scoping.
 
ngn
@dzaima well, if normal assignment doesn't work, it's not quite dynamic scope, is it?
 
7:28 PM
I'm confused as well! :(
tldr: use dfns everywhere, avoid complex scoping rules? sounds good to me
 
@ngn just judging by only regular assignment, you'd get that dfns aren't lexically scoped either (i.e. equivalent to k)
 
ngn
@dzaima no. you're mixing up too many things that should be independent.
one is the scoping. when i mention "a", does it refer to the variable "a" in the caller's env, or in the lexically surrounding scope.
how to modify it is another thing
k limits the available "scopes" only to local and global, it ignores everything between them, and yeah, that's bad :(
 
@ngn So, with that definition, is this clear enough?
      ∇ Outer
        g←'caller''s env'
        Inner⍬
      ∇
      g←'lexically surrounding scope'
      Inner←{g}
      Outer
caller's env
 
@ngn if there's no a← (or ⎕shadow or whatever) in the dfn, then a dfn called from a tradfn is viewing a by dynamic scope.
 
ngn
@ngn but k is lexically scoped. it would never try to modify the caller's locals.
 
7:35 PM
@ngn I wouldn't call k lexically scoped. it's no-scoped :)
 
ngn
@dzaima ok, whatever. just not dynamically scoped :)
 
@ngn and, as I said, by looking at just modification (and ignoring modified assignment which you want to for some reason), you can't modify any parent variable, so it's also no-scoped
 
ngn
@dzaima i'm not ignoring modified assignment, just recognizing that there are multiple ways to assign
@Adám g is a global?
 
@ngn Oh, my mistake. Forgot to localise ⍨
 
@ngn right. I think in the dynamic vs lexical scope, we should consider the worse offender
 
7:39 PM
      ∇ Outer;g
        g←'caller''s env'
        Inner⍬
      ∇
      g←'lexically surrounding scope'
      Inner←{g}
      Outer
caller's env
      g
lexically surrounding scope
 
ngn
@Adám now i'm confused too :)
why does it resolve the scope of g in inconsistent ways? bug?
 
@ngn it's dynamic scope, as per Adám's table
 
@ngn How is that inconsistent?
 
ngn
@dzaima dynamic scope.. without (plain) assignment to the caller's env?
 
13 mins ago, by ngn
one is the scoping. when i mention "a", does it refer to the variable "a" in the caller's env, or in the lexically surrounding scope.
Where does assignment come into the picture?
 
ngn
7:46 PM
@Adám so, the tradfn-tradfn case is dynamically scoped with both kinds of assignment, but the tradfn-dfn case only with modified assignment
 
@ngn right. But no plain assignment to caller isn't a lexical vs dynamic thing
 
@ngn No, it has nothing to do with assignment.
 
@ngn I don't think there's any value in mentioning regular assignment. It's just hard-coded to always ⎕shadow in a dfn, but not a tradfn
 
ngn
what will happen if one dfn "sees" a local variable from another, but somewhere in the call stack there is a tradfn with a local variable of the same name?
 
@ngn What called the dfn, a dfn or a tradfn?
 
ngn
7:56 PM
@Adám my idea is: dfn calls tradfn calls dfn
(still trying to construct an example)
 
@ngn I.e. the innermost dfn was called by a tradfn, so dynamic scope.
 
ngn
that would violate the lexical scoping of dfns then
 
Apparently, the scoping isn't an inherent property of a function, but rather of a specific type of function call.
 
@ngn but you don't have just dfns here. Dfns don't magically make tradfns too use lexical scope
 
ngn
but dfns themselves are assumed to use lexical scope. at least i did until now..
 
7:59 PM
@ngn This:
      OuterDfn←{
       a←'od'
       TradFn
       }
      ∇ TradFn
        InnerDfn⍬
      ∇
      InnerDfn←{a}
      a←'global'
      OuterDfn⍬
od
 
00:00 - 20:0020:00 - 00:00

« first day (1490 days earlier)      last day (1182 days later) »