5

For example, in this class Foo both methods b and c return the same value:

class Foo {
    method a { 42     }
    method b { $.a    }
    method c { self.a }
}

my $foo = Foo.new;
say $foo.a; #=> 42
say $foo.b; #=> 42
say $foo.c; #=> 42

I noticed I can do the same thing for the other sigil and twigil combinations, e.g., @.scores vs self.score, %.matches vs self.matches, etc.

Edit: I flagged this question as duplicate, however as librasteve points out I failed to realize the subtle distinction mentioned in the answers for the other question isn't the focal point, and might be easily missed especially by someone new to Raku.

uzluisf
  • 2,586
  • 1
  • 9
  • 27
  • Please flag as duplicate and point to https://stackoverflow.com/questions/49970530/using-public-and-private-methods-inside-their-class-in-perl-6/76624226 . – uzluisf Jul 05 '23 at 21:53
  • 1
    dear @moderators, imo this is not a duplicate question since there is a (very) subtle distinction between $.foo and self.foo that is only mentioned in passing in the previous question and may well bite someone in the butt where they need SO to clearly describe the implications. – librasteve Jul 06 '23 at 18:19
  • 2
    @librasteve I asked for it to be reopened. By the subtle distinction, do you mean `$.foo` (or any other sigil variant) contextualizes the method's return value while `self.foo` doesn't? I figured lizmat's answer would be enough but I can see that small distinction might be missed among the other info more relevant to that other question. – uzluisf Jul 06 '23 at 19:38
  • 1
    yes, that is exactly what I mean – librasteve Jul 07 '23 at 18:26

1 Answers1

4

As briefly mentioned in this other SO question's answer, $.method is a shorthand for $(self.method) which means the method's return value is itemized or treated in an item or scalar context. Alternatively you can call item explicitly on self.method, i.e.,, self.method.item.

This contextualization taking place would be more evident if method a returned a list instead:

class Foo {
    method a { 42, 84 }
    method b { $.a    }
    method c { self.a }
}

my $foo = Foo.new;
dd $foo.a; #=> «(42, 84)␤»
dd $foo.b; #=> «$(42, 84)␤»
dd $foo.c; #=> «(42, 84)␤»

Methods a and c returns the list as-is and method b has itemized it. Thus, $.a returns an itemized list while self.a returns a list without any context.

Another way to showcase this is to loop over each method's return value and see how it behaves:

.say for $foo.a; #=> «42␤84␤»
.say for $foo.b; #=> «(42 84)␤»
.say for $foo.c; #=> «42␤84␤»

As shown here, b's return value is treated as a single item, unlike the other methods where for iterates over each element of the list. Contextualization also happens for @.method and %.method, as shown here:

class Bar {
    method a { 1..4 }
    method b { @.a }
    method c { %.a }
    method d { self.a }
}

my $bar = Bar.new;
dd $bar.a; #=> «1..4␤»
dd $bar.b; #=> «(1, 2, 3, 4)␤»
dd $bar.c; #=> «{"1" => 2, "3" => 4}␤»
dd $bar.d; #=> «1..4␤»

The following table summarizes the behavior for contextualized method invocations:

Contextualized Method Invocation Shorthand For Explicit Contextualization
$.method $(self.method) self.method.item
@.method @(self.method) self.method.list
%.method %(self.method) self.method.hash
uzluisf
  • 2,586
  • 1
  • 9
  • 27