Re: Junctions of classes, roles, etc.
Abhijit Mahabal wrote: When you dispatch, what happens would depend upon WALKMETH (according to the pseudocode for CALLONE in A12). Usually the first inherited method would get called. Ohh, yes, that thing. I forget about it. And actually I hope that there's a version among the standard pragmas that gives an error. Or actually this option should go to the typechecker and then the WALKMETH would nicely find a single, most specific method to call :) But the important thing for me in this thread is that there are no junctive bark methods in the alien beast classes! Well, unless the WALKMETH of choice implements them =:) -- TSa (Thomas Sandlaß)
Re: Junctions of classes, roles, etc.
David Storrs wrote: Let's move this away from simple types like Str and Int for a moment. If you consider them simple... Tell me what this does: class Tree { method bark() { die Cannot instantiate a Tree--it is abstract! } } class Birch { method bark() { return White, papery } } class Oak { method bark() { return Dark, heavy } } class Dog { method bark() { print Woof, woof!; return bow wow } } Four 'pure' classes so far. class AlienBeastie isa Tree isa Dog {} Here you get an error/warning of a composition time conflict between Tree::bark and Dog::bark. BTW, it's 'is' not 'isa'. My preferred syntax for multiple inheritance is the junctive notation 'is Tree Dog' for subclassing because it nicely allows for superclassing with 'is Tree | Dog'. class WhiteAlienBeastie isa Birch isa Dog {} Same for Birch::bark and Dog::bark. class HeavyAlienBeastie isa Oak isa Dog {} Same. sub Foo(Tree|Dog $x) { $x.bark() } This might dispatch correctly for 'pure' Trees, Dogs etc. but not for your mixed classes above. Regards, -- TSa (Thomas Sandlaß)
Re: Junctions of classes, roles, etc.
On Mon, 2 May 2005, [ISO-8859-1] Thomas Sandlaß wrote: David Storrs wrote: Tell me what this does: class Tree { method bark() { die Cannot instantiate a Tree--it is abstract! } } class Birch { method bark() { return White, papery } } class Oak { method bark() { return Dark, heavy } } class Dog { method bark() { print Woof, woof!; return bow wow } } Four 'pure' classes so far. class AlienBeastie isa Tree isa Dog {} Here you get an error/warning of a composition time conflict between Tree::bark and Dog::bark. I don't think so; I had come to the same conclusion before realising that we are talking inheritance here, not roles. So no trouble at class composition time. Superclasses do not enter the picture while composing. You'd be right if s/isa/is/ and then s/is/does/, of course. When you dispatch, what happens would depend upon WALKMETH (according to the pseudocode for CALLONE in A12). Usually the first inherited method would get called. TSa (Thomas Sandlaß) regards, abhijit
Re: Junctions of classes, roles, etc.
On Mon, May 02, 2005 at 06:49:10PM +0200, Thomas Sandlaß wrote: David Storrs wrote: Let's move this away from simple types like Str and Int for a moment. If you consider them simple... When compared to arbitrary-class-that-was-defined-by- arbitrary-programmer-of- arbitrary-and-unknown-skill-level then yes, I consider them to be extremely simple. Tell me what this does: class Tree { method bark() { die Cannot instantiate a Tree--it is abstract! } } class Birch { method bark() { return White, papery } } class Oak { method bark() { return Dark, heavy } } class Dog { method bark() { print Woof, woof!; return bow wow } } Four 'pure' classes so far. Dog is not pure according to the definition of pure class that I know (no side effects in any method, constructor, or subclass). Maybe 'pure class' means something else to you? class AlienBeastie isa Tree isa Dog {} Here you get an error/warning of a composition time conflict between Tree::bark and Dog::bark. So that I'm clear, is this your opinion/preference or is it based on material from the SEAs? If the latter, could you point me to the relevant passage? My preferred syntax for multiple inheritance is the junctive notation 'is Tree Dog' for subclassing because it nicely allows for superclassing with 'is Tree | Dog'. Again, so that I'm clear--this is your preference, and is not derived from any authoritative source, correct? This might dispatch correctly for 'pure' Trees, Dogs etc. but not for your mixed classes above. As I noted above, Dog is not 'pure' by the definition I know so I'm not sure what to make of this statement. --Dks
Re: Junctions of classes, roles, etc.
David Storrs writes: On Mon, May 02, 2005 at 06:49:10PM +0200, Thomas Sandla wrote: David Storrs wrote: class Tree { method bark() { die Cannot instantiate a Tree--it is abstract! } } class Birch { method bark() { return White, papery } } class Oak { method bark() { return Dark, heavy } } class Dog { method bark() { print Woof, woof!; return bow wow } } class AlienBeastie isa Tree isa Dog {} Here you get an error/warning of a composition time conflict between Tree::bark and Dog::bark. So that I'm clear, is this your opinion/preference or is it based on material from the SEAs? If the latter, could you point me to the relevant passage? As has been pointed out, there's no composition going on. But we are getting rid of search order problems, so you'll get an ambiguous method call error at some point. Whether this is at the time you create the class or the time you try to call the method, I do not know. My preferred syntax for multiple inheritance is the junctive notation 'is Tree Dog' for subclassing because it nicely allows for superclassing with 'is Tree | Dog'. Again, so that I'm clear--this is your preference, and is not derived from any authoritative source, correct? Not authoritative. I, for one, really want the ability to superclass a posteriori, but I'm not sure this is how you do it. Luke
Re: Junctions of classes, roles, etc.
On Sat, 2005-04-30 at 16:55 -0700, Brent 'Dax' Royal-Gordon wrote: Aaron Sherman [EMAIL PROTECTED] wrote: On Sat, 2005-04-30 at 22:24 +0800, Autrijus Tang wrote: That would be absolutely horrible. Str|Int is simply the type of Yes|1, isn't it? That would certainly make signature matching on different kinds of junctive types trivial. Nope. You all seem to have some very strong opinions, and I'm unable to have a discussion around absolutes like absolutely horrible and nope, so all hypotheticals aside, I'll just concede that this is an uninteresting way to spend our time.
Re: Junctions of classes, roles, etc.
On Sun, May 01, 2005 at 10:59:59AM -0400, Aaron Sherman wrote: On Sat, 2005-04-30 at 16:55 -0700, Brent 'Dax' Royal-Gordon wrote: Aaron Sherman [EMAIL PROTECTED] wrote: On Sat, 2005-04-30 at 22:24 +0800, Autrijus Tang wrote: That would be absolutely horrible. You all seem to have some very strong opinions, and I'm unable to have a discussion around absolutes like absolutely horrible and nope, so all hypotheticals aside, I'll just concede that this is an uninteresting way to spend our time. Sorry. I'll watch my language better in the future, and provide better rationales to support my opinion. :-/ In this case, the reason I called this absolutely horrible: my Str|Int $x; $x.method(); # calls .method twice Is because to me, it is conceptually no difference to: sub foo (Str|Int $x) { $x.method() }; In both cases, the junctive type is used to construct a new type that is a supertype of both Str and Int, for type checking purposes. If it silently promotes the variable itself to a Junction for autothreading, that will render such type construction unusable, as it will be doing two highly orthogonal things with a single syntax. Again, my apologies for using strong words without adequate justification. Thanks, /Autrijus/ pgpvkCR2varmo.pgp Description: PGP signature
Re: Junctions of classes, roles, etc.
On Sat, Apr 30, 2005 at 09:13:26AM -0500, Abhijit Mahabal wrote: On Fri, 29 Apr 2005, Brent 'Dax' Royal-Gordon wrote: David Storrs [EMAIL PROTECTED] wrote: Could we see some code that shows why this is a good idea? My initial reaction is horror; I can very easily see huge numbers of subtle, hard-to-reproduce bugs coming out of this. I'm quite willing to believe that there are [good results], but I'm not coming up with them. What do you think this is? sub foo(Str | Int $bar) { ... } I believe you mean sub foo(Str^Int $bar){...} ( something that is Int or Str but not both). But that, too, just reduces the amount of code and is merely a shortcut for: multi sub(Str $bar){...} multi sub(Int $bar){...} I do not see how any auto-threading occurs in that code. It is completely innocuous in that sense, and I don't think that is what horrified David. Indeed, you're right on the money, Abhijit. Thanks for stating it so well. Let's move this away from simple types like Str and Int for a moment. Tell me what this does: class Tree { method bark() { die Cannot instantiate a Tree--it is abstract! } } class Birch { method bark() { return White, papery } } class Oak { method bark() { return Dark, heavy } } class Dog { method bark() { print Woof, woof!; return bow wow } } class AlienBeastie isa Tree isa Dog {} class WhiteAlienBeastie isa Birch isa Dog {} class HeavyAlienBeastie isa Oak isa Dog {} sub Foo(Tree|Dog $x) { $x.bark() } Ignore for the moment that this is stupid code--it's semantically and (AFAIK) syntactically valid. So, what happens when I do each of these: Foo( new AlienBeastie() ); Foo( new WhiteAlienBeastie() ); Foo( new HeavyAlienBeastie() ); ?? --Dks
Re: Junctions of classes, roles, etc.
On Fri, 29 Apr 2005, Brent 'Dax' Royal-Gordon wrote: David Storrs [EMAIL PROTECTED] wrote: On Thu, Apr 28, 2005 at 03:28:41PM +0200, Ingo Blechschmidt wrote: so we had junctions of Code references some days ago, what's with junctions of Class and Role objects? :) Could we see some code that shows why this is a good idea? My initial reaction is horror; I can very easily see huge numbers of subtle, hard-to-reproduce bugs coming out of this. On the other hand, I do not immediately see major applications...most of what I can see is things that reduce the amount of code needed, but don't actually accomplish anything fundamentally new. What do junctions of Class|Role objects give us that can't be achieved in other ways? I'm quite willing to believe that there are such things, but I'm not coming up with them. What do you think this is? sub foo(Str | Int $bar) { ... } I believe you mean sub foo(Str^Int $bar){...} ( something that is Int or Str but not both). But that, too, just reduces the amount of code and is merely a shortcut for: multi sub(Str $bar){...} multi sub(Int $bar){...} I do not see how any auto-threading occurs in that code. It is completely innocuous in that sense, and I don't think that is what horrified David. What was troublesome was, I think: my Str|Int $x; $x.foo(); # runs two methods and returns a junction I would like to be able to read the above code to mean: type X ::= Scalar where Str|Int; my X $x; # $x = non int/non string now a runtime error $x.foo(); # no different from if you had just said my $x Feel free to tell me I am barking up the wrong tree if that is what I am doing. --abhijit
Re: Junctions of classes, roles, etc.
On Sat, 2005-04-30 at 22:24 +0800, Autrijus Tang wrote: On Sat, Apr 30, 2005 at 09:13:26AM -0500, Abhijit Mahabal wrote: I do not see how any auto-threading occurs in that code. It is completely innocuous in that sense, and I don't think that is what horrified David. What was troublesome was, I think: my Str|Int $x; $x.foo(); # runs two methods and returns a junction That would be absolutely horrible. Then tell me what $!.can(chars) returns, assuming that $! is implemented as an any junction of Int and Str values? My take would be that it returns false|true, which is true in a boolean context, but feel free to talk me out of it. Str|Int is simply the type of Yes|1, isn't it? That would certainly make signature matching on different kinds of junctive types trivial. I would like to be able to read the above code to mean: type X ::= Scalar where Str|Int; my X $x; # $x = non int/non string now a runtime error $x.foo(); # no different from if you had just said my $x This is my current understanding in the implementation. That's not a junction, and thus should not use junction syntax. I'm not opposed to having such a construct, but re-using junction syntax is going to cause massive headaches for anyone trying to learn the language. Also, what is: $x = ::(Int) | ::(Str) my ::($x) $y; at which stages of the execution of that code? Are you saying that $x does not contain a junction, or that a junction used as a type does not create a junction value? If the latter, then what is the type of Yes|1?
Re: Junctions of classes, roles, etc.
On Sat, 30 Apr 2005, Aaron Sherman wrote: On Sat, 2005-04-30 at 22:24 +0800, Autrijus Tang wrote: On Sat, Apr 30, 2005 at 09:13:26AM -0500, Abhijit Mahabal wrote: I do not see how any auto-threading occurs in that code. It is completely innocuous in that sense, and I don't think that is what horrified David. What was troublesome was, I think: my Str|Int $x; $x.foo(); # runs two methods and returns a junction That would be absolutely horrible. Then tell me what $!.can(chars) returns, assuming that $! is implemented as an any junction of Int and Str values? If $! were explicitely Yes|1, then I agree that it returns false|true. I believe that in the code you wrote.. $x = ::(Int) | ::(Str) my ::($x) $y; $x is a junction, and $y is not a junction. type, to me, is just a sticky note attched to an object. I would not like to see autothreading on every junctive sticky. In the code above, if there were a method called .type(), then $y.type() would indeed return a junction, but not by running two methods and orring their output. Str|Int is simply the type of Yes|1, isn't it? Hmmm... I am not sure. Maybe the type is just Junc or something. Str|Int is also the type of 7 and of yes. Moreover, if the return type of a method is junctive, would you want that menthod to autothread too? --abhijit Abhijit Mahabal http://www.cs.indiana.edu/~amahabal/
Re: Junctions of classes, roles, etc.
Aaron Sherman [EMAIL PROTECTED] wrote: On Sat, 2005-04-30 at 22:24 +0800, Autrijus Tang wrote: On Sat, Apr 30, 2005 at 09:13:26AM -0500, Abhijit Mahabal wrote: I do not see how any auto-threading occurs in that code. It is completely innocuous in that sense, and I don't think that is what horrified David. What was troublesome was, I think: my Str|Int $x; $x.foo(); # runs two methods and returns a junction That would be absolutely horrible. Then tell me what $!.can(chars) returns, assuming that $! is implemented as an any junction of Int and Str values? My take would be that it returns false|true, which is true in a boolean context, but feel free to talk me out of it. `$!` is an `Exception` (or somesuch) object, not a `Str|Int`, but in general, that depends on the contents of the variable. If a Str|Int was assigned a `Str`, `can` would be true; if it were assigned an `Int`, `can` would be false. If it were assigned a disjunction of a `Str` and an `Int`, it'd return `true|false`, which evaluates to `true`. Str|Int is simply the type of Yes|1, isn't it? That would certainly make signature matching on different kinds of junctive types trivial. Nope. The type `Str|Int` doesn't mean this variable contains a disjunction of `Str`s and `Int`s; it means This variable can contain either a `Str` or an `Int`. (Actually, it means this variable can contain anything consistent with a Str or Int, which also includes subclasses and certain junctions.) When you see a declaration like: my Foo $bar; Think of it as being like: my $bar where { $_ ~~ Foo }; If the latter, then what is the type of Yes|1? I suspect it's `Disjunction of Str | Int`. -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junctions of classes, roles, etc.
On Thu, Apr 28, 2005 at 03:28:41PM +0200, Ingo Blechschmidt wrote: so we had junctions of Code references some days ago, what's with junctions of Class and Role objects? :) Could we see some code that shows why this is a good idea? My initial reaction is horror; I can very easily see huge numbers of subtle, hard-to-reproduce bugs coming out of this. On the other hand, I do not immediately see major applications...most of what I can see is things that reduce the amount of code needed, but don't actually accomplish anything fundamentally new. What do junctions of Class|Role objects give us that can't be achieved in other ways? I'm quite willing to believe that there are such things, but I'm not coming up with them. --Dks
Re: Junctions of classes, roles, etc.
David Storrs [EMAIL PROTECTED] wrote: On Thu, Apr 28, 2005 at 03:28:41PM +0200, Ingo Blechschmidt wrote: so we had junctions of Code references some days ago, what's with junctions of Class and Role objects? :) Could we see some code that shows why this is a good idea? My initial reaction is horror; I can very easily see huge numbers of subtle, hard-to-reproduce bugs coming out of this. On the other hand, I do not immediately see major applications...most of what I can see is things that reduce the amount of code needed, but don't actually accomplish anything fundamentally new. What do junctions of Class|Role objects give us that can't be achieved in other ways? I'm quite willing to believe that there are such things, but I'm not coming up with them. What do you think this is? sub foo(Str | Int $bar) { ... } Or this one, which is even more important? sub foo(Any | Junction $bar) { ... } -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junctions of classes, roles, etc.
Ingo Blechschmidt wrote: Hi, so we had junctions of Code references some days ago, what's with junctions of Class and Role objects? :) I like them! In the type lattice A|B is the lub (lowest upper bound) of A and B. And AB is the glb (greatest lower bound) of A and B. Both are cases of multiple inheritance with possible conflicts. But A|B is more general than each of A and B, while AB is more specific than both. role A { method foo() { 42 } } role B { method foo() { 23 } } class Test does A|B {} Here you have to implement Test::foo. Not doing so is a compile time error---or more precisly a class composition time error. my Test $test .= new; my $ret = $test.foo; # 42|23? Whatever Test::foo returns. role A {} role B { method foo() { 42 } } class Test does A|B {} Here is no conflict, but it might be necessary to implement the more general behaviour. my Test $test .= new; my $ret = $test.foo; # unthrown-exception undef|42? No, $ret == 42 unless Test::foo() is implemented and returns something else. Regards, -- TSa (Thomas Sandlaß)
Re: Junctions of classes, roles, etc.
On Thu, 2005-04-28 at 09:51, Thomas Sandlaß wrote: Ingo Blechschmidt wrote: Hi, so we had junctions of Code references some days ago, what's with junctions of Class and Role objects? :) I like them! In the type lattice A|B is the lub (lowest upper bound) of A and B. And AB is the glb (greatest lower bound) of A and B. That's not at all intuitively obvious because what you're describing is not a junction. At least it doesn't seem like one to me (you're describing a situation where the new class has a specific kind of inheritance, not the situation where it's first ancestor is either all or one of a set). The difference being that in the case of: class x is yz {} my x $a; $a.foo(); The method foo will be invoked from both y and z simultaneously, without conflict, and return a junction of the two results. role A { method foo() { 42 } } role B { method foo() { 23 } } class Test does A|B {} Here you have to implement Test::foo. Not doing so is a compile time error---or more precisly a class composition time error. Let's be clear about why you think that. Roles are not ordered, and thus you must disambiguate the use of more than one. S12 says: There are several ways to solve method conflicts. The first is simply to write a class method that overrides the conflicting role methods, perhaps figuring out which role method to call. Alternately, if the role's methods are declared multi, they can be disambiguated based on their long name. If the roles forget to declare them as multi, you can force a multi on the roles' methods by installing a multi stub in the class being constructed: multi method shake {...} However, this is a junction, so: class Test does A|B is really saying that you compose two different classes called Test, which you refer to singly through the magic of junctions. One Test is composed of the base Test class plus A, and another is composed of the base Test class plus B (well A plus Test and B plus Test if you think of it in terms of which overrides which). Now, I'm not saying that that's the way it MUST be, just that that seems to be the way that junctions would work in that situation. If we decide that | and aren't really junction constructors in class/role definitions, then we can make them whatever we want. -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: Junctions of classes, roles, etc.
Aaron Sherman wrote: Now, I'm not saying that that's the way it MUST be, just that that seems to be the way that junctions would work in that situation. I know, and I'm very confused about all these pseudo procedural uses of junctions. And others seem to share my state of affairs. If we decide that | and aren't really junction constructors in class/role definitions, then we can make them whatever we want. Ohh, yes please! Actually I see the biggest potential of junctions in the type system. E.g. the comparison operator = could get return type -1^0^1. This is first of all good documentation and secondly preserves valuable information for the optimizer. The none() junction is most usefull for excluding types---e.g junctions. So, in the extreme Perl6 might have a junctive type calculation overlaying the value calculation. Thus when a junctive class is needed the class composer can be triggered to make an instance thereof. As you pointed out that might be possible and then continue to MMD with that newly created class. Sounds very dynamic too me. And I've not heard about a language that throws exceptions that say Can't create class Foo does A|B because of conflicting methods bar(). Regards, -- TSa (Thomas Sandlaß)