Re: How to default? (was Unary dot)
On Fri, Apr 12, 2002 at 05:34:13PM -0700, Glenn Linderman wrote: Allison Randal wrote: In a message dated Fri, 12 Apr 2002, Glenn Linderman writes: $_ becomes lexical Sound logic. And it almost did go that way. But subs that access the current $_ directly are far too common, and far to useful. One thing I'm missing is how those common useful subs that access the current $_ directly will be affected by $_ becoming lexical... Or perhaps $_ stays global, but gets automatically restored at the end of blocks in which it is changed, so that it appears lexical in value, even though it is global in the name space ??? No, it is truly lexical. Absolutely, positively. And you're right that this should present a problem. The lexical scope of a subroutine is the lexical scope where it was defined, not the lexical scope where it was evaluated. So, typical subs can only access global external variables, while closures and lexical subs access external variables from the scope in which they were defined. I suspect I've imperfectly represented the original idea, but I'll proceed as devil's advocate, for the sake of discussion... What if $_ were dynamically scoped, but only for subroutines? Dynamic scoping is not necessarily the same thing as a global $_. It would merely pretend (only for $_) that the subroutine had been defined in the scope where it was evaluated. But that could get you into trouble with recursion. So then you would want some way to explicitly either turn on, or turn off, dynamic scoping for a specific subroutine. The Cis given (or Cis topic) property would be an obvious way to turn it off (since it would create a $_ scoped to the subroutine). But, what if you wanted it off by default? It could be turned on either as a characteristic of the sub as a whole, or as a characteristic of an individual parameter: sub foo is dynamic_topic { ... } sub foo ($bar is topic_preserving, $baz) { ... } The property Cis topic_preserving would be both binding the value of the $_ in the calling scope to $bar and making $bar the current topic in the scope of the sub. The subroutine property would be basically the same, but wouldn't give you a named variable, and also wouldn't require you to include an extra parameter (which could be nice). Allison
Re: How to default? (was Unary dot)
Allison Randal wrote: What if $_ were dynamically scoped, but only for subroutines? Dynamic scoping is not necessarily the same thing as a global $_. It would merely pretend (only for $_) that the subroutine had been defined in the scope where it was evaluated. But that could get you into trouble with recursion. So then you would want some way to explicitly either turn on, or turn off, dynamic scoping for a specific subroutine. The Cis given (or Cis topic) property would be an obvious way to turn it off (since it would create a $_ scoped to the subroutine). But, what if you wanted it off by default? It could be turned on either as a characteristic of the sub as a whole, or as a characteristic of an individual parameter: sub foo is dynamic_topic { ... } sub foo ($bar is topic_preserving, $baz) { ... } The property Cis topic_preserving would be both binding the value of the $_ in the calling scope to $bar and making $bar the current topic in the scope of the sub. The subroutine property would be basically the same, but wouldn't give you a named variable, and also wouldn't require you to include an extra parameter (which could be nice). OK, I can see how all these things could work. Off hand, it seems like defaulting to is dynamic_topic would make more of those common useful $_-dependent subroutines work without change, but I guess if the perl 5 to 6 translator can detect use of $_ before definition of $_ within a sub accurately, that it could provide the appropriate annotation during conversion. And personally, I haven't written subs that assume dynamic $_ usage (I think), so I'm not too concerned about which way the default goes. I'm not a real heavy user of $_ for everything, as some people seem to be. It's useful at times, but can also be confusing at times. Regarding is topic_preserving: I assume that it would not have to be the first parameter; it would generally be more useful as the last, I expect, as in split, or the first optional parameter. Of course, there are cases where first and last are the same, or the other parameters can also be usefully defaulted when the first one is, etc. There'd be an interaction between is topic_preserving, default parameter values, and explicit parameter values which should be clarified. Now I understand why someone suggested using //= $_ instead of is topic_preserving, somewhere along the line. Clearly if the user supplies the parameter, is topic_preserving would limit itself to making that parameter available as $_ within the sub. If the user supplied both //= 3 and is topic_preserving, that would either be a bug or a feature. I guess as a feature, it would use $_, but if $_ were undef, then it would use 3 ??? -- Glenn = Remember, 84.3% of all statistics are made up on the spot.
Re: How to default? (was Unary dot)
There'd be an interaction between is topic_preserving, default parameter values, and explicit parameter values which should be clarified. Now I understand why someone suggested using //= $_ instead of is topic_preserving, somewhere along the line. Clearly if the user supplies the parameter, is topic_preserving would limit itself to making that parameter available as $_ within the sub. If the user supplied both //= 3 and is topic_preserving, that would either be a bug or a feature. I guess as a feature, it would use $_, but if $_ were undef, then it would use 3 ??? Personally, I like //= $_. It's clear, such that a reader would immediately know what it's doing. topic_preserving, despite being more verbose, is not so clear. Plus, if someone didn't know about that feature, that's probably the first thing they would do (provided they knew about defaults) to accomplish that task. Luke
Re: How to default? (was Unary dot)
On Sat, Apr 13, 2002 at 08:53:41AM -0700, Glenn Linderman wrote: Off hand, it seems like defaulting to is dynamic_topic would make more of those common useful $_-dependent subroutines work without change, but I guess if the perl 5 to 6 translator can detect use of $_ before definition of $_ within a sub accurately, that it could provide the appropriate annotation during conversion. ... I agree dynamic scoping of $_ in subroutines by default would make for an easier transition between 5 and 6. And at first I preferred it. But I'm gradually leaning in the opposite direction. The lexical scoping of $_ encourages encapsulation (good coding practice), and minimizes unexpected side effects. I'm not a real heavy user of $_ for everything, as some people seem to be. It's useful at times, but can also be confusing at times. I think the two most confusing aspects of $_ in 5 are the fact that it isn't created consistently (only when there isn't a named alias) and how easy it is to accidentally clobber it. Both of which should be eliminated in 6. :) Regarding is topic_preserving: I assume that it would not have to be the first parameter; it would generally be more useful as the last, I expect, as in split, or the first optional parameter. Of course, there are cases where first and last are the same, or the other parameters can also be usefully defaulted when the first one is, etc. Yeah, any of the properties or //= should work on any parameter in the list. There'd be an interaction between is topic_preserving, default parameter values, and explicit parameter values which should be clarified. Now I understand why someone suggested using //= $_ instead of is topic_preserving, somewhere along the line. Well, topic_preserving wasn't intended as a defaulting mechanism, just as a way of keeping the value of $_ across subroutines, even though it's lexically scoped. That's why I prefer the subroutine property, it makes it clearer that we're fundamentally altering the behaviour of subroutines, instead of making it look like we're just monkeying around with the parameters. For defaulting to the current topic, I'd probaly choose a property name topic_default instead. Possibly it would be helpful to be explicit about the options we're discussing: sub foo ($bar //= $_, ... The parameter can be passed a value, but it will default to the outer $_ if not passed a value. It will not set the value of $bar as topic within the subroutine, so the inner $_ will be undefined (unless there was a global $_ defined, which would produce really anti-dwim behaviour). One thing to consider here is that we're already abusing the $_ is lexical concept to make the $_ of the calling scope accessible as a value for the parameter. If you wanted to also make $bar the topic within the sub, you'd have to use the property Cis given: sub foo ($bar //= $_ is given, ... So, the Cis topic_default property would condense the two behaviours into one. I would guess that if you've defaulted to $_ you would expect it to also be $_ within the sub anyway. sub foo ($bar is topic_default, ... It also makes it clearer that this isn't your ordinary //= default happening, but a special lexical scope bending one. The other proposed property, Cis topic_preserving, wouldn't accept a value passed in, it would only and always be the $_ of the calling scope, and make it the topic within the subroutine scope. sub foo ($bar is topic_preserving, ... Okay, looking at the details laid out like this, I would probably ditch the topic_preserving property in favor of topic_default. But topic_default isn't going to give us perl 5 behaviour. Neither would topic_preserving, because both alter the parameter structure of the sub. So, my favorite final solution: Use the subroutine property dynamic_topic for perl 5 behaviour, topic_default to create Cprint type subs. If the user supplied both //= 3 and is topic_preserving, that would either be a bug or a feature. I guess as a feature, it would use $_, but if $_ were undef, then it would use 3 ??? I'd say a bug. I don't know, can you: sub foo ($bar //= $some_value //= 3, ... (Presuming that $some_value is a true global or otherwise accessible in the scope where the sub was defined.) If you can do that, then it should probably work the same for $_ defaulting. Allison
Re: How to default? (was Unary dot)
Trey Harris [EMAIL PROTECTED] writes: I think I've missed something, even after poring over the archives for some hours looking for the answer. How does one write defaulting subroutines a la builtins like print() and chomp()? Assume the code: for { printRec; } printRec Done!; sub printRec { chomp; print :$_:\n; } You could take advantage of subroutine signatures and multi-dispatch sub printRec() { printRec($_) } # No args, therefore no new topic. sub printRec($rec) { .chomp; print :$rec:\n } # 1 arg Assuming we *get* multidispatch that is. It would be nice to hope that the compiler could optimize that... -- Piers It is a truth universally acknowledged that a language in possession of a rich syntax must be in need of a rewrite. -- Jane Austen?
Re: How to default? (was Unary dot)
On Fri, 2002-04-12 at 04:26, Piers Cawley wrote: Trey Harris [EMAIL PROTECTED] writes: I think I've missed something, even after poring over the archives for some hours looking for the answer. How does one write defaulting subroutines a la builtins like print() and chomp()? Assume the code: for { printRec; } printRec Done!; sub printRec { chomp; print :$_:\n; } You could take advantage of subroutine signatures and multi-dispatch sub printRec() { printRec($_) } # No args, therefore no new topic. sub printRec($rec) { .chomp; print :$rec:\n } # 1 arg I think was he was saying is that your first printRec would not have a $_ available to it (lexically scoped, as I understand it). You've got a problem here, which I don't think there's a mechanism for. Perhaps sub printRec(-$rec) I'm just throwing that out, but some way to say that the argument defaults to getting the topic would seem to be called for.
Re: How to default? (was Unary dot)
On Fri, Apr 12, 2002 at 09:40:16AM -0400, Aaron Sherman wrote: On Fri, 2002-04-12 at 04:26, Piers Cawley wrote: Trey Harris [EMAIL PROTECTED] writes: I think I've missed something, even after poring over the archives for some hours looking for the answer. How does one write defaulting subroutines a la builtins like print() and chomp()? Assume the code: for { printRec; } printRec Done!; sub printRec { chomp; print :$_:\n; } You could take advantage of subroutine signatures and multi-dispatch sub printRec() { printRec($_) } # No args, therefore no new topic. sub printRec($rec) { .chomp; print :$rec:\n } # 1 arg I think was he was saying is that your first printRec would not have a $_ available to it (lexically scoped, as I understand it). You've got a problem here, which I don't think there's a mechanism for. If $_ is lexical by default (did larry say this somewhere?), then I'm sure we can make it dynamic on request ala: for $_ is temp { printRec; } I may have the syntax slightly borked but you get the idea. I read the original posters message the same as Piers though. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: How to default? (was Unary dot)
On Fri, Apr 12, 2002 at 09:26:45AM +0100, Piers Cawley wrote: Trey Harris [EMAIL PROTECTED] writes: I think I've missed something, even after poring over the archives for some hours looking for the answer. How does one write defaulting subroutines a la builtins like print() and chomp()? Assume the code: for { printRec; } printRec Done!; sub printRec { chomp; print :$_:\n; } You could take advantage of subroutine signatures and multi-dispatch sub printRec() { printRec($_) } # No args, therefore no new topic. sub printRec($rec) { .chomp; print :$rec:\n } # 1 arg Hm, I wonder if sub printRec($rec=$_) { ... } or someother way to specify that the current topic be used as a default argument, might be possible Graham.
Re: How to default? (was Unary dot)
On Fri, 2002-04-12 at 09:52, Jonathan Scott Duff wrote: On Fri, Apr 12, 2002 at 09:40:16AM -0400, Aaron Sherman wrote: sub printRec() { printRec($_) } # No args, therefore no new topic. sub printRec($rec) { .chomp; print :$rec:\n } # 1 arg I think was he was saying is that your first printRec would not have a $_ available to it (lexically scoped, as I understand it). You've got a problem here, which I don't think there's a mechanism for. If $_ is lexical by default (did larry say this somewhere?), then I'm sure we can make it dynamic on request ala: Nope, I don't think that works. If the caller of printRec has to do something special, we're meeting the original request which is to be able to write print, which scoops up $_ without any special case code. Now, we can say, you just can't ever write print. I can understand why we would, but why NOT just allow the subroutine author to indicate that the subroutine acquires the current topic as a parameter default? It would seem nice and clean. Either foo($a=$_){} as Graham suggests, or foo(-$a){} which was mine. Either one works. I guess with the aliasing of $_, Graham's seems cleaner to me. Of course, the other conversation pending, we might end up with: foo($a//=$_){} which doesn't do the same thing as print, but may be the best we can do with the syntax we have. I read the original posters message the same as Piers though. Ok, what did you get from it that's different?
Re: How to default? (was Unary dot)
- Original Message - From: Graham Barr [EMAIL PROTECTED] Hm, I wonder if sub printRec($rec=$_) { ... } or someother way to specify that the current topic be used as a default argument, might be possible Would it would be reasonable to have given default to the caller's topic? sub printRec { given { # $_ is now the caller's topic in this scope } } Perhaps Cgiven caller.topic {} would work as well. Ashley Winters
Re: How to default? (was Unary dot)
In a message dated Fri, 12 Apr 2002, Ashley Winters writes: Would it would be reasonable to have given default to the caller's topic? sub printRec { given { # $_ is now the caller's topic in this scope } } Perhaps Cgiven caller.topic {} would work as well. Yes, something like that would be nice. Of course, you could say, Cgiven caller.MY{'$_'}, but I think there's two separate things going on here: 1) There should probably be something in the syntax to allow for retopicalization of the up-scope topic 2) It may be useful to have some way to allow single-parameter blocks to take the up-scope topic as a first parameter. Trey
Re: How to default? (was Unary dot)
On Fri, 12 Apr 2002, Trey Harris wrote: I think I've missed something, even after poring over the archives for some hours looking for the answer. How does one write defaulting subroutines a la builtins like print() and chomp()? Assume the code: for { printRec; } printRec Done!; sub printRec { chomp; print :$_:\n; } Assuming the input file 1\n2\n3\n, I want to end up with: :1: :2: :3: :Done!: I assume I'm missing something in the sub printRec { line. But what? (I also assume, perhaps incorrectly, that I won't have to resort to anything so crass as checking whether my first parameter is defined...) Couldn't you do it with old-style Perl5 subs? sub printRec { my $p = chomp(shift // $_); print :$_:\n } Or am _I_ missing something? Luke
Re: How to default? (was Unary dot)
In a message dated Fri, 12 Apr 2002, Luke Palmer writes: Couldn't you do it with old-style Perl5 subs? sub printRec { my $p = chomp(shift // $_); print :$_:\n } Or am _I_ missing something? That definitely won't work (aside from the $p/$_ swap which I assume is unintentional), because $_ is now lexical. If my understanding is correct and $_ is always the topic, and the first parameter of any block is always the topic, that would make your code somewhat equivalent to: sub printRec { my $p; if (defined _[0]) { $p = shift; } else { $p = _[0]; } print :$p:\n; } Or is the topic of a block mutable (i.e., will a shift cause the topic to shift as well)? If so, I guess your code is actually is equivalent to: sub printRec { my $p = chomp(shift // shift); print :$p:\n; } Either way, bizarre, no? What I *think* you meant to say is: sub printRec { my $p = chomp(shift // caller.MY{'$_'}); print :$p:\n } which should certainly work, it just makes my skin crawl--vestiges of Perl 4 still coming to bite us, or something. Trey
Re: How to default? (was Unary dot)
Oops, caught my own mistake... In a message dated Fri, 12 Apr 2002, Trey Harris writes: In a message dated Fri, 12 Apr 2002, Luke Palmer writes: sub printRec { my $p = chomp(shift // $_); print :$_:\n } [Should be equivalent to] sub printRec { my $p = chomp(shift // shift); print :$p:\n; } Actually, it should be equivalent to sub printRec { my $p = chomp(shift // _[0]); print :$p:\n; } No shifting is happening just by referring to $_. Because $_ is always the topic, which is always the first parameter to a block, which in subroutines is _[0], right? So in a sub, $_ == _[0]. The only question I have is if you modify _ with a shift, does $_ continue to point at the old _[0], or does it now point at the new _[0], the original _[1]? Trey
Re: How to default? (was Unary dot)
In a message dated Fri, 12 Apr 2002, Glenn Linderman writes: $_ becomes lexical $_ gets aliased to the first topic of a given clause (hence changes value more often, but the lexical scoping helps reduce that impact) Okay. But it sounds like you're saying that Cgiven, and Cgiven only, introduces a topic, and that can't be right. From Ex4: This is a fundamental change from Perl 5, where $_ was only aliased to the current topic in a for loop. In Perl 6, the current topic -- whatever its name and however you make it the topic -- is always aliased to $_. And later: In a Perl 6 method, the invocant (i.e. the first argument of the method, which is a reference to the object on which the method was invoked) is always the topic And obviously a CCATCH block introduces a topic (though I guess we can pretend that CCATCH is a special kind of Cgiven). So I had (wrongly, I guess?) extended this logic to: all blocks taking parameters introduce a topic, which is the first parameter. Which made me think that Csub blocks, too, introduce a topic, which would be equivalent to _[0]. So where did I go wrong? Trey
Re: How to default? (was Unary dot)
On Fri, Apr 12, 2002 at 02:44:38AM -0400, Trey Harris wrote: I think I've missed something, even after poring over the archives for some hours looking for the answer. How does one write defaulting subroutines a la builtins like print() and chomp()? Assume the code: for { printRec; } printRec Done!; sub printRec { chomp; print :$_:\n; } Assuming the input file 1\n2\n3\n, I want to end up with: :1: :2: :3: :Done!: I assume I'm missing something in the sub printRec { line. But what? (I also assume, perhaps incorrectly, that I won't have to resort to anything so crass as checking whether my first parameter is defined...) The first call to printRec, where you simply want to use the same $_ works without changes. Larry decided that ordinary subs don't topicalize, partly for this very reason. But you will be able to tell your subs to topicalize, using a property. It hasn't been decided yet if this property will be is topic or is given, probably the latter. sub printRec ($msg is given) { ... } So for the second call to printRec, you could do something like: sub printRec ($msg //= $_ is given) { ... } Which would allow you to default to the outer $_ and make the first argument the topic. It's kind of ugly, though, and wouldn't deal with subsequent parameters in quite the way you would want. I much prefer handling the problem with overloading: sub printRec { chomp; print :$_:\n; } sub printRec ($msg is given) { printRec; } Allison
Re: How to default? (was Unary dot)
Okay, first thing to keep in mind, this hasn't been finally-finalized yet. Alot was hashed out in the process of proofing E4, but there will be more to come. On Fri, Apr 12, 2002 at 07:39:17PM -0400, Trey Harris wrote: In a message dated Fri, 12 Apr 2002, Glenn Linderman writes: $_ becomes lexical $_ gets aliased to the first topic of a given clause (hence changes value more often, but the lexical scoping helps reduce that impact) Okay. But it sounds like you're saying that Cgiven, and Cgiven only, introduces a topic, and that can't be right. From Ex4: You are correct, Cgiven is not the only topicalizer. Cfor is too, and -, etc... This is a fundamental change from Perl 5, where $_ was only aliased to the current topic in a for loop. In Perl 6, the current topic -- whatever its name and however you make it the topic -- is always aliased to $_. You could really say topic is just another name for $_. In a Perl 6 method, the invocant (i.e. the first argument of the method, which is a reference to the object on which the method was invoked) is always the topic Emphasis on method. And obviously a CCATCH block introduces a topic (though I guess we can pretend that CCATCH is a special kind of Cgiven). Yes. So I had (wrongly, I guess?) extended this logic to: all blocks taking parameters introduce a topic, which is the first parameter. Which made me think that Csub blocks, too, introduce a topic, which would be equivalent to _[0]. Sound logic. And it almost did go that way. But subs that access the current $_ directly are far too common, and far to useful. (Drat! Now I have to leave for several hours, just when it's getting interesting...) Allison
Re: How to default? (was Unary dot)
Allison Randal wrote: In a message dated Fri, 12 Apr 2002, Glenn Linderman writes: $_ becomes lexical Sound logic. And it almost did go that way. But subs that access the current $_ directly are far too common, and far to useful. One thing I'm missing is how those common useful subs that access the current $_ directly will be affected by $_ becoming lexical... Or perhaps $_ stays global, but gets automatically restored at the end of blocks in which it is changed, so that it appears lexical in value, even though it is global in the name space ??? Guess I haven't got all the Apocalypses memorized :) -- Glenn = Remember, 84.3% of all statistics are made up on the spot.