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

Owner: Nobody
Requestors: john [at] johnkingsley.ca
Cc:
AdminCc:

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



Subject: [BUG] When overriding .gist, it's all or nothing
From: John Kingsley <john [...] johnkingsley.ca>
To: rakudobug [...] perl.org
Date: Mon, 20 Oct 2014 12:00:07 -0400
Download (untitled) / with headers
text/plain 1.7k
Hi, When I define a gist() method, it doesn't get called when I expected it to be called. This occurs when you call gist() not on the object directly, but instead on another object which uses the class where the gist() is defined. So if you are defining a gist() method on your class, you pretty much need to do it on every class in your program for it to be useful. I would argue it would be better to allow programmers to define gist on an incremental fashion. The problem is here in the core: multi method gist(Mu:D:) { self.perl } If a gist method isn't defined on a class, then it uses .perl for every attribute, even when attributes may have a .gist method. Test below, with output. cheers, John $ perl6 -v This is perl6 version 2014.09 built on MoarVM version 2014.09 Test: ================================ #!/usr/bin/env perl6 class Coord { has Int $.x; has Int $.y; multi method gist(Coord:D:) { "L($.x,$.y)"; } } class Route1 { has Coord @.loc; } class Route2 { has Coord @.loc; multi method gist(Route2:D:) { "Route2(" ~ @.loc.map({.gist}).join(", ") ~ ")"; } } my $r1 = Route1.new(loc => [Coord.new(x => 0, y => 0), Coord.new(x => 0, y => 1)]); note "Got: " ~ $r1.gist; note "Exp: " ~ "Route1.new(loc => Array[Coord].new(L(0,0), L(0,1)))"; my $r2 = Route2.new(loc => [Coord.new(x => 0, y => 0), Coord.new(x => 0, y => 1)]); note "Got: " ~ $r2.gist; note "Exp: " ~ "Route2(L(0,0), L(0,1))"; ================================ Output: ================================ Got: Route1.new(loc => Array[Coord].new(Coord.new(x => 0, y => 0), Coord.new(x => 0, y => 1))) Exp: Route1.new(loc => Array[Coord].new(L(0,0), L(0,1))) Got: Route2(L(0,0), L(0,1)) Exp: Route2(L(0,0), L(0,1)) ================================
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 3.2k
On Mon, 20 Oct 2014 09:00:24 -0700, john@johnkingsley.ca wrote: Show quoted text
> Hi, > > When I define a gist() method, it doesn't get called when I expected > it to be called. > > This occurs when you call gist() not on the object directly, but > instead > on another object which uses the class where the gist() is defined. > > So if you are defining a gist() method on your class, you pretty much > need to do it on every class in your program for it to be useful. > I would argue it would be better to allow programmers to define gist > on an incremental fashion. > > The problem is here in the core: > multi method gist(Mu:D:) { self.perl } > If a gist method isn't defined on a class, then it uses .perl for > every attribute, > even when attributes may have a .gist method. > > Test below, with output. > > cheers, John > > $ perl6 -v > This is perl6 version 2014.09 built on MoarVM version 2014.09 > > Test: > ================================ > #!/usr/bin/env perl6 > > class Coord { > has Int $.x; > has Int $.y; > multi method gist(Coord:D:) { > "L($.x,$.y)"; > } > } > > class Route1 { > has Coord @.loc; > } > > class Route2 { > has Coord @.loc; > multi method gist(Route2:D:) { > "Route2(" ~ @.loc.map({.gist}).join(", ") ~ ")"; > } > } > > my $r1 = Route1.new(loc => [Coord.new(x => 0, y => 0), Coord.new(x => > 0, y => 1)]); > note "Got: " ~ $r1.gist; > note "Exp: " ~ "Route1.new(loc => Array[Coord].new(L(0,0), L(0,1)))"; > > my $r2 = Route2.new(loc => [Coord.new(x => 0, y => 0), Coord.new(x => > 0, y => 1)]); > note "Got: " ~ $r2.gist; > note "Exp: " ~ "Route2(L(0,0), L(0,1))"; > ================================ > > Output: > ================================ > Got: Route1.new(loc => Array[Coord].new(Coord.new(x => 0, y => 0), > Coord.new(x => 0, y => 1))) > Exp: Route1.new(loc => Array[Coord].new(L(0,0), L(0,1))) > Got: Route2(L(0,0), L(0,1)) > Exp: Route2(L(0,0), L(0,1)) > ================================
FWIW, I tried the patch below, but that caused a bunch of spectest breakage from things that do assume that Mu.gist is implemented as Mu.perl. It's almost if it should be trying Foo.gist, if that's not available then Foo.perl, and only then go to Mu.perl, which is kinda messy. diff --git a/src/core/Mu.pm b/src/core/Mu.pm index 6f53d66..a560dbd 100644 --- a/src/core/Mu.pm +++ b/src/core/Mu.pm @@ -580,7 +580,20 @@ Perhaps it can be found at https://docs.perl6.org/type/$name" proto method gist(|) { * } multi method gist(Mu:U:) { '(' ~ self.^shortname ~ ')' } - multi method gist(Mu:D:) { self.perl } + multi method gist(Mu:D:) { + nqp::if( + nqp::eqaddr(self,IterationEnd), + "IterationEnd", + self.gistseen(self.^name, { + my @attrs; + for self.^attributes().flat.grep: { .has_accessor } -> $attr { + my $name := substr($attr.Str,2); + @attrs.push: $name ~ ' => ' ~ $attr.get_value(self).gist + } + self.^name ~ '.new' ~ ('(' ~ @attrs.join(', ') ~ ')' if @attrs) + }) + ) + } method perlseen(Mu:D \SELF: $id, $perl, *%named) { my $sigil = nqp::iseq_s($id, 'Array') ?? '@'


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