Raku rebless doesn't work with inherited classes anymore

The code given in this thread doesn't work anymore: How can I rebless an object in Perl 6?

I wrote this piece of code last year, and it worked then. Now it doesn't:

class Person { ; }
class Woman is Person { ; }
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

Metamodel::Primitives.rebless($tom, Woman);
# -> New type Woman for Person is not a mixin type

The error message doesn't make sense, as it is supposed to work with inherited classes. At least it was.

The documentation is not helpful; https://docs.raku.org/routine/rebless

it is supposed to work with inherited classes

It never was supposed to be that general. I designed that API and implemented it in the first place, and it was only ever intended as an implementation detail of mixins.

Until very recently, it was not part of the language specification test suite - and when it did become part of it, it already had its current, more restrictive, semantics. The constraints on it are important for performance reasons: when we know a type is not one that can be the target of a mixin operation, we can JIT-compile attribute accesses on that object into something much simpler (we paid an extra conditional move on every attribute access before the change, and now only have to pay it on mixin target types).

It's possible to modify the original program to work by using the MOP to construct the class. In fact, the following isn't quite the original program; I did a small tweak for the sake of showing how one can provide methods in the subclass as an anonymous role, so as to avoid too much MOP boilerplate.

class Person { method m() { "person" } }
constant Woman = do {
    my \w = Metamodel::ClassHOW.new_type(:is_mixin, :name<Woman>);
    w.^add_parent(Person);
    w.^add_role(role { method m() { "woman" } });
    w.^compose()
}
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m; # person
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m; # woman

While that's the most semantically direct fix to the original program, there is a shorter way: use the but operator on the Person type object to produce a mixin type and return it, and then just tweak its name to your liking:

class Person { method m() { "person" } }
constant Woman = Person but role { method m() { "woman" } }
BEGIN Woman.^set_name('Woman');

my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m;
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m;

Which is only one line extra than the original anyway.

method rebless, method rebless(Mu $object, Mu $type). Changes $object to be of type $type . This only works if $type type-checks against the current type of $object , and if the � Raku and the (Re)blessed Child [56] Published 12. February 2020. Why doesn't «rebless» work in Raku anymore? See also Part 2: Exploring Rebless with Raku for sample code. Back in 2018 I started working on a Raku (or Perl 6 as the language was called then) course and accompanying textbook.

Exploring Rebless with Raku, The official documentation has this entry for �rebless�: type that allows positive integers (including 0) only), but that doesn't make sense her. «subset» is a Raku keyword used to set up custom types (as in e.g. «subset Positive of Int where * > -1;» which defines a type that allows positive integers (including 0) only), but that doesn't make sense her. So surely it means inheritance and a subclass.

Follow-up question: See Raku rebless and multiple classes

Raku rebless doesn't work with inherited classes anymore, The code given in this thread doesn't work anymore: How can I rebless an object in Perl 6?I wrote this piece of code last year, and it worked then. Now it� So, given the consensus on what belongs in docs.raku.org and what doesn't (see above), the most helpful thing its rebless page could do was to either not document rebless at all or, perhaps better, include a page for it but make sure it did not describe its behavior. Which is what the situation was: the page did exist; was not directly helpful; and that was arguably better than nothing.

Raku rebless and multiple classes, This is a follow up to: Raku rebless doesn't work with inherited classes anymore)I have tried to come up with a more complex use case, but am unable to get the� [56] Why doesn't «rebless» work in Raku anymore? 12. February 2020 - Arne Sommer. The Cryptic Raku Room [55] My response to the Perl Weekly Challenge #46. 7

Raku rebless doesn't work with inherited classes anymore, 问题The code given in this thread doesn't work anymore: How can I rebless an object in Perl 6? I wrote this piece of code last year, and it worked then. Now it� Western-Style Raku Firing and Oxidation Reduction . The ancient Eastern styles of Raku were developed with new methods by American ceramicist Paul Soldner in the 1960s. The methods he created were known as ‘low-temperature salt firing,’ and he was known to teach his students 'not to fight the unexpected but to look for the opportunities it offers.’

Exploring Rebless with Raku, Raku Perl 6 programming. method rebless(Mu $object, Mu $type) positive integers (including 0) only), but that doesn't make sense her. raku rebless-error Person Woman New type Woman for Person is not a mixin type It doesn’t have to be a glaze specifically designed for raku, formulated to fire at the temperature you fire your raku to, nor homemade or commercial. It can be most anything. The key to success is understanding the raku firing process and the ability to predict how a particular glaze reacts to that process.

Comments
  • Might be a regression bug. Probably best to report it as a Rakudo issue.
  • There were some changes last February: github.com/perl6/nqp/blob/…
  • Also, I have updated the documentation with a footnote pointing to @jnthn answer docs.raku.org/type/Metamodel::Primitives. Thanks, raiph
  • constant Woman = Person but role … Did not realize that that could be done. And thus but for the BEGIN line, Raku just about pulls off being able to do a JS-style prototypal paradigm too!
  • Ok. Thank you for the explanation. I do hope that it will find its way into the documentation, as docs.raku.org/routine/rebless is pretty useless... I will update «Beginning Raku» shortly.
  • @user0721090601 Raku supports, quoting S12: "both class-based and prototype-based OO programming". However, if you construct objects using the class keyword, then, quoting S12 again: "by default, objects derived from Mu support a fairly standard class-based model ... bless ... calls ... BUILD routines ... default BUILD semantics are inherited from Mu". In summary, I'd argue it's more accurate to say that Raku supports A) "seriously warping even the bog standard class-based OO with just a couple lines of code" and B) "prototype-based OO."
  • See raku-musings.com/reblessed.html for my view on breaking changes.
  • I found this article when I tried to figure out how "rebless" works, as the documentation was useless: stackoverflow.com/questions/44486985/… And it worked, then. And then it suddenly didn't work anymore, and the documentation was still useless. It still is, as it should document the call, and not refer to something else. And the reference to changes in 2019.11 is 7 months off by my count.
  • I can help with the documentation part, if that helps.
  • @ArneSommer Please see the new sections in my answer starting with Helping with the docs.
  • I have a solution (but it won't fit in a comment). Please post the above as a new SO. Thanks.
  • See stackoverflow.com/questions/60051089/…