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/

Reply via email to