Re: How to write a self.pm (Re: method calls on $self)
Autrijus Tang wrote: The compiler, in turn inspect whether there's an bound $_ in scope with $?SELF set. It is not trivial, because this should work: sub baz (c) { c() } method foo { baz { .bar } } # $_ is free in inner closure But this needs to fail: sub baz (c) { c(1) } method foo { baz { .bar } } # $_ is bound in inner closure I might still not understand topic, $_ or lexical vars in general. But why does the fact that c is called with a parameter in the second case and without one in the first example make a difference? Isn't $_ always coming in out of band? So .bar is always invoked on the invocant of foo if we think that there is an implicit $_ := $?SELF before the call to baz in foo. And I hope the binding of $_ to $?SELF is a read-only binding! -- TSa (Thomas Sandlaß)
Re: How to write a self.pm (Re: method calls on $self)
On Tue, Jul 12, 2005 at 12:36:23PM +0800, Autrijus Tang wrote: : On Mon, Jul 11, 2005 at 09:04:54PM -0700, Larry Wall wrote: : On Tue, Jul 12, 2005 at 10:17:01AM +0800, Autrijus Tang wrote: : : On Mon, Jul 11, 2005 at 06:29:28PM -0700, Larry Wall wrote: : : The obvious thought is to have yet another magical, $^H like flag, to : : denote the current dialect. If it is set, then the parser can emit : : .method as $_.method, instead of $?IMPLICIT_INVOCANT.method. : : The parser always emits .method as $_.method under any dialect, or : fails. What has changed is whether $_ sometimes means the invocant. : : But the compiler needs to trigger ambiguity resolution -- i.e. check : for $?SELF agreement with $_ -- when it sees $?IMPLICIT_INVOCANT. : : No need to do that if it sees $_.method. So they need to be different. Well, another approach is to treat .method as invariably $_.method, and catch the problem at the attempt to rebind $_. Thomas seems to think it should already be doing that. Of course, that would make it impossible to use given or for inside a method at all... So the other approach is to give up on compile-time checks and say that $?IMPLICIT_INVOCANT.method in a method's lexical scope (and in the absence of use self) turns into ($_ =:= $?SELF ?? $_.method :: fail Phooey) : In any event, SMD methods always have a first argument, so you're never : in doubt at that point. And since .bar always means $_.bar, I don't : think you really have a problem here that's any harder than you already : had with $_. : : The problem here is for the compiler to detect whether $_ agrees : with $?SELF, when it sees $?IMPLICIT_INVOCANT. If they agree, : $?IMPLICIT_INVOCANT gets replaced by $_; otherwise it is an error. : : Consider this construct: : : method foo { : $_ := $something_else if rand(2)1; : .bar; : } : : That's one case where it's not possible to detect at compile time, : so it needs to silently let .bar go thru as $_.bar. Though Thomas's constant binding notion would presumably catch that. But then we're getting into the noalias zone that Dennis Ritchie hates. On the other hand, I can see lots of uses for variables that may not be rebound, at least in terms of reassuring the optimizer that Weird Things Can't Happen. : : Clearly we need a way to statically determine statement:given : : and statement:for will always assign at least one argument to : : its block argument. Without that, the compile-time analysis mandated by : : Larry is infeasible. : : I think you can assume that given and for always bind at least one : argument. In particular, a for that binds 0 arguments will never : progress, plus you can recognize it: : : But what in given and for signify that? I do not want to special : case based on function names, and statement:given may be rebound : to something else. I understand the desire for generality, but that road also leads to error messages that are completely opaque to naive users, who are pretty accurate in their view that features like given and for will Stay Put in the normal course of events. Many of the most useful diagnostics in Perl 5 are the ones that are guessing based on common usage patterns. Users can't do much with messages that when deciphered come out to mean something like you called a function passing as its first argument another function whose first argument's declared type allows it to be optionally bound to $_ but if we actually try to make use of that we'll get some ambiguity further on down the road, and that's bad. They'd much rather chuck the generality and have You can't say .foo inside given where the topic could be either $_ or the method's invocant. Or in the absense of that just blow up at run time. Of course, I'm just restating your problem here... : How does that something else signify that it will : at least bind at least one argument to its code argument? Via the : signature of the code argument, i.e. the Any in codeAny? : : sub statement:given (Any $topic, codeAny) { ... } Maybe something like: sub statement:given (Any $topic, *code:(Any is topic)) { ... } : If so, what is the signature of for? I can't seem to write it down. Good question. I suppose the signature wants to guarantee minimum arity of 1 somehow. Maybe sub statement:for (Lazy [EMAIL PROTECTED], *code:(Any is topic, *)) { ... } or some such. But whether the outer function is actually functioning as a topicalizer would still depend on the innards of your function. Hmm. We might settle for declaring such functions with a special trait that indicates that they are *intended* to function as topicializers. And then maybe the compiler could just depend on those declarations for its static analysis: sub statement:given (Any $topic, *code:(Any)) is topicalizer { ... } Other that that we rely on the run-time check. (Which hopefully common code analysis can factor out multiple copies of.) : : Then,
How to write a self.pm (Re: method calls on $self)
(Cross-posting the new ruling from p6l to p6c to discuss implementation strategy) On Mon, Jul 11, 2005 at 06:29:28PM -0700, Larry Wall wrote: { let $Larry.decisive = 1; Okay, this is what we're gonna do. We're gonna go back pretty close to where we were originally, but with a twist. That is, .foo is always a call on the current topic, but the invocant is (again) always the topic in the outer scope of a method. The difference from before is that we simply outlaw .foo notation at *compile* time in those scopes where we know (at compile time) that $_ and $?SELF diverge. In such a scope you *must* specify $_ or $?SELF (or equivalent). (If necessary we can also compile .foo inside methods down to code that checks at runtime whether $_ has diverged from $?SELF and pitch a run-time fit for those situations we can't detect at compile time. Or we can just declare it erroneous.) Basically, you can't use .foo inside a given or a for inside a method. That's the default, and I'm not changing my mind ever again, at least till next week. That being said, if you mutate your language with anything like: use self this; use self self; use self o; use self ./; use self ; ... then the pragma is allowed to warp .foo semantics to make it *always* refer to $_ everywhere, provided it *also* undoes the default binding of $_ := $?SELF, so people that people aren't tempted to use .foo to mean $?SELF.foo in that scope. Yes, this is possibly a hazard for cut-n-pasters. But then, you weren't supposed to be cutting-n-pasting anymore, were you? Shame on you. Move the common code to a role, or a base class. } Normally, I try to comply with new rulings as soon as they become available, but the implementation of this is nontrivial, so I'd welcome more input. The obvious thought is to have yet another magical, $^H like flag, to denote the current dialect. If it is set, then the parser can emit .method as $_.method, instead of $?IMPLICIT_INVOCANT.method. If it is not set, the parser needs to emit this as the first statement in any method body: $_ := $?SELF The compiler, in turn inspect whether there's an bound $_ in scope with $?SELF set. It is not trivial, because this should work: sub baz (c) { c() } method foo { baz { .bar } } # $_ is free in inner closure But this needs to fail: sub baz (c) { c(1) } method foo { baz { .bar } } # $_ is bound in inner closure Clearly we need a way to statically determine statement:given and statement:for will always assign at least one argument to its block argument. Without that, the compile-time analysis mandated by Larry is infeasible. Then, we need to figure out the structure for the magic flag set by self.pm on behalf of its caller. We are not using $^H anymore, so there needs to be a way to pass lexical settings to the caller. To use MJD's lexical pragma design: module self; use pragma; sub import ($caller, $dialect) { install_pragma_value('$?SELF_MAGICAL', $dialect); } This will create a lexically scoped hint in the importer's scope; the parser and compiler will be hard-wired to recognise that magic and act accordingly. Does this seem sane? The static detection of $_ is the showstopper currently, and Pugs will need to separate the compiler with PIL evaluator to implement the pragma.pm above. Before that happens, I'll still pretend that: use self './'; is in scope. If people are uncomfortable with that, maybe we can retrofit all tests and examples using the ./ syntax to add that dummy line on top of their code, and ship with a stub self.pm that does nothing. Will that do as a interim solution? Thanks, /Autrijus/ pgpN8udhQ2SUX.pgp Description: PGP signature
Re: How to write a self.pm (Re: method calls on $self)
On Tue, Jul 12, 2005 at 10:17:01AM +0800, Autrijus Tang wrote: : On Mon, Jul 11, 2005 at 06:29:28PM -0700, Larry Wall wrote: : The obvious thought is to have yet another magical, $^H like flag, to : denote the current dialect. If it is set, then the parser can emit : .method as $_.method, instead of $?IMPLICIT_INVOCANT.method. The parser always emits .method as $_.method under any dialect, or fails. What has changed is whether $_ sometimes means the invocant. : If it is : not set, the parser needs to emit this as the first statement in any : method body: : : $_ := $?SELF That is the part that has to be conditional on the dialect. : The compiler, in turn inspect whether there's an bound $_ in scope : with $?SELF set. It is not trivial, because this should work: : : sub baz (c) { c() } : method foo { baz { .bar } } # $_ is free in inner closure : : But this needs to fail: : : sub baz (c) { c(1) } : method foo { baz { .bar } } # $_ is bound in inner closure The compiler is free to treat any undecidable binding as ambiguous and die of uncertainty. Though we should probably make some official rule so that different compilers don't end up with different definitions of undecidable. In any event, SMD methods always have a first argument, so you're never in doubt at that point. And since .bar always means $_.bar, I don't think you really have a problem here that's any harder than you already had with $_. : Clearly we need a way to statically determine statement:given : and statement:for will always assign at least one argument to : its block argument. Without that, the compile-time analysis mandated by : Larry is infeasible. I think you can assume that given and for always bind at least one argument. In particular, a for that binds 0 arguments will never progress, plus you can recognize it: for @foo - {...} And a given that doesn't bind $_ isn't worth much either. Or is that what you're asking? : Then, we need to figure out the structure for the magic flag set by : self.pm on behalf of its caller. We are not using $^H anymore, so : there needs to be a way to pass lexical settings to the caller. Perhaps hints should just be considered lexically scoped $? variables. You export them lexically just the same way you export any other lexically scoped things, however that is. : To use MJD's lexical pragma design: : : module self; : use pragma; : sub import ($caller, $dialect) { : install_pragma_value('$?SELF_MAGICAL', $dialect); : } : : This will create a lexically scoped hint in the importer's scope; : the parser and compiler will be hard-wired to recognise that magic : and act accordingly. How will you handle: use Foo :my$x; Seems like this is just a kind of use Foo :my$?MYHINT thingy, only perhaps you're just setting $?MYHINT rather than aliasing it back into a Foo variable. : Does this seem sane? The static detection of $_ is the showstopper : currently, and Pugs will need to separate the compiler with PIL evaluator : to implement the pragma.pm above. I suspect you're making it complicateder than it needs to be, but perhaps I don't understand the problem fully. Of course, the two are not mutually exclusive... : Before that happens, I'll still pretend that: : : use self './'; : : is in scope. If people are uncomfortable with that, maybe we can : retrofit all tests and examples using the ./ syntax to add that dummy : line on top of their code, and ship with a stub self.pm that does : nothing. Will that do as a interim solution? That's fine for the short term. Larry
Re: How to write a self.pm (Re: method calls on $self)
On Mon, Jul 11, 2005 at 09:04:54PM -0700, Larry Wall wrote: On Tue, Jul 12, 2005 at 10:17:01AM +0800, Autrijus Tang wrote: : On Mon, Jul 11, 2005 at 06:29:28PM -0700, Larry Wall wrote: : The obvious thought is to have yet another magical, $^H like flag, to : denote the current dialect. If it is set, then the parser can emit : .method as $_.method, instead of $?IMPLICIT_INVOCANT.method. The parser always emits .method as $_.method under any dialect, or fails. What has changed is whether $_ sometimes means the invocant. But the compiler needs to trigger ambiguity resolution -- i.e. check for $?SELF agreement with $_ -- when it sees $?IMPLICIT_INVOCANT. No need to do that if it sees $_.method. So they need to be different. In any event, SMD methods always have a first argument, so you're never in doubt at that point. And since .bar always means $_.bar, I don't think you really have a problem here that's any harder than you already had with $_. The problem here is for the compiler to detect whether $_ agrees with $?SELF, when it sees $?IMPLICIT_INVOCANT. If they agree, $?IMPLICIT_INVOCANT gets replaced by $_; otherwise it is an error. Consider this construct: method foo { $_ := $something_else if rand(2)1; .bar; } That's one case where it's not possible to detect at compile time, so it needs to silently let .bar go thru as $_.bar. : Clearly we need a way to statically determine statement:given : and statement:for will always assign at least one argument to : its block argument. Without that, the compile-time analysis mandated by : Larry is infeasible. I think you can assume that given and for always bind at least one argument. In particular, a for that binds 0 arguments will never progress, plus you can recognize it: But what in given and for signify that? I do not want to special case based on function names, and statement:given may be rebound to something else. How does that something else signify that it will at least bind at least one argument to its code argument? Via the signature of the code argument, i.e. the Any in codeAny? sub statement:given (Any $topic, codeAny) { ... } If so, what is the signature of for? I can't seem to write it down. : Then, we need to figure out the structure for the magic flag set by : self.pm on behalf of its caller. We are not using $^H anymore, so : there needs to be a way to pass lexical settings to the caller. Perhaps hints should just be considered lexically scoped $? variables. You export them lexically just the same way you export any other lexically scoped things, however that is. How will you handle: use Foo :my$x; Seems like this is just a kind of use Foo :my$?MYHINT thingy, only perhaps you're just setting $?MYHINT rather than aliasing it back into a Foo variable. Yes, that's the main difference. How does the :my form of export work in the exporter's end? sub foo is exportmy { ... } Will that work? : Does this seem sane? The static detection of $_ is the showstopper : currently, and Pugs will need to separate the compiler with PIL evaluator : to implement the pragma.pm above. I suspect you're making it complicateder than it needs to be, but perhaps I don't understand the problem fully. Of course, the two are not mutually exclusive... Indeed I suspect both are true. :) Thanks, /Autrijus/ pgpUx78e7n7vf.pgp Description: PGP signature