From S06:

      sub bar ($a,$b,$c,:$mice) { say $mice }
      sub foo (\$args) { say $args.perl; &bar.call($args); }

  The C<.call> method of C<Code> objects accepts a single C<Capture>
  object, and calls it without introducing a C<CALLER> frame.

And from S12:

  In addition to C<next METHOD>, the special function C<call> dispatches
  to the next candidate, possibly with a new argument list:

      call;           # calls with the original arguments
      call();         # calls with no arguments
      call(1,2,3);    # calls with a different set of arguments

And back in S06:

  The entire argument list may be captured by the C<\$args> parameter.
  It can then be passed to C<call> as C<[,] =$args>:

      # Double the return value for &thermo
      &thermo.wrap( -> \$args { call([,] =$args) * 2 } );

The inconsistency between these three things called "call" is vexing to me. One is a method and takes a capture and only a capture. The second is a special function and takes an argument list, but also has a special arglistless form that passes on the original arguments. The third is a function that takes only a function list, but apparently lacks a arglistless form (otherwise, why bother with capturing an arglist in the example?).

I believe the current spec works. I just think the inconsistency is bad--the three things called "call" do very similar things, but take completely different arguments. I suspect this is just historical smear and we just need to back up and normalize.

(Let me quickly note here that I don't think it's possible to write a subroutine or method that can take either a bare argument list or a Capture and treat them the same, because of the intractable ambiguity that would arise in the case of an argument list that actually contains a single capture as its only positional element. If I'm mistaken, then other avenues open up. But I don't think I am.)

Audrey confirmed to me on IRC that the motivation for the arglistless form was that passing on the original arguments will likely be one of the most common uses of call. And I certainly can't argue with that, I agree.

But why, then, does .call not have an argumentless form? (Because we can't write user-defined methods, short of C<is parsed> tricks, that differentiate between .meth and .meth()? We can't write user-defined subs that do that either, AFAIK...)

Might I propose the following normalization:

1. .call, method definition call(), and .wrap call all take captures. 2. .call() and both types of call() all pass on the arguments of the
   current subroutine.
3. To call with no arguments, use .call(\()) and call(\()).
4. Introduce some syntax for getting a capture of the current argument
   list explicitly.  Perhaps $?ARGS or $?_ or $?CAPTURE.  One shouldn't
   have to choose between repeating your 20 parameters in order to take a
   capture of them, and eliminating your nice self-documenting 20
   parameter names so you can use the easy \$arglist trick.

Trey

Reply via email to