-
Notifications
You must be signed in to change notification settings - Fork 577
experimental 'class' doesn't work with existing objects #21331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Yeah; the wording of the message isn't very clear but it's hard to explain without ending up writing most of a paragraph of text in the message. perldiag has more:
100% agree. This and about a hundred other as-yet-missing but definitely planned features are part of the reason it remains experimental, and is likely to for some time yet. |
Here's the syntax class
|
Things like this are exactly why we're proceeding cautiously. Consider the following: #!/usr/bin/env perl
use v5.38.0;
use experimental qw(class);
class Person {
field $name :param = 'John Doe';
method name () {
return $name;
}
sub name2 ($self) {
return $name;
}
} That won't compile. It fails with: That's because subroutines aren't methods and can't have access to internals. Later, it's likely that even if we can write code which compiles, we should at least get a runtime error if we try to call subroutines as methods because they're fundamentally different things. This is one of the reasons why boilerplate such as Do you have the code for the |
Also, the Moose stuff does a lot of heavy lifting with the MOP and appears to make assumptions about Moose being used. We can't just automatically inherit from non-Corinna classes right now because it's not clear that it would even work. A subclass should work with any code that accepts a parent class (Liskov) and it's not clear that's the case. Thus, following our "Principle of Parsimony", we're deliberately being restrictive at first to make sure we can shake out all the bugs. Later, we can revisit opening things up. If we start with the latter and it turns out to be problematic, we might not be able to walk back that decision because working code might rely on it. |
The more I think about this, the more I realize a longer answer is warranted. Post-MVP this decision might be revisited, but for the MVP, we needed to class My::Class :isa(Other::Class) {
field $name :param;
sub get_name ($self) {
return $name;
}
} The above is a syntax error because subroutines cannot access instance data. class My::Class {
sub sum ($self,@nums) {
my $total = 0;
$total += $_ for @nums;
}
} That looks fine, right? Well, not really. Even though it's not accessing class My::Class {
use List::Util qw(sum);
} That's similar, but it doesn't take an invocant ( class My::Class :does(Some::Role) {
...
} If And that brings us back to our core problem: class My::Class :isa(Other::Class) {
field $name :param;
sub get_name ($self) {
return $name;
}
} If This isn't to say that we will never allow this, but for now, it was agreed class My::Class {
use Other::Class;
field $name :param;
field $other_class = Other::Class->new( name => $name );
method some_method ($arg) {
return $other_class->some_method($arg);
}
} In the future, we might even be able to shorten that to this: class My::Class {
use Other::Class;
field $name :param;
field $other_class :handles(some_method) = Other::Class->new( name => $name );
} But that means we don't get signature safety since signatures are not Mixing Corinna and Fortunately, |
@Ovid I favor composition over inheritance but for the use case I've linked in the GitHub repo that means there's not one single place I can use the new system. In Catalyst a control must inherit from Catalyst::Controller. I can't use core class for controller, for models, for view. I can't use it in DBIC for result or resultset classes either. It appears you can only use it for Greenfield code which is far from abundant in Perl. |
@jjn1056 I'm sorry you feel that way. Trying to retrofit old code onto the new If you wanted to write some brand-new code to shake out bugs, that's great. Stevan Little has been doing so with Stella, building an actor model with Chris "peregrin" Prather has been doing the same thing by building a clone of Rogue with the new syntax. He also appears to be happy with the new syntax. |
Oh, there's also the problem that Corinna is single-inheritance and We also recognize that I don't think there was anyone on the design team who was happy that the new object system can't inherit from the old, but the MVP is hard and trying to retrofit it onto the I get that it's frustrating that you can't use this with existing |
Need I remind folks that Object::Pad exists? ;) Object::Pad can subclass an existing bless-based class just fine. It's an excellent testing ground to try out whether you like the new syntax. It also makes a good migration path. Migrate a few bits of code at a time using it, until eventually all your codebase is using All it requires is not being afraid of CPAN modules. |
Slightly related question, as I tried to see if I could "translate" an existing Moo* class on the fly to perl class syntax. The following all fail, should or shouldn't we support dynamic class names?
|
@nicomen It's failing, in part, because you didn't interpolate the class names. Also, once a class is declared, you can't redeclare it with the same name. I think this is closer to what you want: use v5.38;
use feature 'class';
no warnings 'experimental::class';
my $class = 'Class';
my @tests = (
"class C1$class {}",
"class C2My${class} {}",
"class C3$class 1.0 {}",
"class C4My${class} 1.0 {}",
);
do { say "$_:\n"; eval "$_; 1" or warn $@; }
for @tests; |
@Ovid I intentionally do not want to interpolate until the actual perl code is eval()-ed. I just wanted to bulk the examples together. (And the different examples should perhaps have a bit different error messages.) This example is perhaps clearer:
This tells me that we are not allowed to set class names based on variables, my initial question is wether this should be possible or not. |
That's more of a question for @leonerd then. Not sure the fine-grained details of parsing there. Class names from variables will certainly be possible with the MOP, but that's not built yet. |
One problem with this is the assignment is done at runtime, but the class is parsed and sealed at compile time. |
@tonycoz That's a good point. It will mean that dynamically creating new classes will need to be done through the MOP. When we get to anonymous classes, that will impact us, too. |
This is exactly the same as
|
Crossposted from Perl-Apollo/Corinna#105 because its completely unclear how to start a conversation about where core class is going
So I tried to use core class with a basic Catalyst controller:
But when I try to run I get a compile time error:
I'm enabling the class pragma via the 'Example::Syntax' module , it basically does 'use experimental class'.
I would propose that code like this working should be considered mandatory before moving this out of experimental status.
The text was updated successfully, but these errors were encountered: