Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this splat method call not working in Ruby?

Tags:

ruby

def method(a, b='a', c, *d)
  [a,b,c, d]
end

p method(1,2,3,4)

doesn't work, I don't understand why, if we remove the b parameter all works well. The syntax rules say that you can put params with default values before the splat parameter.

like image 544
daremkd Avatar asked Mar 22 '23 04:03

daremkd


2 Answers

Variables with defaults and a splat variable can exist and coexist as long as variables with defaults can be interpreted as the initial elements of the (one and only) splat.

As a result, these will all work:

def good(a = :a, b);      [a,b];    end
def good(a = :a, *b);     [a,b];    end
def good(a, b = :b, *c);  [a,b,c];  end

But these won't:

def bad(*a, b = :b);          [a,b];    end  # default after the splat
def bad(a = :a, b, c = :c);   [a,b,c];  end  # parsing would need two splats
def bad(a = :a, b, *c);       [a,b,c];  end  # parsing would need two splats
def bad(*a, b = :b, c);       [a,b,c];  end  # default after the splat

(Tbh, I have no idea what implementation details prevent Ruby from accepting defaults immediately after a splat provided there is no ambiguity. But I'm guessing it's to avoid looping twice over the splat instead of a single time, i.e. performance, and that there might be additional reasons that may have something to do with the way Ruby computes a method's arity.)

like image 176
Denis de Bernardy Avatar answered Mar 31 '23 13:03

Denis de Bernardy


Default parameters (b) should come after positional parameters (a, c):

def method(a, c, b='a', *d)
  [a,b,c, d]
end
like image 36
falsetru Avatar answered Mar 31 '23 13:03

falsetru