From: Allison Randal <[EMAIL PROTECTED]> Date: Sun, 26 Nov 2006 18:14:28 -0800
Bob Rogers wrote: > > - Overall, I want the implementation of dynamic binding to be tied in > more closely with the implementation of globals and lexicals. > Particularly lexicals. They're already operating under the same scope > constraints as locals. They already have storage for named variables > relevant to a particular scope, and the mechanism for handling scopes > within scopes. > > I'm afraid I don't follow you, particularly the "operating under the > same scope constraints" part. It seems to me that lexical variables are > orthogonal to dynamic/global variables, and dynamic binding is purely a > feature of globals. And lexicals are necessarily simpler, because all > possible references are available to the compiler. So nested scopes are > handled by the compiler simply by using a different register. Globals > and dynamic bindings, because they must be visible to code in multiple > compilation units, must necessarily use different mechanisms. The proposal starts off talking about Perl 5's 'local' and Perl 6's 'temp'. They are lexical in nature (though they're more feature-rich than simple lexicals). They only exist within a specific lexical scope, and "roll back" on exiting that scope. They do "roll back" on block exit, but that is a statement about lifetime, not scope. The whole point of dynamic binding is that such bindings are visible outside of the sub where they are bound, which by definition makes them "not lexical" in scope. Do you disagree? Why would dynamic binding only apply to globals? Perl 5's 'local' doesn't apply to lexicals, but Perl 6's 'temp' will. Because I have been assuming that these language constructs *always* introduce a new binding, which is trivial for lexicals, as I've already said: Just allocate a new register and you're done. The extra mechanism is only needed for globals because only global bindings are potentially visible outside the compilation unit that creates the binding (but I've said that, too). But then, prompted by your response, I took another look at S04 and found the following statement near the end of the first section: C<temp> and C<let> temporize or hypotheticalize the value or the variable depending on whether you do assignment or binding. This could mean that "temp" and "let" might not always create new bindings, which would mean that a "rollback" mechanism could indeed be needed for lexicals. I assume this statement can be defactored into the following four: C<temp> temporizes the value if you do assignment. C<temp> temporizes the variable if you do binding. C<let> hypotheticalizes the value if you do assignment. C<let> hypotheticalizes the variable if you do binding. But I'm not at all sure what "assignment" vs "binding" means here, since it appears to refer to syntax that is not shown. I'm also unsure that I understand the difference between temporizing/hypotheticalizing values vs. variables; is this a question of morphing a PMC vs. replacing it in its container? My apologies if these are Perl 6 FAQs, or the answers turn out to be irrelevant to Parrot; I figure I ought to know in order to understand what mechanisms Parrot needs to provide. > - I like the idea of "thread locals": global variables shared across > threads, but with a local value in one particular thread. I'll have to > mull that one over some more. It seems fundamentally different from > "scope locals", to the point of deserving a different way of interacting > with the feature (perhaps more closely tied to the concurrency model > than to variable storage). > > By "local value" I assume you mean "local binding," which (in the > version I posted) would indeed be per-thread. But in what sense are > "global variables shared across threads"? Without the binding, all you > have is the name, which isn't terribly variable. > > And "scope locals" -- aren't all variables local to their scope by > definition, even if that scope happens to be universal? > > So I'm pretty sure I must be misunderstanding something . . . Your proposal mixes two ideas. One is the idea of 'local'/'temp', the other is thread-level dynamic bindings. (I called these two concepts "scope locals" and "thread locals", but "scoped locals" is probably a better term for the first set.) Perhaps, but I did mix them deliberately. After considering several alternatives, I decided that it was most useful to define "dynamic scope" as being thread-local. A more explicit phrasing of my comment about "local value" is: "In the case of a global variable shared across threads, this proposal would make it possible to have a version of the variable local to one specific thread, so changes to that variable within that thread do not affect the variable's value in the other threads." I consider this to be the most interesting idea put forth in the proposal. For the record, the concept is far from original. That's essentially how dynamic bindings behaved on the Lisp Machine of yore, though the mechanism proposed is different. Besides, dynamic binding is not supposed to be interesting; it's supposed to be cheap, simple, and boring, so that it can be used to implement the *really* interesting stuff. ;-} However, your use of the phrase "a version of the variable" makes me wonder if I understand you properly. Does this mean "a variable binding"? If so, why avoid this well-established terminology? And in any case, I still don't understand in what sense such a variable could be "shared across threads" if the binding is not? It seems to me that sharing only the variable name is not sharing the variable. While I'm not accepting the currently proposed implementation, this idea is likely to make it in. Possibly as a lightweight use of STM, possibly as part of the new concurrency model(s), or possibly as a variation on scoped locals. Could you be more specific about the proposed implementation? What issues do you have with it? Is it worth fixing, or should I give up? > - We keep adding hacks to get around the fact that Parrot doesn't > handle scopes smaller than a compilation unit particularly well. If we > tackled that quirk, dynamic binding would likely fall out more > naturally, not to mention exception handlers, lexical variables, etc. > > I'm afraid I don't follow this, either. "Scope" is mostly an HLL > concept; what would Parrot need to do to support them better? Or are > you talking about debugger annotation for variable lifetime? It's true that scope is an HLL concept, but the whole idea of Parrot is to provide tools for implementing HLLs. Parrot's concept of scope is still quite primitive, and not very helpful to compiler writers. Allison Then I'm still in the dark -- or perhaps just lucky. As a compiler writer, the only thing I find "unhelpful" about Parrot in terms of scoping is its lack of dynamic binding. Hence, the patch. -- Bob