Error with splat params in method definition

I’d like to ask why having:

def my_method(*param1, param2 = "default"); end

returns

SyntaxError: (irb):15: syntax error, unexpected '=', expecting ')'

My workaround is explicitly wrap param in brackets like this:

def my_method((*param1), param2 = "default"); end

May thanks

On 02/05/2012 07:19 PM, Jones L. wrote:


My workaround is explicitly wrap param in brackets like this:

def my_method((*param1), param2 = “default”); end

Have you tried calling your method with the workaround with exactly 0 or
more than 2 arguments? I think you’ll find that your workaround doesn’t
really work around anything aside from the syntax error.

Now, I could be wrong about the details, and I believe there are some
subtle changes coming soon with respect to parameter handling for
methods, but I’ll see if I can clarify what is going on. Ruby attempts
to associate method parameters as follows:

  1. Assign the first parameters given in the method call to all the
    positional parameters that do not have defaults defined and report an
    error if there are not enough given parameters to do this.
  2. If there are still more given parameters, assign those to the
    positional parameters that would otherwise have defaults set.
  3. Assign any remaining parameters that are NOT key-value definitions
    for a hash to the splat parameter.
  4. Assign the key-value hash definitions to the final parameter as a
    single hash.

These rules require that method definitions first specify positional
parameters without defaults, followed by positional parameters with
defaults, followed by the splat parameter, followed by a single
parameter that will receive the hash parameters.

I’m sure that I’m going to get all sorts of corrections about the above,
but that’s the gist as I understand things at least.

It appears that you would like to instead specify your positional
parameters (param2) after your splat parameter (param1). I don’t
believe Ruby yet has any facility to handle that in the language, but
you can emulate it:

def my_method(*params)
param1 = params
param2 = params.size > 1 ? params.pop : “default”

end

-Jeremy

On Mon, Feb 6, 2012 at 5:20 AM, Jeremy B. [email protected] wrote:

SyntaxError: (irb):15: syntax error, unexpected ‘=’, expecting ‘)’

This cannot reliably be evaluated because there is an ambiguity. Will
my_method(1) invoke with param1 = [] and param2 = 1 or with param1 =
[1] and param2 = “default”? No machine can decide this.

Now, I could be wrong about the details, and I believe there are some
for a hash to the splat parameter.
4) Assign the key-value hash definitions to the final parameter as a
single hash.

Not sure whether the order between 3 and 4 is correct or even matters.
But that looks like a pretty good description of what’s going on -
apart from the fact that splash can occur anywhere and hence step one
does not only eat leading parameters.

These rules require that method definitions first specify positional
parameters without defaults, followed by positional parameters with
defaults, followed by the splat parameter, followed by a single
parameter that will receive the hash parameters.

It’s not exactly correct any more with 1.9.*: you can have the splat
in other places than the last position:

irb(main):007:0> def f(a,*b,c) p a,b,c end
=> nil
irb(main):008:0> f 1
ArgumentError: wrong number of arguments (1 for 2)
from (irb):7:in f' from (irb):8 from /opt/bin/irb19:12:in
irb(main):009:0> f 1, 2
1
[]
2
=> [1, [], 2]
irb(main):010:0> f 1, 2, 3
1
[2]
3
=> [1, [2], 3]
irb(main):011:0> f 1, 2, 3, 4
1
[2, 3]
4
=> [1, [2, 3], 4]

I’m sure that I’m going to get all sorts of corrections about the above,
but that’s the gist as I understand things at least.

You are correct in that there are limitations.

It appears that you would like to instead specify your positional
parameters (param2) after your splat parameter (param1). I don’t
believe Ruby yet has any facility to handle that in the language,

It can do it but not with defaults:

irb(main):012:0> def f(*a, b, c) p a, b, c end
=> nil
irb(main):013:0> f 1
ArgumentError: wrong number of arguments (1 for 2)
from (irb):12:in f' from (irb):13 from /opt/bin/irb19:12:in
irb(main):014:0> f 1,2
[]
1
2
=> [[], 1, 2]
irb(main):015:0> f 1,2,3
[1]
2
3
=> [[1], 2, 3]
irb(main):016:0> f 1,2,3,4
[1, 2]
3
4
=> [[1, 2], 3, 4]

but you can emulate it:

def my_method(*params)
param1 = params
param2 = params.size > 1 ? params.pop : “default”

end

Yeah, but who wants to read such code? That will be a heck of a
difficult thing to debug. I’d rather stick with standard features
because they also allow for automated error checking and reporting.

Kind regards

robert