On Sat, Nov 23, 2002 at 08:46:03PM -0600, Me wrote: : First, I'd like to confirm I've understood : C<temp> and C<let> right: : : 1. C<temp> dynamically scopes changes to a : variable's value to the enclosing block. : It does not dynamically scope the name. : The variable can obviously be a global. : It can also make sense if it is lexical. : Is the latter currently allowed?
I'm planning to allow it unless someone can come up with a good reason not to. : 2. C<let> is a conditional C<temp>; it only : restores a variable's value if, on exit : from the enclosing block, the block is : somehow considered to have "failed". It : can be applied to a global or lexical. At the moment, it doesn't apply to either. It applies only to the current regex's variables. It is a bit of an inconsistency that in the current model, regex variables are lexically scoped but not actually declared. This may be a mistake. : The above two features are basically sugar : for what would otherwise be achieved with : paired FIRST/LAST/UNDO blocks. Well, there's no UNDO defined for regex backtracking unless we define some kind of BACK block, but conceptually you're basically right. : Both must be applied to an existing variable. Not strictly true. if you say /foo bar { let $baz = 2 } / the $baz is creating a new variable within the scope of the surrounding regex. : Next, I want to do a better job of stating : a problem I wonder about: : : Consider "environmental" values such as : "screen sizes, graphics contexts, file : handles, environment variables, and : foreign interface environment handles." [1] : : Consider a sub One that is going to call : a 10 deep stack of subs such that sub Ten : needs to access one of these environmental : values. How do you pass the data? : : A. Globals. Bad. Disastrous in threads. : : B. Passed as args to all intervening subs. : Verbose. Sometimes incredibly verbose. : : C. Aggregate info into objects. But then : you still have to do either 1 or 2 above : with the object references. And it's a : shame to be forced to the object paradigm : unnecessarily. : : D. Use $CALLERS::. Relatively succinct, but : definitely error-prone and ugly. But you haven't mentioned what's really going on with package variables: E. Passed via thread-local storage. Under I-threads, package variables are *not* shared by default among threads, so they can be scoped dynamically without the threading problems of A. Package variables are global only if you squint really hard. : Given what I understand of Perl 6 syntax, : Parrot, and Perl philosophy, I suspect P6 : should, and could fairly easily, provide a : good solution to the problem outlined above. : : Does anyone agree the problem I've outlined : is inadequately addressed by $CALLERS::? The real question is, do I agree. :-) : In previous emails I've suggested: : : 1. The notion of something like attaching : a C<passed> property on variables, and : picking appropriate defaults for its : args (not/ro/rw), to allow the writer : of a sub to easily strictly limit what : a called sub can access. I think the granularity is wrong on this. Trying to mesh the namespaces of caller and callee is a big problem as soon as you have multiple callees with different ideas. In other words, I think it's probably a mistake to try to generalize implicit $_ passing to any name. : 2. The notion of args that are explicitly : defined in a sub's sig but implicitly : passed. This kills most of the verbosity : of B above, while, in combination with : the previous point, being otherwise just : as safe as passing args explicitly all : the way down the call stack. We already have currying, and I think that notion should be extended to handle any caller-instituted defaulting. The granularity can be controlled on a sub-by-sub or on a class-by-class basis. # curry sub my $DBhandle = mumble(); my &shortcut ::= &longcut.assuming(handle => $DBhandle); # curry all methods of a class use Dog.assuming(tail => "cut_short", ears => "cut_long"); my $little_dog = Dog.where_oh_where(); or some such. If there are early-binding/late-binding issues we should address those as part of the currying design. For instance, it's not clear above whether $DBhandle is evaluated at compile time or run time. I think we have to say that it's a binding, which means the value of handle depends on the *current* value of $DBhandle each time the shortcut is called. Basically, the parameter list of the subroutine is already providing a limited namespace to be shared by caller and callee. If the caller really wants to bind to a variable of the same name, they can always say my $bar; &foo.assuming(bar => $bar) But I think it would be wrong for the callee to start forcing its namespace into the namespace of the caller beyond what we already do with named parameter syntax (and $_). Larry