Re: Ways to add behavior
On Mon, Nov 07, 2005 at 08:44:28PM +0100, TSa wrote: : HaloO, : : Larry Wall wrote: : > : ::Takes3Ints ::= :(Int,Int,Int --> Any); : > : : > : my &foo:(Takes3Ints); : > : > I'd say that has to be something like: : > : > my &foo:(Takes3Ints:); : > : > or maybe one of : > : > my &foo:(Takes3Ints \!); : > my &foo:(\Takes3Ints); : > my &foo\(Takes3Ints); : > : > since Takes3Ints is the implementation and/or arglist type. : : Sorry, you lost me. Why is there a invocant colon in the : first example, It would presumably indicate an implementation type for &foo, which is probably wrong. : and what exactly does the ref indicator : mean in all the three different alternatives? Those would indicate an arglist parameter, which is probably right. The most recent S06 has sub foo (\$arglist) to bind the entire arglist object to $arglist, though arguably (no pun intended) the syntax could be: sub foo \($arglist) instead. This goes with the decision that rvalue \(1,2,3,:foo) generates an arglist object. : > Otherwise how do you distinguish : > : > my &foo:(Takes3Ints); : > my &foo:(Int, Int, Int); : : You mean the latter &foo as non-code, simple 3-tuple type? : Otherwise I would think the & sigil implies the optional : default &:( --> Any). The Any would be implied in that case. I don't see much difference between that and the multi disambiguating construct: my &foo := &bar:(Int, Int, Int); say foo(1,1,1); : But than again I haven't fully grasped : your notion of the pure type name before the first colon. I was just playing off of your @array:(Array: ...) thought, but the signature is not the implementation type, so forget that. : > The colon would still be required in an rvalue context. But the extension : > of that to subs seems to be: : > : > my &sub(Sub: \$args) : > : > Hmm, does that mean that a method actually looks like this? : > : > my &meth(Method: $self: \$args) : : I have ranted that I see method invocation as a two step : call with a covariant dispatch first and then a normal : contravariant call with argument type check, but why the : second colon? Only because multiple colons imply tiebreaking behavior under MMD. I'm just trying to picture SMD as a form of MMD. : And why the first on &sub(Sub: \$args)? Just : to name the intended code subtype? Yes, just the same as your @array:(FooArray: ...) idea that the first invocant is the function-like object implementing the thing. Larry
Re: Ways to add behavior
HaloO, Larry Wall wrote: > : ::Takes3Ints ::= :(Int,Int,Int --> Any); > : > : my &foo:(Takes3Ints); > > I'd say that has to be something like: > > my &foo:(Takes3Ints:); > > or maybe one of > > my &foo:(Takes3Ints \!); > my &foo:(\Takes3Ints); > my &foo\(Takes3Ints); > > since Takes3Ints is the implementation and/or arglist type. Sorry, you lost me. Why is there a invocant colon in the first example, and what exactly does the ref indicator mean in all the three different alternatives? > Otherwise how do you distinguish > > my &foo:(Takes3Ints); > my &foo:(Int, Int, Int); You mean the latter &foo as non-code, simple 3-tuple type? Otherwise I would think the & sigil implies the optional default &:( --> Any). But than again I haven't fully grasped your notion of the pure type name before the first colon. > The colon would still be required in an rvalue context. But the extension > of that to subs seems to be: > > my &sub(Sub: \$args) > > Hmm, does that mean that a method actually looks like this? > > my &meth(Method: $self: \$args) I have ranted that I see method invocation as a two step call with a covariant dispatch first and then a normal contravariant call with argument type check, but why the second colon? And why the first on &sub(Sub: \$args)? Just to name the intended code subtype? --
Re: Ways to add behavior
On Mon, Nov 07, 2005 at 09:37:04AM -0800, Larry Wall wrote: : It would be nice to generalize this sufficiently to be able to declare : polymorphic objects resembling match objects: : :my $matchobj(Poly: Key^Int^Notthere --> Any); : : Or maybe that should be: : :my $matchobj\(Highlander); : : :-) But seriously, I do keep wanting poly objects to keep trees in. For example, I want to represent XML with the tag attributes in a hash but the contents in a list: $obj = q:xml; # (conjectural here-xml syntax) text2 text2 say ~$obj; # t1 say $obj.xml; # say $obj{a2}; # y say $obj[2];# text2 say ~$obj.first('t2') # t2 say $obj.first('t2').xml# Larry
Re: Ways to add behavior
On Mon, Nov 07, 2005 at 01:05:16PM +0100, TSa wrote: : With the introduction of kind capture variables ^T we could complety : drop the subtype special form. As you pointed out the adding of constraints : happens with the where clause anyway. Thus we return to the usage of the : compile time name assignment form : : ::Blahh ::= ::Fasel where {...} : : where the :: in all cases means working on the MIR (Meta Information : Repository) which is the world of names (In Russian, Mir (Мир) means : "peace," and connotes "community." --- cited from Wikipedia). Except that a type declarator can remove the need for all those extra :: markers. (Actually, the ::Fasel can be presumably written Fasel if Fasel is already declared, so the only strangeness is on the left. We could hack identifier-left-of ::= like we did identifier-left-of =>, or we could turn ::= into more of a general alias macro idea. But I think people generally like declarators out to the left for readability.) : Question: shouldn't there be a natural 1 to 1 relation of ::T and ^T : or globally ::*T and ^*T where the former is the name and the latter : the kind represented by T? Of course scoping applies and there are : anonymous things that can be captured into ^T vars at runtime. Yes, that's basically how I see it. ::T is the literal form, ^T is the free form, but both map to package T in some scope or other. : If the answer is 'yes' as I expect, I wonder if the compiler has to restrict : the usage of ::= to scopes which don't depend on runtime evaluations like : :if $x < 10 { ::*Surprise ::= ::*FunnyType; say 'did it'; } : : Or should these be extracted out, making the above mean : :::*Surprise ::= ::*FunnyType; # or further out if necessary : :if $x < 10 { say 'did it'; } To me it's similar to my $x = 1 if $y; which should probably just be disallowed or warned about under strict. On the other hand, the declarations in a class file are also contingent on the class being used, so those declarations are also in a conditional context. So maybe we should just declare such things to be erroneous. : >: Question: does a subtype declaration work only on package-like things : >: which are addressed with a :: sigil? Or does your 'potentially : >: contravariant' mean that arrow types can be constraint or aliased, as : >: well? : >: : >: subtype TakesInt of Sub where { .sig =:= :(Int --> Any) }; : >: : >: my TakesInt &foo; : >: : >: foo('a string'); # type error : > : >Hmm, I would read that as declaring that &foo *returns* a TakesInt, : >not that &foo *is* a TakesInt. Just as : > : >my TakesInt @bar; : > : >declares an array of individual TakesInt elements. : : This is not too bad because then the & sigil is naturally associated : with the :( --> ) arrow type syntax and the forms can be mixed only : to the extent of signature aliasing: : : ::Takes3Ints ::= :(Int,Int,Int --> Any); : : my &foo:(Takes3Ints); I'd say that has to be something like: my &foo:(Takes3Ints:); or maybe one of my &foo:(Takes3Ints \!); my &foo:(\Takes3Ints); my &foo\(Takes3Ints); since Takes3Ints is the implementation and/or arglist type. Otherwise how do you distinguish my &foo:(Takes3Ints); my &foo:(Int, Int, Int); : How does arrow typing apply to the three data sigils $, @ and %? : Compare: : : my $foo:(Int); # non-referential value type : my $foo:(-->Int); # same? Or perhaps means anonymous ref/link/alias? : my $foo:(Ref-->Int) # explicit reference? same as 'is ref' trait? : my $foo:(Item: -->Int) # tied container : : Which is the default when the Int is used in the type slot of the : declaration? : :my Int $foo; That means my $foo:(-->Int); : Could this be used to define the key type of hashes? : :my %foo:(Blahh-->Any); : : And shape of arrays : :my @foo:(Int,Int,Int-->Any); : : where the Int or subtypes of it are enforced and Any defaulted. Certainly. I wouldn't mind getting rid of the "shape" property. : Thus this could just be : :my @foo:(!,!,!); Yeah, though that doesn't mean you can't write @foo[1] and get a :(!,!) out of it. : The covariant invocant/container types are of course : :my $item :(Item: --> Any); :my @array:(Array: Int --> Any); :my %hash :(Hash: Key --> Any); : : The & sigils have a free signature and ^ vars obviously have no signature : other than pure type ;) Works for me. As with & sigs, we might be able to lose the colon in a declarative context: my $item(Item: --> Any); my @array(Array: Int --> Any); my %hash(Hash: Key --> Any); The colon would still be required in an rvalue context. But the extension of that to subs seems to be: my &sub(Sub: \$args) Hmm, does that mean that a method actually looks like this? my &meth(Method: $self: \$args) I also wonder about hybrid hash/arrays: my %harry(HashArray: Key^Int --> Any); It would be nice to generalize this sufficiently
Re: Ways to add behavior
HaloO, Larry Wall wrote: : or is 'bound of' proper english? It doesn't really resonate for a native speaker. --snip-- : > Plus, as we've defined : >them above, subtypes are the most generic type you can name in Perl. --snip-- I wasn't using the term "generic" in a type-theoretic sense. Rather, I was calling them generic in an operational sense, which you just demonstrated. You can turn any other type into a "subtype" alias that adds no additional constraints. Maybe I should have said the "widest" type instead. With the introduction of kind capture variables ^T we could complety drop the subtype special form. As you pointed out the adding of constraints happens with the where clause anyway. Thus we return to the usage of the compile time name assignment form ::Blahh ::= ::Fasel where {...} where the :: in all cases means working on the MIR (Meta Information Repository) which is the world of names (In Russian, Mir (Мир) means "peace," and connotes "community." --- cited from Wikipedia). Question: shouldn't there be a natural 1 to 1 relation of ::T and ^T or globally ::*T and ^*T where the former is the name and the latter the kind represented by T? Of course scoping applies and there are anonymous things that can be captured into ^T vars at runtime. If the answer is 'yes' as I expect, I wonder if the compiler has to restrict the usage of ::= to scopes which don't depend on runtime evaluations like if $x < 10 { ::*Surprise ::= ::*FunnyType; say 'did it'; } Or should these be extracted out, making the above mean ::*Surprise ::= ::*FunnyType; # or further out if necessary if $x < 10 { say 'did it'; } : Question: does a subtype declaration work only on package-like things : which are addressed with a :: sigil? Or does your 'potentially : contravariant' mean that arrow types can be constraint or aliased, as : well? : : subtype TakesInt of Sub where { .sig =:= :(Int --> Any) }; : : my TakesInt &foo; : : foo('a string'); # type error Hmm, I would read that as declaring that &foo *returns* a TakesInt, not that &foo *is* a TakesInt. Just as my TakesInt @bar; declares an array of individual TakesInt elements. This is not too bad because then the & sigil is naturally associated with the :( --> ) arrow type syntax and the forms can be mixed only to the extent of signature aliasing: ::Takes3Ints ::= :(Int,Int,Int --> Any); my &foo:(Takes3Ints); How does arrow typing apply to the three data sigils $, @ and %? Compare: my $foo:(Int); # non-referential value type my $foo:(-->Int); # same? Or perhaps means anonymous ref/link/alias? my $foo:(Ref-->Int) # explicit reference? same as 'is ref' trait? my $foo:(Item: -->Int) # tied container Which is the default when the Int is used in the type slot of the declaration? my Int $foo; Could this be used to define the key type of hashes? my %foo:(Blahh-->Any); And shape of arrays my @foo:(Int,Int,Int-->Any); where the Int or subtypes of it are enforced and Any defaulted. Thus this could just be my @foo:(!,!,!); The covariant invocant/container types are of course my $item :(Item: --> Any); my @array:(Array: Int --> Any); my %hash :(Hash: Key --> Any); The & sigils have a free signature and ^ vars obviously have no signature other than pure type ;) -- $TSa.greeting := "HaloO"; # mind the echo!
Re: Ways to add behavior
HaloO, Stevan Little wrote: This is actually the principe behind the Ruby style singleton methods (the shadow class), it basically creates an anon-class which inherits from $x's original class, then it rebinds/blesses $x into the anon- class. It is very simple really :) Yes, it's the typical case were an implementation is way easier than the (type) theoretical modelling of such a simple "pointer" reassignment. Assignment in general is very difficult to model, actually. As for if this is/should be accessible through .meta, i am not sure that is a good idea. The reason being is that .meta brings with it the idea of metaclasses, which then relates to classes, and so now the user is thinking they are accessing the metaclass of the class of which $x is an instance. Indeed, we should drop the association of meta with class. There should be just meta *information* (MI) which is sort of opaque to the general public. The .meta method should return a MIO (Meta Info Object, My Internal Object, or what ever) from the MIR (Meta Info Repository). Note that mio in italian means 'my' or 'mine' depending on the grammatical slot. I would suggest instead that we have a method, which is found in Object which allows instances to add methods to themselves (and only themselves). In Ruby this is called 'add_singleton_method' or something like that. I use that same name in the metamodel prototype too. In the absence of that, what's going on seems more like $x.META::addmethod($arg); where META:: is smart enough to dispatch to the proper metaclass without throwing away the invocant, and then the metaclass decides what to do based on the instancehood of $x. Since we have imperative runtime forms of 'does' for role composition why not the equivalent on the 'has' installer. But I know it reads bad. $x has &action; $x has &.action = &action; # code slot form $x does &action; # &action wrapping role created on the fly? $x gets &action; # new keyword? But IIRC, re-opening of classes is now done with 'is also' and 'does also' for extending and 'is instead' and 'does instead' for replacing functionality. This reads better imperatively on the instance level: $x has also &action; In the prototype style the my form could use a class style declarator block: my $point { has Num $.x = 0; has Num $.y = 0; method magnitude { sqrt( $.x**2 + $.y**2 ) } } $a = $point; # kind is implicitly copied, that is $a.kind == $b.kind $b = $point; # which could also be tested with ^$a == ^$b or $a =^= $b $a.x = 3; # easy with COW and a pseudo-hash implementation of $point kind $a.y = 4; say $a.magnitude; # prints 5 I am not sure I like this for 2 reasons. 1) META:: smells like ::SUPER, and that feels like re-dispatching to me, which is not really what we need to be doing. I agree. Adding to an object incrementally slides it out of it's class's kind to ultimately become its own singleton kind. Hmm, this gives us a beautifully ugly cast operator syntax $foo.kind = Bar; # re-bless $foo.kind(Bar); # same? Bar.bless($foo); # same? $foo ^= Bar; # kind assignment available? if Bar{$foo} # theorytic query { $foo.kind = Bar; # success guaranteed, I almost wrote: guaran-tied :) } $foo.kind = Bar if Bar{$foo}; # as statement modifier to make such a transition in a single jump. The ^Bar kinding/blessing of $foo might not succeed unless ^Bar is prepared to accept ^$foo kinds, though. And, I think perlkind is expecting persistence of referential identity of $foo independent of the success or failure of the re-blessing. I guess there should be a dedicated exception kind to handle that. So you can sport a very experimental, explorative programming style. --
Re: Ways to add behavior
On Sat, Nov 05, 2005 at 01:55:11AM +0100, TSa wrote: : Larry Wall wrote: : >The notion of constraints or limitations is already conveyed by : >"where", and some subtypes may just be aliases. : : Wouldn't 'bound' work? Perhaps combined with 'on': : : bound SmallInt on Int where { 0 < $_ < 100 }; : : and : : Int bound SmallInt where { 0 < $_ < 100 }; : : or is 'bound of' proper english? It doesn't really resonate for a native speaker. : And perhaps ranges could be allowed in the type slot : : my 1..100 $x; : : $x = 101; # type error : : And with enums : : my enum $x; : : $x = g; # error unless &g exists and returns a type : # structurally equal to enum which : # might be the same as 0..3 It starts getting a bit special-casey to allow rvalue-ish expressions in the type slot. Now that we have a type sigil, maybe: my ^(1..100) $x my ^(enum ) $x; : > Plus, as we've defined : >them above, subtypes are the most generic type you can name in Perl. : : Ahm, why? They just add predicates that have to hold true. The only : genericity I see is that a subtype declaration doesn't need anything : remotely implementation like. Not even the constraint type must be : there yet: : : subtype Blahh of ::Fasel; # declaration of Fasel deferred : : my Blahh $b .=new; # compiles for now, but needs ::Fasel eventually : : BTW, could we restrict predicates to deal with the state available through : the type/kind that is constraint? This would allow compile time calculations : of contraint subsumption, type entailment and of upper and lower bounds. I wasn't using the term "generic" in a type-theoretic sense. Rather, I was calling them generic in an operational sense, which you just demonstrated. You can turn any other type into a "subtype" alias that adds no additional constraints. Maybe I should have said the "widest" type instead. : Question: does a subtype declaration work only on package-like things : which are addressed with a :: sigil? Or does your 'potentially : contravariant' mean that arrow types can be constraint or aliased, as : well? : : subtype TakesInt of Sub where { .sig =:= :(Int --> Any) }; : : my TakesInt &foo; : : foo('a string'); # type error Hmm, I would read that as declaring that &foo *returns* a TakesInt, not that &foo *is* a TakesInt. Just as my TakesInt @bar; declares an array of individual TakesInt elements. : This might actually produce the strange association of subtype : with subs and requesting corresponding methodtype, datatype, : roletype, etc. keywords for other kinds of types. I really don't know how far it makes sense to drive this. Mostly I'm just trying to keep the syntax open enough that the bikeshed doesn't end up looking like grafitti when we're done. Larry
Re: Ways to add behavior
HaloO, Larry Wall wrote: At the moment, I think the weakest word choice is "subtype". People from certain cultures will confuse subtypes with subclasses. Not to mention submethods and subroutines! The notion of constraints or limitations is already conveyed by "where", and some subtypes may just be aliases. Wouldn't 'bound' work? Perhaps combined with 'on': bound SmallInt on Int where { 0 < $_ < 100 }; and Int bound SmallInt where { 0 < $_ < 100 }; or is 'bound of' proper english? And perhaps ranges could be allowed in the type slot my 1..100 $x; $x = 101; # type error And with enums my enum $x; $x = g; # error unless &g exists and returns a type # structurally equal to enum which # might be the same as 0..3 Plus, as we've defined them above, subtypes are the most generic type you can name in Perl. Ahm, why? They just add predicates that have to hold true. The only genericity I see is that a subtype declaration doesn't need anything remotely implementation like. Not even the constraint type must be there yet: subtype Blahh of ::Fasel; # declaration of Fasel deferred my Blahh $b .=new; # compiles for now, but needs ::Fasel eventually BTW, could we restrict predicates to deal with the state available through the type/kind that is constraint? This would allow compile time calculations of contraint subsumption, type entailment and of upper and lower bounds. Question: does a subtype declaration work only on package-like things which are addressed with a :: sigil? Or does your 'potentially contravariant' mean that arrow types can be constraint or aliased, as well? subtype TakesInt of Sub where { .sig =:= :(Int --> Any) }; my TakesInt &foo; foo('a string'); # type error This might actually produce the strange association of subtype with subs and requesting corresponding methodtype, datatype, roletype, etc. keywords for other kinds of types. So maybe we should go with "type"...which is yet another thing I've waffled on repeatedly... HiHi. --
Re: Ways to add behavior
HaloO, Larry Wall wrote: On Wed, Oct 26, 2005 at 04:56:23PM -0600, Luke Palmer wrote: : > Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks : > if two objects are of the same type, : : Don't you mean $x.kind eqv $y.kind? I start to dislike the eqv name as generic value comparator because it looks too much like the dual of xor. And there is the numeric comparator <=> and its string companion cmp. But I don't want to re-open the settled discussion of the operator names. OTOH, we could use the Num kind as the prime representative of things that provide ==, !=, <=, >=, <, > and <=>. Actually != is a bit odd there, but I guess no one would accept <> even if it were available. But then keeping the ! logical negation indicator we could use !< and !> instead of >= and <= respectively. This is not too bad linguistically if we define < below !< not below # >= is an alias > above !> not above # <= is an alias == equal=!= not equal = equal != not equal # this one is just too beautiful # to become Perl6 reality :) and the string counter parts lt < ge !lt !< gt > le !gt !> eq == ne !eq =!= Thus logical negation becomes a meta prefix operator like meta postfix = deals with infix ops. The unless conditional form then means exactly the same as outer logical negation if $x != $y {...} if !($x == $y) {...} # same, also with space: ! (...) unless $x == $y {...} # same if $x not == $y {...} # same if not($x == $y) {...} # same, also with space: not (...) if($x == $y).not {...} # same, method form As a side effect the junctive annoyance if $x != any(1,2,3) {...} automagically becomes if !($x == any(1,2,3)) {...} The in-place modification unary method form then is $x.=not and might have an optional boolean argument whose negated form becomes the new boolean property. So $x.=not(0) means '$x becomes not false'. With bit beeing an abbreviation of 'be it' just as not means 'no true' this can be spelled $x.=bit(1) and read '$x becomes be it true' or some such. If the Num kind models the mathematical ideal of real numbers then $x == $y is synonym to false and $x != $y to true almost always. Anyone doing numerics knows that you should actually use abs($x - $y) < $eps. With $eps == 1 you get the integer case. Implementing Num as Int+Rem where 0 !> Rem < 1 the Int comparison would be spelled $x ==:rem(0) $y or perhaps better looking as $x == $y :rem(0) or $x ==:int $y Note that there is a slight difference to $x ==:eps(1.0) $y which is true for $x = 3.8 and $y = 4.2 because their delta is 0.4 while 3 < 4 intwise. The default fall-back in case of $x and $y beeing actual non-int nums could use e.g. :eps(1e-6) which of course is configurable via pragma use Num:eps(1e-10); The spelled out forms might read $x equal:int $y # infix form $x.equal( :int, $y ) # method form equal :int, $x, $y; # listop form and correspondingly $x below:int $y # infix form $x.below( :int, $y ) # method form below :int, $x, $y; # listop form This logical negation idea could even be driven further // err /!/ nerr || or |!| nor && and &!& nand ^^ xor ^!^ nxor eqv The same can be done with the equality/identity checkers where the intended concept is indicated by something between the two = chars == generic num-like equality=!= generic num-like inequality =:= referential identity =::= symbol identity =^= kind identity = value copy := referential binding ::= symbol binding and perhaps something like <::< type below >::> type above ^< kind below # or: <^ <^= <^< ^> kind above Now that infix:<::> has come available, maybe I mean: $x.kind :: $y.kind Well or $x =^= $y and also ^$x == ^$y Sorry, couldn't resist. --
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
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/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: 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, Rob Kinyon <[EMAIL PROTECTED]> wrote: > What about: > > class Foo is also { > method foo() { ... } > } > > Where the second foo() is no longer what the first foo() did. Just overwrite the vtable. > Furthermore, let's say you have: > > class Bar isa Foo { > method floober() { ... } > } > > If they were roles, then role Bar could alias all the methods it > inherits from role Foo. In other words, it can cache all the method > lookups at compile-time. That's a substantial savings. If they're open > classes, the runtime has to throw out all the cached lookups the > moment any of the classes upstream are modified. This one is a little better. It is expensive to rejig all the cached methods, but that expense comes at the time when you reopen. If you never reopen, you never pay a penalty. > 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. Unless your module is the one creating the Some::Classes, or unless (as you point out above) there are existing subclasses of Some::Class, or unless some other thing that you didn't think of, which is the whole point of this discussion. There is no omniscient library writer; there is no omniscient language designer. :-) Luke
Re: Roles vs. Classes (was Re: Ways to add behavior)
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. Larry
Re: Roles vs. Classes (was Re: Ways to add behavior)
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. -- c
Re: Ways to add behavior
On Wed, 2005-10-26 at 14:52 -0400, Uri Guttman wrote: > > "LW" == Larry Wall <[EMAIL PROTECTED]> writes: > LW> One wants to coin a word like "Qlass". Unfortunately "qlass" is > LW> too easy to misread as "glass". Oy veh, I'm getting notions of > LW> "the qlass is half empty" for a partially instantiated object. > > [EMAIL PROTECTED], > > i think you need some immediate mental help. please step back from the > keyboard before you commit such a sin again. the next time, i will ask > gloria to stick you with a knitting needle. > > is the smiley :) or (: ? I can't believe you missed the opportunity to write "qloria". -- c
Re: Roles vs. Classes (was Re: Ways to add behavior)
On 10/26/05, Luke Palmer <[EMAIL PROTECTED]> wrote: [snip] > Okay, an open class means you can add methods to it, right? So, let's > say you have this class: > > class Foo { > method foo() {...} > method bar() {...} > } > > And this code: > > my Foo $x = Foo.new; > $x.foo(); > $x.bar(); > > This might be compiled to the following pseudo intermediate code: > > my $x = Foo[0](); > Foo[1]($x); > Foo[2]($x); > > Now let's say you extend the class: > >class Foo is also { >method baz() {...} >} > > Is there any reason that the preceding pseudo intermediate code is no > longer valid? I don't see one; baz() is just installed in slot 3. So > why would you say it was faster to have it closed? What about: class Foo is also { method foo() { ... } } Where the second foo() is no longer what the first foo() did. Furthermore, let's say you have: class Bar isa Foo { method floober() { ... } } If they were roles, then role Bar could alias all the methods it inherits from role Foo. In other words, it can cache all the method lookups at compile-time. That's a substantial savings. If they're open classes, the runtime has to throw out all the cached lookups the moment any of the classes upstream are modified. 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. Rob
Re: Roles vs. Classes (was Re: Ways to add behavior)
On Wed, 2005-10-26 at 19:22 -0600, Luke Palmer wrote: > But we find that many programmers make decisions that trade > readability and extensibility for an extra 1% of speed, even when they > are writing a command-line frontend to MPlayer[1]. If those people > are module writers, then we have a bunch of modules on CPAN that are > not friendly to the user who wants to use the module in the one way > the writer didn't expect. Worse, that's a *theoretical* 1% of speed based on non-profiled code. > And if you're going to use roles for everything because they're closed > and they will gain you 2% of speed on one particular backend, then > we'll have to make the same rule for them too. I know it sounds like > we're "babying" our programmers. We are, because it's such a > widespread superstition. I prefer to think of it as "Helping to prevent them from writing unreusable code." > And just to reinforce that it's a superstition: a theory defines a > vtable. If you extend the class in an incompatible way, you have to > make a new instance of its theory, defining new vtable slots. Once > the new vtable is created, it is just as fast as the old one. There > is no speed loss whatsoever for keeping your class open. Even further, don't forget that someone, somewhere will really need to do something you didn't think of. Either he extends your class somehow or works around it in an ugly, funky way. Which one is faster to write? Which one is faster to execute? Which one is more likely to be correct? Which one is more maintainable? -- c
Re: Ways to add behavior
On Wed, Oct 26, 2005 at 06:34:48PM -0700, Larry Wall wrote: : On Wed, Oct 26, 2005 at 04:56:23PM -0600, Luke Palmer wrote: : : > Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks : : > if two objects are of the same type, : : : : Don't you mean $x.kind eqv $y.kind? : : : : Ugh. : : Now that infix:<::> has come available, maybe I mean: : : $x.kind :: $y.kind And maybe eq and == could degenerate to :: if both args aren't coercable to the desired type. Larry
Re: Ways to add behavior
On Wed, Oct 26, 2005 at 04:56:23PM -0600, Luke Palmer wrote: : > Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks : > if two objects are of the same type, : : Don't you mean $x.kind eqv $y.kind? : : Ugh. Now that infix:<::> has come available, maybe I mean: $x.kind :: $y.kind Now all we need is infix:<:> to calculate the value of the relationship of two items, and we can write: $a : $b :: $c : $d :-) * .5 Larry
Re: Roles vs. Classes (was Re: Ways to add behavior)
On Wed, Oct 26, 2005 at 08:48:12PM -0400, Rob Kinyon wrote: : If a role is an immutable class, that means that its internals cannot : be changed. Hence, the compiler can trust that it will be the same at : the end as at the beginning. Which means it's optimized. Which means : my objects run faster if I create them from roles than if I create : them from classes. And, given that this seems to be the sole : difference between them (mutability vs. immutability), why would I use : classes as my standard? Because it might be a premature optimization to the extent that it restricts flexibility before you know whether it's going to affect performance. Part of the power of Ruby on Rails reputedly comes from the fact that Ruby leaves its classes open by default. Larry
Re: Roles vs. Classes (was Re: Ways to add behavior)
On 10/26/05, Rob Kinyon <[EMAIL PROTECTED]> wrote: > On 10/26/05, chromatic <[EMAIL PROTECTED]> wrote: > > On Wed, 2005-10-26 at 20:29 -0400, Rob Kinyon wrote: > > > > > I would prefer to use roles as they're closed by default, leaving > > > "class" to be my powertool, if I need the power. > > > > I don't understand this desire; can you explain your reasoning? > > If a role is an immutable class, that means that its internals cannot > be changed. Hence, the compiler can trust that it will be the same at > the end as at the beginning. Which means it's optimized. Which means > my objects run faster if I create them from roles than if I create > them from classes. And, given that this seems to be the sole > difference between them (mutability vs. immutability), why would I use > classes as my standard? Okay, an open class means you can add methods to it, right? So, let's say you have this class: class Foo { method foo() {...} method bar() {...} } And this code: my Foo $x = Foo.new; $x.foo(); $x.bar(); This might be compiled to the following pseudo intermediate code: my $x = Foo[0](); Foo[1]($x); Foo[2]($x); Now let's say you extend the class: class Foo is also { method baz() {...} } Is there any reason that the preceding pseudo intermediate code is no longer valid? I don't see one; baz() is just installed in slot 3. So why would you say it was faster to have it closed? Indeed, it *could* be faster. But we find that many programmers make decisions that trade readability and extensibility for an extra 1% of speed, even when they are writing a command-line frontend to MPlayer[1]. If those people are module writers, then we have a bunch of modules on CPAN that are not friendly to the user who wants to use the module in the one way the writer didn't expect. So the reason we made classes open by default is so that people wouldn't have a chance to make that decision until they're more experienced. Indeed, no module writer can say that a class is closed; only the main program may say that, because the main program knows the most about how everything is used. The precise definition of "main program" is not well-defined yet, but it's there so that a module writer doesn't close himself off from the world without knowing how his module is even being used. And if you're going to use roles for everything because they're closed and they will gain you 2% of speed on one particular backend, then we'll have to make the same rule for them too. I know it sounds like we're "babying" our programmers. We are, because it's such a widespread superstition. And just to reinforce that it's a superstition: a theory defines a vtable. If you extend the class in an incompatible way, you have to make a new instance of its theory, defining new vtable slots. Once the new vtable is created, it is just as fast as the old one. There is no speed loss whatsoever for keeping your class open. Luke [1] This is a concrete example that I actually witnessed.
Re: Roles vs. Classes (was Re: Ways to add behavior)
On 10/26/05, chromatic <[EMAIL PROTECTED]> wrote: > On Wed, 2005-10-26 at 20:29 -0400, Rob Kinyon wrote: > > > I would prefer to use roles as they're closed by default, leaving > > "class" to be my powertool, if I need the power. > > I don't understand this desire; can you explain your reasoning? If a role is an immutable class, that means that its internals cannot be changed. Hence, the compiler can trust that it will be the same at the end as at the beginning. Which means it's optimized. Which means my objects run faster if I create them from roles than if I create them from classes. And, given that this seems to be the sole difference between them (mutability vs. immutability), why would I use classes as my standard? Rob
Re: Roles vs. Classes (was Re: Ways to add behavior)
On Wed, 2005-10-26 at 20:29 -0400, Rob Kinyon wrote: > I would prefer to use roles as they're closed by default, leaving > "class" to be my powertool, if I need the power. I don't understand this desire; can you explain your reasoning? (NB: "closed" here, as I use it, still *does not* correspond to licensing or availability of the source code.) -- c
Roles vs. Classes (was Re: Ways to add behavior)
> : 3) Aren't classes mutable and roles immutable by default only? Or has > : this changed? > > Of course. To change the default for a role, call it a class, and > to change the default for a class, call it a role. :-) Does this mean that roles are the recommended way to create immutable classes? Given that roles and classes now seem to differ only in their mutability, I can't see a reason why I would use class as my default object definer. I would prefer to use roles as they're closed by default, leaving "class" to be my powertool, if I need the power. Rob
Re: Ways to add behavior
On 10/26/05, Larry Wall <[EMAIL PROTECTED]> wrote: > So maybe we can define our terms like this: > > type: a completely generic metaterm for any of the following, > and then some. > > class: a mutable interface object that manages instances in the > "classical" way, with covariant derivational properties. > > role: an immutable and possibly generic interface class, with > covariant compositional properties. > > kind: the abstract, often unnamed type of an actual instance > or storage location, abstracted from any of its machinery or > degree of definedness. You should not generally declare a "kind", > they just happen. We're screwing around with existing OO jargon, so it's probably not too bad to screw around with this one too, especially since it only appears under the covers in ML. A kind is the "signature" of a type. So, for instance, Int has kind * Array has kind * -> * Array Int has kind * Other than that, I think the term works find. > subtype: a potentially contravariant type based on any of the > previous types, allowed to impose constraints that are more > selective than a kind is allowed to be. > > Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks > if two objects are of the same type, Don't you mean $x.kind eqv $y.kind? Ugh. > but $x.kind isn't a class-like > object, only an identity of some sort. $x.meta returns the Class > instance, or whatever. > > At the moment, I think the weakest word choice is "subtype". > People from certain cultures will confuse subtypes with subclasses. > The notion of constraints or limitations is already conveyed by > "where", and some subtypes may just be aliases. Plus, as we've defined > them above, subtypes are the most generic type you can name in Perl. > So maybe we should go with "type"...which is yet another thing I've > waffled on repeatedly... "constrained type"? Though that only works for the literature, not Perl's active vocabulary. Luke
Re: Ways to add behavior
On Wed, Oct 26, 2005 at 03:54:35PM -0400, Rob Kinyon wrote: : > So maybe we can define our terms like this: : > : > type: a completely generic metaterm for any of the following, : > and then some. : > : > class: a mutable interface object that manages instances in the : > "classical" way, with covariant derivational properties. : > : > role: an immutable and possibly generic interface class, with : > covariant compositional properties. : > : > kind: the abstract, often unnamed type of an actual instance : > or storage location, abstracted from any of its machinery or : > degree of definedness. You should not generally declare a "kind", : > they just happen. : > : > subtype: a potentially contravariant type based on any of the : > previous types, allowed to impose constraints that are more : > selective than a kind is allowed to be. : > : > Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks : > if two objects are of the same type, but $x.kind isn't a class-like : > object, only an identity of some sort. $x.meta returns the Class : > instance, or whatever. : : A few questions: : 1) Where does prototype-style OO fit into all of this? I hope it's not : through repeated eigenclasses (or whatever they're called this week) : ... that just sounds too heavy. I don't profess to be an expert on prototype style, but I think even if we do it with eigenclasses it's not too heavy as long as we find a way to share structurally identical eigenclasses. Copy on write would get some sharing benefit, though wouldn't coalesce eigenclasses that just happened to converge on the same definition. On the other hand, I think we can abstract out kindness sufficiently well that, for the prototype kind of object, the machinery can just clone the method refs along with the attributes. : 2) Isn't Dog|Cat kinda declaring a kind? If it resolves to a set of types, it can be *used* as a kind. But if you insist on the ORness of it, then it's really a subtype, because a kind supports all of its member roles, not just one of them. : Thus, can't you say "my Dog|Cat $catdog;" and be talking about a kind? No, that merely asserts that the kind of $catdog must support those two interfaces, assuming | just constructs a set. But it's not clear that we'll support | there at all, but assuming AND juxtapositional syntax, we can just write that: my Dog Cat $catdog; and get the same constraints on $catdog. And the fact of the matter is that either of Dog or Cat may be a constrained subtype, not a real kind. If we say my Even Odd $evenodd; then we'll never match our constraints, despite the fact that Even and Odd are both subtypes of Int, and Int can function as a kind. : I would think that a "named kind" is just a role ... No, other way around, a role is just a named kind. More precisely, a non-generic role can be forced to compose to a class that can function as a kind. But there can be kinds that don't behave well according to the rules of roles. You can't compose two kinds that happen to represent native types, for instance. : 3) Aren't classes mutable and roles immutable by default only? Or has : this changed? Of course. To change the default for a role, call it a class, and to change the default for a class, call it a role. :-) Larry
Re: Ways to add behavior
> So maybe we can define our terms like this: > > type: a completely generic metaterm for any of the following, > and then some. > > class: a mutable interface object that manages instances in the > "classical" way, with covariant derivational properties. > > role: an immutable and possibly generic interface class, with > covariant compositional properties. > > kind: the abstract, often unnamed type of an actual instance > or storage location, abstracted from any of its machinery or > degree of definedness. You should not generally declare a "kind", > they just happen. > > subtype: a potentially contravariant type based on any of the > previous types, allowed to impose constraints that are more > selective than a kind is allowed to be. > > Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks > if two objects are of the same type, but $x.kind isn't a class-like > object, only an identity of some sort. $x.meta returns the Class > instance, or whatever. A few questions: 1) Where does prototype-style OO fit into all of this? I hope it's not through repeated eigenclasses (or whatever they're called this week) ... that just sounds too heavy. 2) Isn't Dog|Cat kinda declaring a kind? Thus, can't you say "my Dog|Cat $catdog;" and be talking about a kind? I would think that a "named kind" is just a role ... 3) Aren't classes mutable and roles immutable by default only? Or has this changed? Rob
Re: Ways to add behavior
> "LW" == Larry Wall <[EMAIL PROTECTED]> writes: LW> One wants to coin a word like "Qlass". Unfortunately "qlass" is LW> too easy to misread as "glass". Oy veh, I'm getting notions of LW> "the qlass is half empty" for a partially instantiated object. [EMAIL PROTECTED], i think you need some immediate mental help. please step back from the keyboard before you commit such a sin again. the next time, i will ask gloria to stick you with a knitting needle. is the smiley :) or (: ? uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: Ways to add behavior
On Wed, Oct 26, 2005 at 12:22:07PM -0400, Stevan Little wrote: : : On Oct 26, 2005, at 12:05 PM, Larry Wall wrote: : >Of course, there are other words that are somewhat synonymous with : >"class", Unfortunately "sort" is already hosed. Maybe "kind". : : Actually "kind" is used in the "Core Calculus for Metaclasses" paper : which I brought to the hackathon (not sure if you got to read it or : not). Here is a link: : : http://research.sun.com/projects/plrg/core-calculus.pdf : : They present an rather interesting view on things, that the : definition of the instance creating portion of a "class" should be : seperated from the "class" or "kind" portion of the class. Actually : the first metamodel prototype grew out of an implementation of the : model they describe in the paper. Interesting. I didn't read it, but a bunch of us seem to be converging on the same elephant. I'm thinking of "kind" as the actual type of a real instance separate from the machinery. I think it probably corresponds to what Luke is saying about classes not really having names. So maybe we can define our terms like this: type: a completely generic metaterm for any of the following, and then some. class: a mutable interface object that manages instances in the "classical" way, with covariant derivational properties. role: an immutable and possibly generic interface class, with covariant compositional properties. kind: the abstract, often unnamed type of an actual instance or storage location, abstracted from any of its machinery or degree of definedness. You should not generally declare a "kind", they just happen. subtype: a potentially contravariant type based on any of the previous types, allowed to impose constraints that are more selective than a kind is allowed to be. Then ^T $x binds T to the kind of $x. And $x.kind == $y.kind asks if two objects are of the same type, but $x.kind isn't a class-like object, only an identity of some sort. $x.meta returns the Class instance, or whatever. At the moment, I think the weakest word choice is "subtype". People from certain cultures will confuse subtypes with subclasses. The notion of constraints or limitations is already conveyed by "where", and some subtypes may just be aliases. Plus, as we've defined them above, subtypes are the most generic type you can name in Perl. So maybe we should go with "type"...which is yet another thing I've waffled on repeatedly... Larry
Re: Ways to add behavior
HaloO, Austin Frank wrote: Which (sort of) takes us back to TSa's (non)sign-off note from 10/5, wherein he suggested: I just can't help it, I love the good work done on this list! And thanks for spelling the acronym correctly. The Kindly One of a class beeing the representative like the President of the United States is the First of Man :) With limited runtime, of course ... Who knows the Kindly Ones from the Sandman? This nicely complements the seven Endless and their sigils ;) But the German Sandmännchen has to put the kids to sleep now---sweet dreams to everyone. -- $TSa.greeting := "HaloO"; # mind the echo!
Re: Ways to add behavior
Larry Wall <[EMAIL PROTECTED]> wrote: > Of course, there are other words that are somewhat synonymous with > "class", Unfortunately "sort" is already hosed. Maybe "kind". > Then evolutionists could make jokes about the K(T) boundary, and > creationists could make jokes about "reproducing after their kind". > Some of us could make either kind of joke. But perhaps it wouldn't > be kind. Flavor. (Shades of CLOS, but we're already building the most flexible object system since it...) -- Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]> Perl and Parrot hacker
Re: Ways to add behavior
Stevan Little: > They present an rather interesting view on things, that the > definition of the instance creating portion of a "class" should be > seperated from the "class" or "kind" portion of the class. Its quality. Its character. Its features. Its face. -- Grtz, Ruud
Re: Ways to add behavior
On 10/26/05, Stevan Little <[EMAIL PROTECTED]> wrote: > > On Oct 26, 2005, at 12:05 PM, Larry Wall wrote: > > Of course, there are other words that are somewhat synonymous with > > "class", Unfortunately "sort" is already hosed. Maybe "kind". > > Actually "kind" is used in the "Core Calculus for Metaclasses" paper > which I brought to the hackathon (not sure if you got to read it or > not). Here is a link: > > http://research.sun.com/projects/plrg/core-calculus.pdf > > They present an rather interesting view on things, that the > definition of the instance creating portion of a "class" should be > seperated from the "class" or "kind" portion of the class. Actually > the first metamodel prototype grew out of an implementation of the > model they describe in the paper. This might dovetail quite nicely into the discussion of how types are now sets instead of junctions. Objects are now a junction of the various kinds that were used to create it. Thus, boxed types are now almost trivial to implement ... ? Rob
Re: Ways to add behavior
Larry Wall: > But perhaps it wouldn't be kind. 'caste' wouldn't either. For inspiraton: type sort class variety brand category breed manner style nature form hue caste set background stage setting milieu locale range assortment selection mixture strain suite scenery rank grade division status genre ... -- Grtz, Ruud
Re: Ways to add behavior
On Wed, Oct 26, 2005 at 09:05:22AM -0700, Larry Wall wrote: > Of course, there are other words that are somewhat synonymous with > "class", Unfortunately "sort" is already hosed. Maybe "kind". Maybe we could go with something Linnaean like "family" or "genus" even though their relation to "class" isn't quite the same. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Ways to add behavior
On Oct 26, 2005, at 12:05 PM, Larry Wall wrote: Of course, there are other words that are somewhat synonymous with "class", Unfortunately "sort" is already hosed. Maybe "kind". Actually "kind" is used in the "Core Calculus for Metaclasses" paper which I brought to the hackathon (not sure if you got to read it or not). Here is a link: http://research.sun.com/projects/plrg/core-calculus.pdf They present an rather interesting view on things, that the definition of the instance creating portion of a "class" should be seperated from the "class" or "kind" portion of the class. Actually the first metamodel prototype grew out of an implementation of the model they describe in the paper. Stevan
Re: Ways to add behavior
Larry Wall wrote: Of course, there are other words that are somewhat synonymous with "class", Unfortunately "sort" is already hosed. Maybe "kind". Then evolutionists could make jokes about the K(T) boundary, and creationists could make jokes about "reproducing after their kind". Some of us could make either kind of joke. But perhaps it wouldn't be kind. Which (sort of) takes us back to TSa's (non)sign-off note from 10/5, wherein he suggested: > I've always taken the 'what type of expression' approach to > programming languages and thus have an affinity to type systems and > type theory. > With 'type' in general and 'data type' in particular beeing too > misleading or used in too many different meanings in other programming > languages I propose to coin the notion of 'kind' which has the nice > double meaning of nice and sort. And as such gives the nice pun > > Perl 6, the kind language > > with the two "meanings" > > Perl 6, a kind of language >, the language of kind(ness) I don't know if this is a good sign or a bad one, but the jokes started before you even made the suggestion! :) /au
Re: Ways to add behavior
On Wed, Oct 26, 2005 at 11:31:28AM -0400, Rob Kinyon wrote: : > That's just self.meta.add_method($label, $method) by my lights. : > A .meta already implies/ignores the .class coercion. If we are to : > support prototype-based programming $x.meta *must not care* whether : > it has been given a class or an instance or something in between. : > What I am calling a "class" here is basically that portion of the : > current instance that is the same for all members of its class. : > And that common information presumably includes information on what to : > do if a method is called that is not directly recognized by the object. : > Class-based and prototype-based systems have different answers to that, : > but they have something in common, and I'd like to abstract that out : > and call it something. I've been calling it "class", but maybe I : > should call it something else to avoid confusion. A "type" maybe. : > That would imply that ¢ is really a "type" variable rather than a class : > variable. But maybe "type" is too overloaded already. But maybe not. : : 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. Yes, I was sorry it got Warnocked. : Plus, if you think about the definitions that go into creating an : instance (class, role, prototype, etc), it makes sense that if the : instance is the smallest indivisible thing there is, then the things : that go about being its definition are the quarks. : : > Anyway, if my "class" turns into "type" or something else, maybe I : > can be persuaded to go with ^T instead of ¢T. : : Q(T) ? :-) Will be misinterpreted as sexist, so not on the Q/T. :-) One wants to coin a word like "Qlass". Unfortunately "qlass" is too easy to misread as "glass". Oy veh, I'm getting notions of "the qlass is half empty" for a partially instantiated object. But it's probably not appropriate to coin a new term if we can force "type" to work. Someone please martial some objections. Of course, there are other words that are somewhat synonymous with "class", Unfortunately "sort" is already hosed. Maybe "kind". Then evolutionists could make jokes about the K(T) boundary, and creationists could make jokes about "reproducing after their kind". Some of us could make either kind of joke. But perhaps it wouldn't be kind. Larry
Re: Ways to add behavior
> That's just self.meta.add_method($label, $method) by my lights. > A .meta already implies/ignores the .class coercion. If we are to > support prototype-based programming $x.meta *must not care* whether > it has been given a class or an instance or something in between. > What I am calling a "class" here is basically that portion of the > current instance that is the same for all members of its class. > And that common information presumably includes information on what to > do if a method is called that is not directly recognized by the object. > Class-based and prototype-based systems have different answers to that, > but they have something in common, and I'd like to abstract that out > and call it something. I've been calling it "class", but maybe I > should call it something else to avoid confusion. A "type" maybe. > That would imply that ¢ is really a "type" variable rather than a class > variable. But maybe "type" is too overloaded already. But maybe not. 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. Plus, if you think about the definitions that go into creating an instance (class, role, prototype, etc), it makes sense that if the instance is the smallest indivisible thing there is, then the things that go about being its definition are the quarks. > Anyway, if my "class" turns into "type" or something else, maybe I > can be persuaded to go with ^T instead of ¢T. Q(T) ? :-) Rob
Re: Ways to add behavior
On Tue, Oct 25, 2005 at 05:17:40PM -0400, Stevan Little wrote: : Larry, : : On Oct 25, 2005, at 4:37 PM, Larry Wall wrote: : >On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote: : >: # behavior through prototype -- guessing realistic syntax : >: Base.meta.add_method( : >: do_it => method ($arg) { : >: say "doing $arg!"; : >: }); : >: : >: : >: # or, just add it to a single instance : >: $x.meta.add_method( : >: do_it => method ($arg) { : >: say "doing $arg!"; : >: }); : > : >I don't have a comment on your actual question, but I'd like to use : >this opportunity to point out the symmetry of Base and $x at this : >point, and the fact that .meta can't simply call .add_method in the : >metaclass, or it would lose track of the original invocant, which is : >needed to convey both class and instance information. I'm not sure : >it's even possible to say : > : >$m = $x.meta; : >$m.addmethod($arg); : > : >The only way that can work is if $x.meta returns a shadow class that : >is prebound only to $x. (Though that might explain how .addmethod : >knows it's only adding a method to the object.) : : This is actually the principe behind the Ruby style singleton methods : (the shadow class), it basically creates an anon-class which inherits : from $x's original class, then it rebinds/blesses $x into the anon- : class. It is very simple really :) Sure, but such a heavy behavior shouldn't be implied merely by trying to get at the metaclass. : As for if this is/should be accessible through .meta, i am not sure : that is a good idea. The reason being is that .meta brings with it : the idea of metaclasses, which then relates to classes, and so now : the user is thinking they are accessing the metaclass of the class of : which $x is an instance. : : I would suggest instead that we have a method, which is found in : Object which allows instances to add methods to themselves (and only : themselves). In Ruby this is called 'add_singleton_method' or : something like that. I use that same name in the metamodel prototype : too. That's fine, and fits in with Prototype-Think anyway. : Here is how it could be done. : : class ShadowClass does Class {} : : class Object is reopened { That might change to "is also", the generic trait for appending to things that may or may not be classes. (And "is instead" is used to replace things.) : method add_singleton_method (Str $label, Method $method) { : if ($?SELF.class.class != ShadowClass) { s/$?SELF/self/ And I think .class should be a coercion to the "class" view of its invocant, which would make your second .class a no-op. I think what you're calling .class.class I'm calling .meta.class. I want to think of the class as an abstraction that is not an object. Everything you call Class I want to sweep behind .meta, because the metaclass instance is the real class object. : my $shadow = ShadowClass.new(); : $shadow.meta.superclasses([ $shadow ]); : $?SELF.class = $shadow; I think that should be self.meta = $shadow. .class is not an lvalue--it's just a restricted view of the current object. (Again, by my definitions. I realize clashing definitions are at work here. Maybe I can come up with a different word for what I call "class". Or maybe I get "class", and you get "Class" :-) * .5 : } : $?SELF.class.meta.add_method($label, $method); That's just self.meta.add_method($label, $method) by my lights. A .meta already implies/ignores the .class coercion. If we are to support prototype-based programming $x.meta *must not care* whether it has been given a class or an instance or something in between. What I am calling a "class" here is basically that portion of the current instance that is the same for all members of its class. And that common information presumably includes information on what to do if a method is called that is not directly recognized by the object. Class-based and prototype-based systems have different answers to that, but they have something in common, and I'd like to abstract that out and call it something. I've been calling it "class", but maybe I should call it something else to avoid confusion. A "type" maybe. That would imply that ¢ is really a "type" variable rather than a class variable. But maybe "type" is too overloaded already. But maybe not. Anyway, if my "class" turns into "type" or something else, maybe I can be persuaded to go with ^T instead of ¢T. Larry
Re: Ways to add behavior
Larry, On Oct 25, 2005, at 4:37 PM, Larry Wall wrote: On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote: : # behavior through prototype -- guessing realistic syntax : Base.meta.add_method( : do_it => method ($arg) { : say "doing $arg!"; : }); : : : # or, just add it to a single instance : $x.meta.add_method( : do_it => method ($arg) { : say "doing $arg!"; : }); I don't have a comment on your actual question, but I'd like to use this opportunity to point out the symmetry of Base and $x at this point, and the fact that .meta can't simply call .add_method in the metaclass, or it would lose track of the original invocant, which is needed to convey both class and instance information. I'm not sure it's even possible to say $m = $x.meta; $m.addmethod($arg); The only way that can work is if $x.meta returns a shadow class that is prebound only to $x. (Though that might explain how .addmethod knows it's only adding a method to the object.) This is actually the principe behind the Ruby style singleton methods (the shadow class), it basically creates an anon-class which inherits from $x's original class, then it rebinds/blesses $x into the anon- class. It is very simple really :) As for if this is/should be accessible through .meta, i am not sure that is a good idea. The reason being is that .meta brings with it the idea of metaclasses, which then relates to classes, and so now the user is thinking they are accessing the metaclass of the class of which $x is an instance. I would suggest instead that we have a method, which is found in Object which allows instances to add methods to themselves (and only themselves). In Ruby this is called 'add_singleton_method' or something like that. I use that same name in the metamodel prototype too. In the absence of that, what's going on seems more like $x.META::addmethod($arg); where META:: is smart enough to dispatch to the proper metaclass without throwing away the invocant, and then the metaclass decides what to do based on the instancehood of $x. I am not sure I like this for 2 reasons. 1) META:: smells like ::SUPER, and that feels like re-dispatching to me, which is not really what we need to be doing. 2) there is not need to send this back to the metaclass level. The whole thing could be accomplished as an instance method of Object. Here is how it could be done. class ShadowClass does Class {} class Object is reopened { method add_singleton_method (Str $label, Method $method) { if ($?SELF.class.class != ShadowClass) { my $shadow = ShadowClass.new(); $shadow.meta.superclasses([ $shadow ]); $?SELF.class = $shadow; } $?SELF.class.meta.add_method($label, $method); } } Stevan
Re: Ways to add behavior
On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote: : # behavior through prototype -- guessing realistic syntax : Base.meta.add_method( : do_it => method ($arg) { : say "doing $arg!"; : }); : : : # or, just add it to a single instance : $x.meta.add_method( : do_it => method ($arg) { : say "doing $arg!"; : }); I don't have a comment on your actual question, but I'd like to use this opportunity to point out the symmetry of Base and $x at this point, and the fact that .meta can't simply call .add_method in the metaclass, or it would lose track of the original invocant, which is needed to convey both class and instance information. I'm not sure it's even possible to say $m = $x.meta; $m.addmethod($arg); The only way that can work is if $x.meta returns a shadow class that is prebound only to $x. (Though that might explain how .addmethod knows it's only adding a method to the object.) In the absence of that, what's going on seems more like $x.META::addmethod($arg); where META:: is smart enough to dispatch to the proper metaclass without throwing away the invocant, and then the metaclass decides what to do based on the instancehood of $x. Larry