Re: Dynamic scoping (take 2)
I'm sorry, but I gotta get back on the no-global grail trail for at least one more post. The granularity [of currying] can be controlled on a sub-by-sub or on a class-by-class basis. If one could do something like this: { my $src = 'oldname1'; my $dest = 'newname1'; use FileUtils.default($src, $dest); # FileUtils subs now use $src and/or # $dest if $src and/or $dest args are # not supplied at run-time: foo; foo('oldname2','newname2'); } # FileUtils subs revert to normal sub foo (;$src, $dest) { FileUtils::rename($src, $dest); } where FileUtils is a module (ie one can curry classes OR modules), and where the use XXX.default has something akin to the effect of currying FileUtils sub calls /if the relevant args do not exist/ till the end of the enclosing lexical scope for the current execution thread, and where all of this can be done without a significant hit to performance, then you appear to have completely eliminated the practical need for creating globals and replaced it with a succinct and intuitive way to express what's going on (even if my example above isn't the clearest way to explain it). -- ralph
Re: Dynamic scoping (take 2)
On Mon, Nov 25, 2002 at 02:27:36PM -0800, Randal L. Schwartz wrote: : Simon == Simon Cozens [EMAIL PROTECTED] writes: : : Simon What were the good reasons for not allowing localized lexicals in Perl 5? : : Nobody could explain it in 50 words or less. : : What the hell is 'local my $foo = 35'? That particular form is useless, since the scope of the temporization is the same as the scope of the lexical. But there's no reason not to be able to temporize a file-scoped lexical, for instance, so that it behaves as a global to all the subs in the current file, but is invisible outside the file. Well, hey, that's close to 50 words. :-) Larry
Re: Dynamic scoping (take 2)
so these two are equivalent ??? { my $x is yours ; my $y is yours ; my $z is yours ; 1... sub_a ; 2... } sub sub_a ( ; $x is yours, $y is yours ) { ...3... } ; - same as - # ( here no special meaning for is yours -- just another property ) { my $x is yours ; my $y is yours ; my $z is yours ; 1... #alias %MY to topic so that it can be fetched from sub_a by is given $_ ::= \%MY ; sub_a ; 2... } sub sub_a (;$x is yours, $y is yours ) is given($CALLER_SYMB) { #alias variables from $CALLER_SYMB to the local variables if #requested $SUB_SYMB ::= \%MY ; for $SUB_SYMB.keys { if $SUB_SYMB{$_}.yours and $CALLER_SYMB{$_}.yours { $SUB_SYMB{$_} ::= $CALLER_SYMB{$_} ; } } ; $CALLER_SYMB = undef ; #but better if this happens at compile time # -- probably this have to be forced with #BEGIN 3... } ; arcadi
Re: Dynamic scoping (take 2)
On Sat, Nov 23, 2002 at 08:46:03PM -0600, Me wrote: : First, I'd like to confirm I've understood : Ctemp and Clet right: : : 1. Ctemp 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. Clet is a conditional Ctemp; 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 Cpassed 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
Re: Dynamic scoping (take 2)
[EMAIL PROTECTED] (Larry Wall) writes: :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. What were the good reasons for not allowing localized lexicals in Perl 5? -- User: In 1793 the french king was executed. MegaHAL: HA HA HA! CORRECT. ALTHOUGH, EXECUTED HAS MULTIPLE MEANINGS.
Re: Dynamic scoping (take 2)
Thanks for the clear answers. Larry: I think that currying should be extended to handle any caller-instituted defaulting. Argh. So obvious! (So of course I missed it.) Basically, the parameter list of the subroutine is already providing a limited namespace to be shared by caller and callee. ... 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 $_). Yes. I was following the same principles. But I much prefer your route, that is, to use assuming (a suggested perl lingo replacement for currying) which so clearly fits the bill. I love (natural) brevity, so perhaps one could have .assuming map passed arg values that are variables (rather than pairs) to a target arg of same name: my $tail = cut_short; my $ears = cut_long; Dog.assuming($tail, $ears); What's the briefest way to say: for [Dog, Devil] { use .assuming($tail, $ears) }; Presumably this won't work: use (DogDevil).assuming($tail, $ears); -- ralph
Re: Dynamic scoping (take 2)
Simon == Simon Cozens [EMAIL PROTECTED] writes: Simon What were the good reasons for not allowing localized lexicals in Perl 5? Nobody could explain it in 50 words or less. What the hell is 'local my $foo = 35'? -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 [EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/ Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Re: Dynamic scoping (take 2)
Larry's earlier response means this 'yours' idea is history, but for closure, yes, this seems to be headed in the right direction, at least in theory. It may have even been practical to implement it thru the standard property mechanism. so these two are equivalent ??? { my $x is yours ; my $y is yours ; my $z is yours ; 1... sub_a ; 2... } sub sub_a ( ; $x is yours, $y is yours ) { ...3... } ; - same as - # ( here no special meaning for is yours -- just another property ) { my $x is yours ; my $y is yours ; my $z is yours ; 1... #alias %MY to topic so that it can be fetched from sub_a by is given $_ ::= \%MY ; sub_a ; 2... } sub sub_a (;$x is yours, $y is yours ) is given($CALLER_SYMB) { #alias variables from $CALLER_SYMB to the local variables if #requested $SUB_SYMB ::= \%MY ; for $SUB_SYMB.keys { if $SUB_SYMB{$_}.yours and $CALLER_SYMB{$_}.yours { $SUB_SYMB{$_} ::= $CALLER_SYMB{$_} ; } } ; $CALLER_SYMB = undef ; #but better if this happens at compile time # -- probably this have to be forced with #BEGIN 3... } ; arcadi -- ralph
Re: Dynamic scoping (take 2)
If I misunderstood you -- correct me. It seems that all you worry about is that you want some variable be seen in several subroutines .. you propose a mechanism of passing them between desired subroutins by default through all the dynamical chain of sub calls connecting them. It seems , on the other hand , that there is already existing and ( to my taste ) simpler mechanism of making several subroutines ( and in general -- any lexical scopes ) share *the same* variable -- package ... ; sub a { our $x is private ; ... } ; #...but see below ... sub b { our $x is private ; ... } ; so $x is *package* variable that can be seen *only* from a and b. it plays the role of mailbox : a can put there whatever it want to pass to b . b should know about it ( and it knows because it declares $x inside its body ) and should fetch whatever it wants. it seems that this mechanism is cleaner and clearer and .. more intuitive. although... on the second thought I have a feeling that I am pulling is private property too much -- this way of using it was not discussed in Exe3. so probably we should invent the property that does exactly that : this variable is package *but* it is seen only from *several* lexical scopes , something like this : package ... ; sub a { our $x is shared ; ... } ; sub b { our $x is shared ; ... } ; we can even prescribe which lexical scope is allowed to change it : package ... ; sub a { our $x is shared is rw; ... } ; sub b { our $x is shared is ro; ... } ; but maybe this is abuse for rw and ro here -- so this should be package ... ; sub a { our $x is shared(rw) ; ... } ; sub b { our $x is shared(ro) ; ... } ; also there is one thing that bothers me about even the original is private property : what if my package is *really big* and I have in two distant places two function that each want its own static variable that they declare as Exe3 prescribe as our $var is private; but since I dont remember about having two such subs I can happen to give them the same name - so that naively they will be aliased to the same package variable . Now, with is private that is , probably not a problem , because compiler can notice this and complain about it . but If I want to pull similar mechanism for *sharing* variables -- this becomes a problem -- compiler cannot know that I wanted to share one variable $x between aub A and sub B and *another* variable ( which I mistakenly called $x too ) between sub C and sub D . In this case it will share $x between *all four* subs. I dont know how to stop this source of errors . currently . but anyway that is what bothered me with is private property. anyway, my feeling is that once it is necessary to pass variable far enough it is clearer to do it with globals -- which are restricted to be seen only in the restricted set of lexical scopes. arcadi . Me writes: In summary, I am proposing that one marks variables that are to be automatically passed from sub to sub with 'is yours' where appropriate. An example of what I'm suggesting follows. Code with brief comments first then explanation. { my $_; # $_ can't be touched # unless it is passed # to a sub explicitly. my $foo;# same for $foo my $baz is yours; # $baz will automatically $baz = 10; # be passed to /directly/ # called subs that ask # explicitly for $baz. waldo($foo); } sub waldo ($b ; $baz is yours) { print $baz; emer; } sub emer (;$baz is yours(no)) { print $baz; qux; } sub qux { ... } Running this prints '1010'. Here's why: A property exists that can mark any lexical as yours. When a variable is marked yours it is automatically passed to any directly called sub (not nested subs) that mentions it appropriately. The automatic $_ (available without declaring with a 'my') is marked yours by default. All other (ie declared) lexicals are, by default, not yours, hence guaranteed to be private lexicals unless explicitly passed to a sub. This is safer than the current perl 6 design in which use of $CALLER::, and even builtins and subs that merely use the topic, might accidentally clobber one of my lexicals at any time. Once execution reaches the body of waldo, there is a new lexical called $baz that is bound to the lexical with the same name in the body of the caller. The Cis yours in waldo's sig has two effects: 1. It requires that any /caller/ has a variable of the same name marked as yours or must pass a variable/value using the named arg syntax for that arg name; 2. It propogates the marking of $baz as a yours marked variable for any sub called from this, the body of waldo. Once execution reaches the body of emer, there is a new
Re: Dynamic scoping (take 2)
I think , ( on the second reading of your post ) , that your proposal of my $x is yours is logically very similar to my proposal of our $x is shared but your proposal is cleaner if I understand it as follows ( although I like more shared instead of yours for that purpose ) : instead of aliasing the lexical variable variable $x to the variable of the same name in the *current package* is yours *create* a new (secret) symbol-table that is remembered by compiler to be associated with variable $x and *aliases* $x to the variable of the same name in that (secret) symbol-table . *Any* other instances of $x is yours *alias* $x to *the same* variable $x in that (same) secret symbol-table. I do understand that strictly speaking you proposal is *very* different -- since you want only those function that will *ever* call each other ( not necessarily directly ) to share ( by default ) some variable -- so you propose dynamic (???) sharing . I propose *static* sharing -- but in practice they are *the same* -- the only difference is that I may happen to make two functions that *never* call each other ( or never happen to be in the same dynamic scope ) to share the same variable . But I am in controll of this ( If I am carefull lI will not do it -- and share variables only between those functions that it makes sence to share between ). my point is that static sharing is simpler to understand ( to me ) and it is a simpler concept -- just some mailbox variable that hangs somewere above the battlefield that only several people can access . dynamic sharing is like a *red* message that have to be passed ( secretly ) every time a soldier have it happens to *meet* another soldier that know that it have to receive *red* message. and I am not talking about implementation . arcadi
Re: Dynamic scoping (take 2)
you propose a mechanism of passing [vars] between desired subroutins by default through all the dynamical chain of sub calls connecting them. There's more, or rather, less to it than that. The same mechanism also includes a clean way to pass it, something that needs to be done. And a way to smoothly extend that for user defined pronouns like $first, $rest and $last, through to mini-vocabularies like $source, $target, $user, ... (Imagine you pull in fop1, fop2, fop3 that are file ops written by three independent authors that just agreed to conventions on naming args. With the mechanism I propose you can now do something like: my $source, $target, $user; ... fop1; fop2; fop3; To get this sort of simplicity, you have to decouple inter-sub interfaces in a couple ways, including arg positions and package names.) So I'm addressing several idioms that range from passing one or two pronouns around in the local vicinity, between a caller and a called sub, to passing a whole suite of values (an environment) to an execution thread and the far away subs it will contain. anyway, my feeling is that once it is necessary to pass variable far enough it is clearer to do it with globals -- which are restricted to be seen only in the restricted set of lexical scopes. That's name restriction, not the container. This doesn't help when dealing with threads. Basically, global /containers/ is the root of all evil, not so much global names. package ... ; sub a { our $x is shared ; ... } ; sub b { our $x is shared ; ... } ; This isn't thread-safe. There are other significant issues too, but I'll move on. [accidentally aliasing vars to the same global] I dont know how to stop this source of errors. Having lots of little local namespaces that get chained across long distances does away with this problem. -- ralph
Re: Dynamic scoping (take 2)
I like more shared instead of yours But that's because that's the way you are thinking about the problem/solution. I'm just talking about a very local trick of having autoargs instead of explicitly passing args in parens. The fact that this ends up creating an elegant alternative to dangerous globals is in an important way a mere somewhat surprising side-effect that you don't even need to tell a newbie or even an expert. It just works. I've considered names like passed, autoarg, implied, and so on. But ultimately yours seems to say it all: my $foo is yours; My means my lexical and yours means your lexical where sub calling is the boundary of what's mine and yours. (secret) symbol-table I would have thought the symbol table handling for implicit (your) args would be the exact same as for regular explicit args passed in parens. so you propose dynamic (???) sharing. I propose *static* sharing -- but in practice they are *the same* -- I'd claim that: 1. Autoargs would work with threads, static sharing won't. 2. By requiring explicit marking of autoargs all along the call chain, one retains a key advantage of explicitly passing args, namely avoidance of accidental action-at-a-distance. Just look at a sub's sig to know what is being shared between it and its callers. 3. Autoargs are significantly less verbose in many scenarios. 4. Autoargs are conceptually simpler than shared variables, for both newbies and experts. But clearly this is subjective. : -- ralph
Re: Dynamic scoping (take 2)
Me writes: 4. Autoargs are conceptually simpler than shared variables, for both newbies and experts. But clearly this is subjective. : thats exactly the point where I tryed to improve. Think of me as a newbe ( which I am ) -- If I understand your proposal , I can explain it to myself through the sort of shared variable : $x is yours tells that $x is aliased to variable in some secret scope symbol table that ( the table ) is shared between caller and callee also, another way : $x is yours is like saying that all functions that will ever call each other ( that is, if in my programm A calls B and B calls C and ... , then I will croup them in a group that ever call each other ) and which each have a declaration $x is yours may be thought of as being in special common *enclosing* lexical scope , at the top of which there is a declaration my $x ; so they all *share* the same variable . I think the effect here is the same as what you are saying . but may be I am wrong. also , there is another question : { my $x is yours = 1; a ; print $x # print 1 or 5 ? } sub a { $x is yours ; $x = 5 ; } ( in my formulation it prints 5 ) . so the question is : is is yours variable assigned or aliased in the callee scope ? probably I missed this from your explanations . probably we should have both , and then is yours mechanism is more general . also , anothre question . if is shared isn't thread safe , is static scoping using our $x is private ; thread safe ?? arcadi .
Re: Dynamic scoping (take 2)
Warning: I just watched The Wizard Of Oz for the first time tonight. $x is yours tells that $x is aliased to variable in some secret scope symbol table that ( the table ) is shared between caller and callee The secret place is MyYourca, a Subterranean island. People think it's an old, dangerous and complex place, but actually it's a new, simple, friendly, safe yet dynamic principality that juxtaposes two localities each of which is just an ordinary lexicality, as a defense against the evils of globalization. I'm not sure about the symbolism of all this; I'll let others hash that out. also, another way : $x is yours is like saying that all functions that will ever call each other ... then I will croup them in a group ... may be thought of as being in special common *enclosing* lexical scope Perhaps. I find what you've said confusing so I'm not sure what you mean. MyYourca already exists for transfer of variables to called subs via parens; the scheme I'm talking about just uses the same MyYourca. *share* the same variable. In the sense that $foo in: sub baz ($foo) { print $foo }; sub bar { my $foo; baz ($foo); }; is shared (between baz and bar), then yes. Anything more complicated than that, then, technically, no. { my $x is yours = 1; a ; print $x # print 1 or 5 ? } sub a { $x is yours ; $x = 5 ; } In my scheme, that would print 1 and some variable $x that was declared either package-wise or lexically at the point where sub a was defined has been changed to 5. If sub a were defined this way: sub a (;$x is yours) { $x = 5 ; } then it would print 5. is is yours variable assigned or aliased in the callee scope ? probably we should have both , and then is yours mechanism is more general . Well I was thinking it's always aliased but can be read-only by attaching Cyours(ro) to a variable declaration (as part of an explicit my, not in a sig; you can't put Cis yours(ro) in a sig -- I can't see an alias/copy distinction, nor ability to set ro in a sig, being worth the complexity they introduce). also , anothre question . if is shared isn't thread safe , is static scoping using our $x is private ; thread safe ?? I may have incorrectly used the term thread safe. The point is that you can't arrange for there being a unique $x for multiple threads of the same code. At least I don't see how. -- ralph
Dynamic scoping (take 2)
First, I'd like to confirm I've understood Ctemp and Clet right: 1. Ctemp 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? 2. Clet is a conditional Ctemp; 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. The above two features are basically sugar for what would otherwise be achieved with paired FIRST/LAST/UNDO blocks. Both must be applied to an existing variable. 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. 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::? In previous emails I've suggested: 1. The notion of something like attaching a Cpassed 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. 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. [1] http://tinyurl.com/2yhl -- ralph
Re: Dynamic scoping (take 2)
[temp] [implicit args] Here's a snippet of conversation on a haskell list about implementation of implicit args : http://tinyurl.com/2ym1 -- ralph
Re: Dynamic scoping (take 2)
In summary, I am proposing that one marks variables that are to be automatically passed from sub to sub with 'is yours' where appropriate. An example of what I'm suggesting follows. Code with brief comments first then explanation. { my $_; # $_ can't be touched # unless it is passed # to a sub explicitly. my $foo;# same for $foo my $baz is yours; # $baz will automatically $baz = 10; # be passed to /directly/ # called subs that ask # explicitly for $baz. waldo($foo); } sub waldo ($b ; $baz is yours) { print $baz; emer; } sub emer (;$baz is yours(no)) { print $baz; qux; } sub qux { ... } Running this prints '1010'. Here's why: A property exists that can mark any lexical as yours. When a variable is marked yours it is automatically passed to any directly called sub (not nested subs) that mentions it appropriately. The automatic $_ (available without declaring with a 'my') is marked yours by default. All other (ie declared) lexicals are, by default, not yours, hence guaranteed to be private lexicals unless explicitly passed to a sub. This is safer than the current perl 6 design in which use of $CALLER::, and even builtins and subs that merely use the topic, might accidentally clobber one of my lexicals at any time. Once execution reaches the body of waldo, there is a new lexical called $baz that is bound to the lexical with the same name in the body of the caller. The Cis yours in waldo's sig has two effects: 1. It requires that any /caller/ has a variable of the same name marked as yours or must pass a variable/value using the named arg syntax for that arg name; 2. It propogates the marking of $baz as a yours marked variable for any sub called from this, the body of waldo. Once execution reaches the body of emer, there is a new lexical called $baz that is bound to the lexical from waldo which is in turn bound to the lexical within qux. The '(no)' at the end of the Cis yours means that $baz is private to emer -- it will not be passed to called subs by the yours mechanism. In summary, you mark variables that are to be automatically passed from sub to sub with 'is yours' where appropriate. -- ralph