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 &code<Any>? : : sub statement:<given> (Any $topic, &code<Any>) { ... } 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, 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 export<my> { ... } : : Will that work? Hrm, I don't think so. For standard variables, that's not something the exporter is supposed to worry about. It's the importer that decides what scope to import into. The "is export<foo>" syntax is for export tag groups, but those are orthogonal to the final scoping. But since lexical scoping is the default import scope anyway, all we need to do is make sure the hint variable gets exported mandatorily whether requested or not, and maybe not worry about whether the user has a way to divert the hint into a package variable. So maybe it's just my $?MYHINT is export<MANDATORY> = 1; Except for the small issue that this would also set $?MYHINT in this scope. I suppose { my $?MYHINT is export<MANDATORY> = 1; } might be a workaround, but more likely we just need to tap into the underlying exporter mechanism to create the lexical symbol and copy a 1 into it somehow rather than trying to create a spurious alias into the exporting package that we'll throw away anyway. Maybe there's some kind of syntactic sugar for that, like a special declarator: importsym $?MYHINT = 1; where ordinary export looks like importsym &foo ::= &bar; Or whatever fills the niche of Perl 5's glob assignments. We could go as far as to just return a glob of code to eval after the "use", though that's a bit source-filtery. I think low-level exportation needs to be done with some kind of generics, but I haven't thought it through yet. Maybe it looks like some kind of role-ish upscopey block structure. EXPORT { our $packagevar; my $?MYHINT = 1; mysym &foo ::= &OUTER::bar; reexport Foo.all; # conjectural (as if the rest isn't...) } where "mysym" is a generic declarator that defaults to "my" but is user overridable to "our" or "state" (which are also lexically scoped names but have different dynamic lifetimes). An EXPORT block would only promote to a scope that was currently being compiled. Presumably you could have multiple EXPORT blocks, with implicit EXPORTs being generated from "is export" declarations. Or else there's one EXPORT and you have to call stdexports() from it if you rewrite it. More likely EXPORTALL is the one export block that calls all the individual implicit or explicit EXPORT blocks. : > : 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. :) As you can plainly see, I also reserve the right to do both of those at once all by myself. :-) Larry