In the test suite and on IRC there was quite some confusion about how
list builtins are specced, and how they should behave in corner cases.
One is join():
our Str multi method join ( @values: Str $separator = ' ' )
our Str multi join ( Str $separator = ' ', [EMAIL PROTECTED] )
It is quite clear that the perl 5-style
join 'sep', $value, $value2;
invocation remains valid, and
@list.join($sep)
is the new method form.
The confusion arises what to do with
'str'.join('other_str')
should be.
Fallback semantics in S12 suggest that since no matching multi method is
found, subs are tried - that is, the expression is interpreted as
join('str', 'other_str')
yielding 'other_str'. t/spec/S29-list/join.t disagrees, and wants the
result to be 'str'.
Daniel Ruoso argued in favour of the tested behaviour, suggesting that
perhaps the specs should be updated accordingly, mostly because
('str').join('other_str')
would be confusing otherwise.
Patrick Michaud argued in favour of the specced behaviour, and I agree.
Mostly because nobody sane will write things like
'str'.join('other_str') with a literal string as the invocant in first
place. And if it's not a literal, and you want it to behave as list, the
invocant is either something that returns a list, or a variable with the
'@' sigil. We just need to be careful that everything that should return
really does that, even if it contains a single list.
Currently both pugs and rakudo make <a b> return a list (pugs actually
an array, but that's a different problem), but <a> is a Str.
If we'd just be more consistent and always return a list, I don't see a
problem with the spec. If not, it would be rather weird to have <a
b>.join('c') return 'abc', but <a>.join('c') return 'c'.
Consider
my $x = A.new();
$x.y = <a>;
say $x.y.join('b')
The output is different for the two possible declarations of class A:
class A { has $y is rw } # -> b
class A { has @y is rw } # -> a
not pretty IMHO.
So I see the following options:
1) be more consistent with what returns a list
2) Add a method with invocant Any for each list builtin
3) drop method fallback, thus disallowing Str.join(Str) outright
4) be lisp, make everything a list *g* (not serious)
I haven't thought a lot about the third option, and what it would mean
to the language as a whole, so I have no idea if it's a viable alternative.
Any thoughts on the topic are welcome. I hope I didn't confuse too much
here ;-)
Cheers,
Moritz
--
Moritz Lenz
http://moritz.faui2k3.org/ | http://perl-6.de/