Skip Menu |
Report information
Id: 116783
Status: open
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: masak <cmasak [at] gmail.com>
Cc:
AdminCc:

Severity: (no value)
Tag: Bug
Platform: (no value)
Patch Status: (no value)
VM: (no value)



Subject: [BUG] 'my' class in role should be generic in Rakudo
Date: Sat, 16 Feb 2013 18:13:45 +0100
To: rakudobug [...] perl.org
From: Carl Mäsak <cmasak [...] gmail.com>
<TimToady> r: https://gist.github.com/TimToady/4963642 <TimToady> jnthn: that gets me an error Nominal type check failed for parameter '$payload'; expected T but got Int instead <TimToady> but T is supposed to instantiate to Int <jnthn> Sure is. <jnthn> Any idea exactly which T it is? <TimToady> the sig in post-insert <jnthn> oh. <jnthn> role DLL[::T] { <jnthn> my class DLLE does DLL_Element[T] {} <jnthn> You nested a class in a role. <TimToady> I don't know how to do that otherwise <jnthn> Roles aren't as macro-ish as you expected them... <jnthn> It doesn't make a fresh class per role instance. <TimToady> well, I guess I can instantiate in parallel, but it'd be nice if one could drive the other <jnthn> And the one declaration sees the uninstantiated type variable, 'cus it comes into existence before the role is ever composed. <TimToady> okay...have to think about it s'more <jnthn> Does the spec make a call on what happens to packages declared inside roles? iirc, it doesn't call either way <jnthn> I've always had it down as a grey area. :) <TimToady> here be grey dragons... <jnthn> I suspect we *could* find a way to make it work but by then we're pushing roles further into macro territory <japhb_> .oO( TimToady: "Do I want this enough to change the spec so jnthn has to make it so ...?" :-) ) <TimToady> I just think it's kind of typical to want to instantiate a forest of classes together <jnthn> TimToady: While you're on it, you may also wish to ponder this issue: <jnthn> r: role Foo { our sub foo() { say 42 } }; Foo::foo() 22:31 <+p6eval> rakudo 1e85ff: OUTPUT«Could not find symbol '&foo' [...] <jnthn> That at first blush looks like it should work, but it doesn't at the moment. <jnthn> The reason it doesn't is... <jnthn> role Foo { }; role Foo[::T] { } <jnthn> Roles are multiple dispatch <jnthn> What's actually installed in Foo is not actually the role. It's basically a thingy that does a multi dispatch to pick a role. <jnthn> Which gets a type object of its own. <jnthn> ParametricRoleGroupHOW or so. <TimToady> the downside to all this punning... <moritz> .oO( punning for the fjords...) <jnthn> Yeah. Well, I've mentioned before just how many different forms roles come in :) <jnthn> Which I don't see as a problem per se. <jnthn> But the only sane way I found to implement all the things is to untangle the puns. <jnthn> tbh, I think putting our scoped stuff inside something generic is crazy anyway... * TimToady imagines Foo as a search path of packages, and shudders <TimToady> which is why I declared my inner class with 'my' :) <jnthn> That is, I can imagine that if you try to install something our-scoped inside a role, we say "no, this won't end well" :) <jnthn> Yeah. I can see what you wanted it to do. :) <jnthn> I'm just asking if we really want the complexity of doing it :) <TimToady> dunno; do Java generics have a story on this sort of thing? <jnthn> It *is* the same machinary masak++ will want for declarations in macros, so in a sense we're gonna have to solve the problem anyway. <TimToady> .oO(and you thought *monads* were hard to lift...) <jnthn> Java generics are mostly an example of what not to do. :) <jnthn> C# ones, otoh, are done properly. <TimToady> so what do they do in this case? <jnthn> In C#, if you write an inner class inside a generic class, it also becomes generic. <jnthn> Hm, darn, I just said that's the proper thing to do, didn't I... :) * TimToady is not going to torment the implementors (much) more than they torment themselves <jnthn> From the spec: <jnthn> Any class nested inside a generic class declaration or a generic struct declaration (§25.2) is itself a generic class declaration, since type parameters for the containing type shall be supplied to create a constructed type. <jnthn> We maybe don't want quite that factoring, since our type parameters are just lexical. <jnthn> We just want to hang on to the class in a generic form and then reify it. <TimToady> but an inner class that is dependent on T, like mine... <jnthn> Well, I guess we'd treat any class inside a role as generic in some sense. <jnthn> I suspect making it do what you expected is (a) possible, (b) least surprising, and (c) hard. :) <jnthn> Which basically makes it a great candidate for a Perl 6 feature. ;-) <TimToady> vicarious suffering, and all that... <TimToady> well, just because it's Friday doesn't mean you have to do it today :) <jnthn> :) <jnthn> Anyway, no objections if you want to spec it that way. * TimToady is not sure he understands it well enough yet to talk about it <masak> TimToady, jnthn: could either of you golf an example of expected/actual behavior of a class nested in a generic role? then I can rakudobug it. <TimToady> masak: here: https://gist.github.com/TimToady/4967666 <masak> r: role Foo[::T] { has T $.p = T }; role Bar[::T] { my class Fooey does Foo[T] {}; submethod BUILD { Fooey.new } }; class RatBar does Bar[Rat] {}; RatBar.new <p6eval> rakudo 1e85ff: OUTPUT«Cannot type check against type variable T [...] * masak submits rakudobug <TimToady> and yes, RatBar is an allusion to the Vorkosigan universe :)
Output on all releases: https://gist.github.com/Whateverable/297882f4f84bb8362a0ce0523439c436

