Re: Ways to add behavior
On Wed, 26 Oct 2005, Rob Kinyon wrote: I'd like to take this moment and point to my somewhat hand-wavy metamodel proposal from last week. When Stevan and I were talking about this, we called it a quark. Atom also works quite nicely, but quarks are cooler. They're also colorful. Does this mean we will have a colour trait? But most importantly, who is supposed to be $Muster_Mark? Seriously, quark was originally chosen as a name because of the appearance of _three_ (somewhat mysterious) objects. Now it would indeed be cool to borrow the term in a CS context, especially in Perl, but it would be better suited in a naturally ternary (say, {property,structure}-wise) context. Michele -- Il tempo e' denaro, ma anche il denaro e' denaro. - William Gibson, L'accademia dei sogni.
Re: Roles vs. Classes (was Re: Ways to add behavior)
On 10/26/05, Larry Wall [EMAIL PROTECTED] wrote: On Wed, Oct 26, 2005 at 07:35:05PM -0700, chromatic wrote: : On Wed, 2005-10-26 at 21:58 -0400, Rob Kinyon wrote: : : Plus, the argument is a straw man. Instead of: : : class Some::Class is also { : } : : you would do: : : class My::Version { : does Some::Class; : } : : Problem solved. : : Don't forget the fun of modifying all existing uses of Some::Class to : use My::Version instead, if that's even possible. That should mostly be handled by virtualized class names. Will I be able to do something like: package Foo; $*VERSION = 1.3.2; use Foo-1.3.1; role My::Foo { does Foo; ... } alias My::Foo - Foo; # Or whatever the syntax should be And, in my other code, use Foo; will DWIM?
Re: +$arg changed to :$arg
HaloO, Larry Wall wrote: : Yes, and dispatch as a runtime keyed access into a code multitude. : The covariant part of the method's sig! The code equivalent to keyed : data access into hashes. Um, yeah. Won't play in Peoria, though. Where or what is Peoria? What I mean with the covariant part of a method sig stems from the paper G. Castagna. Covariance and contravariance: conflict without a cause available from ftp://ftp.di.ens.fr/pub/users/castagna/covariance.ps.gz : The left -- is just the virtualizer call. I tend to call : that slot accessor. The return value of a dispatch is the : not yet invoked but curried on the invocant(s) method. This : two stage propcess is in my eyes nicely indicated by the : two --. But we could also but a : in the dispatch arrows : like -:- or :- or -: which all look somewhat ugly. I kind of like : for that, actually. :-) I have no objections. Actually I associate it with the label syntax. But I hope we have the same understanding what multi method abc (A $a: B $b: C $c: X $x, Y $y) {...} #1 means in comparison to multi method abc (A $a, B $b, C $c: X $x, Y $y) {...} #2 where I think that #1 is a mono method on A that yields a mono method on B which in turn yields a mono method on C. That is *three* successive dispatches which could branch out into different targets in each step. E.g. with D a subtype of B multi method abc (A $a: D $b: C $c: X $x, Y $y) {...} #3 The #2 target OTOH is a *single* target on the 3-tupel type :(A,B,C). We could call the #1 and #3 dispatches tree-dispatch and #2 lattice-dispatch. Question is how do they relate to each other? I would opt for :(A,B,C) beeing more specific than :(A). In other words the cascaded dispatch competes in each step with n-tupel types. E.g. multi method abc (A $a: D $b, C $c: X $x, Y $y) {...} #4 outperforms :(B) from #1 and :(D) from #3 with its :(D,C) (sub)signature. Note that multi method abc (A $a: B $b, C $c: X $x, Y $y) {...} #5 would be ambigous in a pure regime because :(B,C) is not a strictly more specific type than :(D). After the successful selection of the target out of the targets #1 to #5 the contravariant part of the sig :(X,Y) is checked and then the invocation procedes with binding the args to the params. : method doit (...) on (invocant sig) { ... } I don't see how that relates. Take the example #2 from above which could be written multi method abc (X $x, Y $y) on (A $a, B $b, C $c) {...} and the cascading version as multi method abc (X $x, Y $y) on (A $a) on (B $b) on (C $c) {...} or with the invocants at the front multi method on (A $a, B $b, C $c) abc (X $x, Y $y) {...} But I'm not a native who could decide if 'method on' is the right choice of preposition. Perhaps it should be 'method in'? But that would further the conception of methods beeing inside of classes which they are only in the special case of a dispatch implementation through vtbls carried around by the objects. My old problem of 'is the object or the method in charge'. The metaphor that illustrates my point is that $ball.throw() looks funny in my mind if you think of the $ball throwing itself. Compare with $Larry.talk() where the talking style is inherent in $Larry. : Well, we could take the ¢ sigil to form invocant twigils ¢$, ¢@, ¢%, ¢ : which look a bit nicer with ^ though: ^$, ^@, ^%, ^. The association : with $^, @^, %^, ^ in placeholders is a bonus in my eyes because they : are post dispatch on void invocants :) Don't know what that means either. 'post dispatch on void' was a poor attempt to paraphrase that I see a sub as a *very* unspecific method. That is a sub call in method style $x.foo(); dispatches to the sub foo only if there is no other applicable method at all. Submethods in that view are methods that are specialized on Undef of the respective class. BTW, is ($x,$y).foo(1,2) valid multi method invocation syntax? Note that if there is nothing else but sub foo ([EMAIL PROTECTED]) {...} in scope it could be selected and called with @bar[0] = $x; @bar[1] = $y; @bar[2] = 1; @bar[3] = 2; : The guiding theme in my line of thinking about twigils is that there's : a void between their two chars. A pair of type constraint and uncaptured : actual invocant type so to say. Well and we could capture it with : : method doit ( Constraint ^Actual $foo, NonInvocant $blahh ) {...} : : to deal have it available inside. Am I makeing sense? Which impact all : this has an the self method discussion I don't know, but ^. and .^ come : to mind. The former would make ^.foo a method on the current invocant : and a bare .^ would dispatch the current method on the topic or some such. I haven't the foggiest clue if you're making sense. And that's the scary part. OK, forget the part about self calls inside the method implementation and let's look at the type variable aspect only. If I understand the concept correctly then ^ splits the type aspect of a variable
Re: +$arg changed to :$arg
On 10/27/05, TSa [EMAIL PROTECTED] wrote: HaloO, Larry Wall wrote: : Yes, and dispatch as a runtime keyed access into a code multitude. : The covariant part of the method's sig! The code equivalent to keyed : data access into hashes. Um, yeah. Won't play in Peoria, though. Where or what is Peoria? It's an expression in the US. Peoria is a town in the state of Illinois. It has a reputation for being conservative and a keeper of American Values (whatever that means). So, when you say something won't play in Peoria, you're saying that it's unlikely to be accepted by the masses. Rob
Re: +$arg changed to :$arg
HaloO, Juerd wrote: This aside, you could of course just double the colon. Or use a semicolon. Semicolon would give me the mnemonic of 'end of statement' seperating the dispatched part from the checked part of the signature. Or it reminds one of the array and hash slicing. Should we call dispatch call or code slicing? :( Int, Int ; Str, Num -- Foo ) A slot call would then retrieve the method from the object first :( Item ^X -- ^X ; Foo, Bar -- Ret ) Assuming we use ^ instead of ¢ as the captured type sigil. Which leaves the question how arrow type invocant methods relate to non-arrow type invocant methods? Hmm, non-arrow types can always be regarded as :( void -- ^X ) and the usual contra-variant subtyping rule would make :( ^X -- ^X ) more specific if void were more specific than ^X. But I think the opposite is true! That is any value can go to void context and be ignored. In other words void is a type close to the universal type. By the same argument any method is more specific than subs which have void as invocant type. I like the outcome that a free method on the same type has higher dispatch precedence than the corresponding slot call. YMMV, though. OTOH, the free method might not have the privileged access that a 'inside class definition' method has. But then such a outside overrider might just delegate to the insider routine through explicit slot access. But how does that look like? I think method bar (Foo $x) # all params dispatched, hence ^ optional { say outside Foo :); $x.Foo::bar(); # slot call } should do the trick. But then again, there might be no free methods in Perl6. I just really wouldn't like : to have two very different meanings in very similar places. I'm split on the issue because of the similarity to the label syntax. The indirect object syntax is then the call continuation after the dispatch target selection and invocants binding or some such. -- $TSa.greeting := HaloO; # mind the echo!
Is there a way to generate an object without new?
What I want to do, is a bit like... class A { has $.b; method show { $.b.say }; }; A( b = 5 ).show;` Thanks, Xinming
Re: Is there a way to generate an object without new?
On 10/27/05, Yiyi Hu [EMAIL PROTECTED] wrote: What I want to do, is a bit like... class A { has $.b; method show { $.b.say }; }; A( b = 5 ).show;` Yes, I definitely want this to be the way that case type instances are created: all those .news everywhere could get annoying. Anyway, assuming that class and sub namespaces are separate, which may be a dubious assumption: our A ::= A::new.assuming(A); Or, more explicitly (and more readably IMO): sub A (\$x) { A.new(*$x) } Luke
Re: Is there a way to generate an object without new?
Yiyi Hu skribis 2005-10-28 3:17 (+0800): class A { has $.b; method show { $.b.say }; }; A( b = 5 ).show;` This is how some other language construct objects, but not how Perl does it. In other words: you should not want this. Perhaps it is possible to have a class export a sub to its user. class A { has $.b handles { 'show' = 'say' }; eval sub $?CLASS is export { $?CLASS.new(\$?ARGS) }; } Not sure about the existence of $?ARGS, or how else to write it. Well, @_, but the signature might be different. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Is there a way to generate an object without new?
Juerd~ On 10/27/05, Juerd [EMAIL PROTECTED] wrote: Yiyi Hu skribis 2005-10-28 3:17 (+0800): class A { has $.b; method show { $.b.say }; }; A( b = 5 ).show;` This is how some other language construct objects, but not how Perl does it. In other words: you should not want this. How does that logically follow? Matt -- Computer Science is merely the post-Turing Decline of Formal Systems Theory. -Stan Kelly-Bootle, The Devil's DP Dictionary
Re: Is there a way to generate an object without new?
Matt Fowles skribis 2005-10-27 15:52 (-0400): This is how some other language construct objects, but not how Perl does it. In other words: you should not want this. How does that logically follow? They are two ways of expressing what I think. If they said exactly the same thing, I wouldn't have felt the need to use both :) Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Is there a way to generate an object without new?
On Thu, Oct 27, 2005 at 01:30:44PM -0600, Luke Palmer wrote: : On 10/27/05, Yiyi Hu [EMAIL PROTECTED] wrote: : What I want to do, is a bit like... : : class A { : has $.b; : method show { $.b.say }; : }; : : A( b = 5 ).show;` : : Yes, I definitely want this to be the way that case type instances are : created: all those .news everywhere could get annoying. On the other hand, it potentially makes these mean very different things: A @x A(@x) and that's a problem. Semantically, it would certainly be possible to teach any kind to respond to .() and attempt to clone or bless itself into a new object, but syntactically if we introduce A as a list operator we can never use it as a bare type mark on a variable like @x without some declarator out front. So either we rule out bare A $x as a coercion or cast, or we rule out bare A as a list operator, which would make the parens required. But even with parens, we can't easily make A([EMAIL PROTECTED]) mean both of these simultaneously: @args[0].as(A) A.new([EMAIL PROTECTED]) Well, okay, maybe if we're really sneaky about our MMD, we could make that work most of the time. But it kind of loses the distinction of making a new A out of something else vs making the current thing look like an A without necessarily cloning it. That probably needs syntactic relief anyway. Maybe A! is a hard cast and A? is a soft cast. Needs more waffling. Er, more thought. : Anyway, assuming that class and sub namespaces are separate, which may : be a dubious assumption: : : our A ::= A::new.assuming(A); The variables are separate in the symbol table, but both of them try to warp the grammar to recognize a bare 'A'. It's not clear what will happen in that case. If the original ^A is really ^*A, then defining A will likely just hide the outer meaning of A. On the other hand, with our definition of package aliasing, the global name includes version and author, and the current scope has an A alias to that long name, and that might collide with the A name of A in the current scope. : Or, more explicitly (and more readably IMO): : : sub A (\$x) { A.new(*$x) } Sorry, A is introduced immediately, so you've just written a nice infinite recursion. I'd suggest sub A (\$x) { ::A.new(*$x) } Larry
Re: Roles vs. Classes (was Re: Ways to add behavior)
On Thu, Oct 27, 2005 at 05:37:13AM -0400, Rob Kinyon wrote: : Will I be able to do something like: : : package Foo; Hmm, you just started in Perl 5 mode. : $*VERSION = 1.3.2; Perl 5 would get confused here, so I'm presuming Perl 6. But Perl 6 isn't likely to let you override the global run-time Perl version. : use Foo-1.3.1; That I think I understand. : role My::Foo { does Foo; ... } Okay, My::Foo does Foo here. Presumably it must do the Foo alias that the use just installed. And presumably the Foo you just used is a role that can be done. Certainly you can't do the global package Foo, assuming that's what your original package declared. : alias My::Foo - Foo; # Or whatever the syntax should be I have no clue where you're intending to install that alias. Are you trying to install a *Foo alias? A bare Foo is going to first find the local alias to the Foo you used, and that hides the global Foo that it would have found otherwise. I suspect you're trying to say *Foo := My::Foo; : And, in my other code, use Foo; will DWIM? I don't know quite what you mean, so I don't know if it'll do what you mean. If you're trying to establish a policy that defaults a particular name to a particular version, the library interface will probably give you a more straightforward way to set that up. Larry
Re: Roles vs. Classes (was Re: Ways to add behavior)
On 10/27/05, Larry Wall [EMAIL PROTECTED] wrote: On Thu, Oct 27, 2005 at 05:37:13AM -0400, Rob Kinyon wrote: : Will I be able to do something like: : : package Foo; Hmm, you just started in Perl 5 mode. : $*VERSION = 1.3.2; Perl 5 would get confused here, so I'm presuming Perl 6. But Perl 6 isn't likely to let you override the global run-time Perl version. : use Foo-1.3.1; That I think I understand. : role My::Foo { does Foo; ... } Okay, My::Foo does Foo here. Presumably it must do the Foo alias that the use just installed. And presumably the Foo you just used is a role that can be done. Certainly you can't do the global package Foo, assuming that's what your original package declared. : alias My::Foo - Foo; # Or whatever the syntax should be I have no clue where you're intending to install that alias. Are you trying to install a *Foo alias? A bare Foo is going to first find the local alias to the Foo you used, and that hides the global Foo that it would have found otherwise. I suspect you're trying to say *Foo := My::Foo; : And, in my other code, use Foo; will DWIM? I don't know quite what you mean, so I don't know if it'll do what you mean. If you're trying to establish a policy that defaults a particular name to a particular version, the library interface will probably give you a more straightforward way to set that up. Sorry. I'm not up on the syntax. I should do some serious backlog reading. What I'm trying to do is load role Foo 1.0, have My::Foo do Foo, then call My::Foo version 2.0 of Foo so that anyone else in my program will see My::Foo instead of the original Foo. Is this possible? Rob
Role Method Conflicts and Disambiguation
Hello all, I have a question about method conflict resolution works for roles, and I cannot seem to find this in any of the Apoc/Syn documents. Here is the basic issue: role Foo { method foo { ... } method bar { ... } # we will use this later :) } role Bar { method foo { ... } } role FooBar { does Foo; does Bar; } Now, at this point we have a method conflict in suspension since (according to A/S-12) method conflicts do not throw an error until a role is composed into a class. This means that when I do this: class MyClass does FooBar {} an exception is thrown. Unless of course MyClass has a foo method, which will disambiguate the conflict. My question then is, can FooBar (the role) disambiguate the foo conflict? role FooBar { does Foo; does Bar; method foo { ... } } Now, on the surface this seems obvious, of course the FooBar role should be able to disambiguate. However, when we expand the example other issues show up. role Baz { does Foo; } class MyClass2 does FooBar does Baz {} # Will this die? Now, since MyClass2 actually does Foo twice, does that mean bar creates a conflcit? Since bar would be found through FooBar and Baz. I would think the answer here would be no, and that we would build some kind of unique list of roles so as to avoid repeated consumption like this. But thats not all, we have a potential problem with foo again. Baz will provide foo from Foo, but FooBar will provide it's own foo (which we used to disambiguate). So our disambiguation is not ambiguated again. / Possible Solutions / A (deceptively) simple solution to this is that MyClass2 needs to disambiguate. But this means that our roles are not really black boxes anymore. In order to properly disambiguate this we need to know where all the foo methods are coming from (Foo, Bar and FooBar), and potentially what is inside these foo methods (especially in the case of FooBar since it is attempting to disambiguate, it's behavior could be very specific). It probably would also become important to know what other methods foo interacts with since we potentially have 3 different expected versions of foo. In the end, we will have probably looked inside every method defined in Foo, Bar, FooBar and Baz in order to properly write MyClass2. IMHO, this is sort of defeating the usefulness of roles at this point. Another simple (but maybe slightly unintuitive) solution would be to not allow roles to disambiguate at all. (Quick side note: Doing this means that roles like FooBar (which carry with them a suspended conflict) would be restricted in what types of behaviors they can provide. Basically they would only be able to provide new behaviors which are unrelated to those provided by Foo and Bar. If it were to try to use methods from Foo or Bar, it would really end up needing to disambiguate.) This actually makes MyClass2 somewhat simpler now, since it only need to disambiguate between foo from Foo, and foo from Bar. Of course this is only marginally better, since you would still need to look inside all the methods of Foo, Bar, FooBar and Baz to see how foo is being used so you could disambiguate properly. ... So what do you all think?? Stevan