@B.Wilson As long as you stick to dfns, it doesn't matter for scoping, only stack manipulation. The capsule of a dfn is simply the largest text wherein that dfn is written.
@B.Wilson No, again, a capsule has nothing to do with scoping, only stack manipulation. If you have mixed tradfns and dfns, then I believe any given dfn's capsule is the outermost dfn wherein the dfn in question is contained.
Stack manipulation includes "cutting to the capsule" on the top of the stack, and signalling out of the capsule.
Okay. I'm mainly wondering how the concept interacts with ⎕SHADOW and Execute, and uh, one-line dfns.
Maybe it doesn't at all. I am just seeing discussions of capsule pope up in discussions of scope here and there.
More clearly, perhaps. I'm wanting to get a crisp understanding of the (funky) scoping behavior of Dyalog. So far, I know relevant concepts to consider include, tradfns, multi-line dfns, one-line dfns, Execute, and ⎕SHADOW. But I'm wondering if I need to worry about any other ontological categories as well, like capsule.
@B.Wilson OK, so there's no difference between multi-line and one-line dfns when it comes to scope. The only difference between them is that you cannot suspend in a one-liner. The things you mention uses dynamic scoping, except for dfn-to-dfn calls which are lexical, and execute sees what its context sees. ⎕SHADOW only applies to tradfns and should be fairly straight-forward. Error guards are dynamic and introduce a scope which we roll back to when triggered. I think that's all.
@user25732704 Hi Jeneliza Magnetico, if you want to participate here, please email [email protected]
Seems pretty material to me. ⍎'a←1' within a lexical boundary introduces or modifies variables outside of said boundary. I'm not sure why comparing with modified assignment is natural at all.
For finding values of names, that's sufficient explanation perhaps, but we're talking about where and how to assign a (potentially new) name. In this case, Execute definitely doesn't do the same thing as "its context".
I didn't say that execute would "do" either. I said that (my emphasis): "execute sees what its context sees"
That is, the scope is the same. There are other differences beween execute and its context. For instance, execute handles multi-line strings and allows control structures in dfns!
But then arguably, execute didn't create the name in the symbol table; it just populated it with a value. Similar to how you can have an unpopulated field in a class:
(⎕FIX':class' ':field public shared a' ':endclass').⎕nl¯2
a
(⎕FIX':class' ':field public shared a' ':endclass').a
VALUE ERROR
(⎕FIX':class' ':field public shared a' ':endclass').a
∧
@B.Wilson OK, I'm using the name "capsule" as I defined above regarding stack manipulation of dfns. But yes, this confirms what I said above that execute sees the same as the code that called it. If foo would shadow a then just as bar cannot see any a outside foo because foo shadows a, so too ⍎ inside bar cannot see (use, create…) any a outside foo because foo shadows a.
Exactly. It's like there are slightly separate mechanisms that define the lexical (context) boundaries between variable references and variable assignments. In the case of a←1 we assign to one context but in ⍎'a←1' we assign to the other.
Oh, sorry for the confusion. The glyph ← is overloaded. It means two very distinct things directly in dfns (not inside ⍎ in dfns) vs everywhere else. Should have been two different glyphs imo.
name←value in a dfn is essentially equivalent to name←value⊣⎕SHADOW'name' outside dfns.
(things get a bit hairy when you have multiple names, but the idea is the same; shadow every name to the left of ← before assigning)
(and this is only for "normal" assignments, not for namespace assignments like ns.name← and not for modified assignments like name+←, and not for hacky assignments like name∘←)
Okay. So ⎕SHADOW effectively is just an explicit way to introduce a lexical boundary that begins at the call site and ends at the enclosing tradfn or dfn?
tradfn only, as I said before, "⎕SHADOW only applies to tradfns"
A very unfortunate effect of the above "everywhere", is that it includes the interactive session. So you might be suspended in a dfn during development, then experiment in the session until you perfect your expression. Then you copy it into your dfn and continue execution, only for your perfected expression to mean something entirely different.
name∘← accidentally derives a monadic function where the left operand is a symbol (as in a symbol table, not a glyph) though Dyalog does its best to avoid exposing symbols.
@B.Wilson You might think that "shadow or not shadow" is a minor difference, but it is actually huge, because APL prohibits overwriting (but not shadowing) nameclasses 2 and 9 with nameclasses 3 and 4, and Dyalog allows multiple assignment without parens, so this is necessary to infer if you're doing multiple assignment, modified assignment, or using the passthrough value from an assignment.