On 2013-02-16 09:14:04, masak wrote:
Show quoted text
> <TimToady> r: https://gist.github.com/TimToady/4963642
> <TimToady> jnthn: that gets me an error Nominal type check failed for
> parameter '$payload'; expected T but got Int instead
> <TimToady> but T is supposed to instantiate to Int
> <jnthn> Sure is.
> <jnthn> Any idea exactly which T it is?
> <TimToady> the sig in post-insert
> <jnthn> oh.
> <jnthn> role DLL[::T] {
> <jnthn> my class DLLE does DLL_Element[T] {}
> <jnthn> You nested a class in a role.
> <TimToady> I don't know how to do that otherwise
> <jnthn> Roles aren't as macro-ish as you expected them...
> <jnthn> It doesn't make a fresh class per role instance.
> <TimToady> well, I guess I can instantiate in parallel, but it'd be
> nice if one could drive the other
> <jnthn> And the one declaration sees the uninstantiated type variable,
> 'cus it comes into existence before the role is ever composed.
> <TimToady> okay...have to think about it s'more
> <jnthn> Does the spec make a call on what happens to packages declared
> inside roles? iirc, it doesn't call either way
> <jnthn> I've always had it down as a grey area. :)
> <TimToady> here be grey dragons...
> <jnthn> I suspect we *could* find a way to make it work but by then
> we're pushing roles further into macro territory
> <japhb_> .oO( TimToady: "Do I want this enough to change the spec so
> jnthn has to make it so ...?" :-) )
> <TimToady> I just think it's kind of typical to want to instantiate a
> forest of classes together
> <jnthn> TimToady: While you're on it, you may also wish to ponder this
> issue:
> <jnthn> r: role Foo { our sub foo() { say 42 } }; Foo::foo()
> 22:31 <+p6eval> rakudo 1e85ff: OUTPUT«Could not find symbol '&foo'
> [...]
> <jnthn> That at first blush looks like it should work, but it doesn't
> at the moment.
> <jnthn> The reason it doesn't is...
> <jnthn> role Foo { }; role Foo[::T] { }
> <jnthn> Roles are multiple dispatch
> <jnthn> What's actually installed in Foo is not actually the role.
> It's basically a thingy that does a multi dispatch to pick a role.
> <jnthn> Which gets a type object of its own.
> <jnthn> ParametricRoleGroupHOW or so.
> <TimToady> the downside to all this punning...
> <moritz> .oO( punning for the fjords...)
> <jnthn> Yeah. Well, I've mentioned before just how many different
> forms roles come in :)
> <jnthn> Which I don't see as a problem per se.
> <jnthn> But the only sane way I found to implement all the things is
> to untangle the puns.
> <jnthn> tbh, I think putting our scoped stuff inside something generic
> is crazy anyway...
> * TimToady imagines Foo as a search path of packages, and shudders
> <TimToady> which is why I declared my inner class with 'my' :)
> <jnthn> That is, I can imagine that if you try to install something
> our-scoped inside a role, we say "no, this won't end well" :)
> <jnthn> Yeah. I can see what you wanted it to do. :)
> <jnthn> I'm just asking if we really want the complexity of doing it
> :)
> <TimToady> dunno; do Java generics have a story on this sort of thing?
> <jnthn> It *is* the same machinary masak++ will want for declarations
> in macros, so in a sense we're gonna have to solve the problem anyway.
> <TimToady> .oO(and you thought *monads* were hard to lift...)
> <jnthn> Java generics are mostly an example of what not to do. :)
> <jnthn> C# ones, otoh, are done properly.
> <TimToady> so what do they do in this case?
> <jnthn> In C#, if you write an inner class inside a generic class, it
> also becomes generic.
> <jnthn> Hm, darn, I just said that's the proper thing to do, didn't
> I... :)
> * TimToady is not going to torment the implementors (much) more than
> they torment themselves
> <jnthn> From the spec:
> <jnthn> Any class nested inside a generic class declaration or a
> generic struct declaration (§25.2) is itself a generic class
> declaration, since type parameters for the containing type shall be
> supplied to create a constructed type.
> <jnthn> We maybe don't want quite that factoring, since our type
> parameters are just lexical.
> <jnthn> We just want to hang on to the class in a generic form and
> then reify it.
> <TimToady> but an inner class that is dependent on T, like mine...
> <jnthn> Well, I guess we'd treat any class inside a role as generic in
> some sense.
> <jnthn> I suspect making it do what you expected is (a) possible, (b)
> least surprising, and (c) hard. :)
> <jnthn> Which basically makes it a great candidate for a Perl 6
> feature. ;-)
> <TimToady> vicarious suffering, and all that...
> <TimToady> well, just because it's Friday doesn't mean you have to do
> it today :)
> <jnthn> :)
> <jnthn> Anyway, no objections if you want to spec it that way.
> * TimToady is not sure he understands it well enough yet to talk about
> it
> <masak> TimToady, jnthn: could either of you golf an example of
> expected/actual behavior of a class nested in a generic role? then I
> can rakudobug it.
> <TimToady> masak: here: https://gist.github.com/TimToady/4967666
> <masak> r: role Foo[::T] { has T $.p = T }; role Bar[::T] { my class
> Fooey does Foo[T] {}; submethod BUILD { Fooey.new } }; class RatBar
> does Bar[Rat] {}; RatBar.new
> <p6eval> rakudo 1e85ff: OUTPUT«Cannot type check against type variable
> T [...]
> * masak submits rakudobug
> <TimToady> and yes, RatBar is an allusion to the Vorkosigan universe
> :)




This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org