Skip to content
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

When overriding .gist, it's all or nothing #3562

Open
p6rt opened this issue Oct 20, 2014 · 3 comments
Open

When overriding .gist, it's all or nothing #3562

p6rt opened this issue Oct 20, 2014 · 3 comments
Labels

Comments

@p6rt
Copy link

p6rt commented Oct 20, 2014

Migrated from rt.perl.org#123016 (status was 'open')

Searchable as RT123016$

@p6rt
Copy link
Author

p6rt commented Oct 20, 2014

From john@johnkingsley.ca

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))

@p6rt
Copy link
Author

p6rt commented Aug 10, 2017

From @zoffixznet

On Mon, 20 Oct 2014 09​:00​:24 -0700, john@​johnkingsley.ca wrote​:

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') ?? '@​'

@p6rt
Copy link
Author

p6rt commented Aug 10, 2017

The RT System itself - Status changed from 'new' to 'open'

@p6rt p6rt added the Bug label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant