Passing splat on nil as argument
Asked Answered
M

1

6

All values for b below let me call a method with the *args syntax.

def some_method(a)
   puts a
end

b = 1
some_method(*b) # => 1

b = false
some_method(*b) # => false

b = "whatever"
some_method(*b) # => "whatever"

With nil, I expected to get nil, not argument error:

b = nil
some_method(*b) # => ArgumentError: wrong number of arguments (0 for 1)

What is happening here?

Mansuetude answered 1/6, 2014 at 23:27 Comment(11)
Interestingly this breaks referential transparency, try doing b = *nil; method(b) which works fine.Pasquinade
On a less related note, I'd get nervous of calling a method method. it does spooky things to my pry (starts printing :inspect). I'm assuming you wouldn't do it normally but I thought it was interesting so I thought I'd mention it, I'd be interested if someone could tell me what is causing that.Pasquinade
Well, I don't think I can really do that. The thing is that I am doing some meta-programming where the stuff that goes through could be any value, including nil, but possibly array. So I kind of need it to be method(*b). And yes, the name "method" for a method is not good. Was just an example here.Mansuetude
I suspect it can have something with nil not being a proper object or something. But would be nice to know.Mansuetude
I agree it would be nice to know, which is why I want to keep an eye on the question (and why I upvoted you), but you can eliminate this problem in this one case by having an extra line saying b= *b as this will coerce nil into [] and will leave arrays the same.Pasquinade
Ahh, so do b= *b; some_method(*b)? That could work.Mansuetude
Yep, I'm not gonna post it as an answer as it doesn't answer the question (of what dark magic has infected ruby's nil) but it is at least a solution. :)Pasquinade
I think b = [] if b == nil would be more clear and better actually, but yeah. What is going on with nil?Mansuetude
@MikeH-R: There is already Object#method so calling your own method method won't work out so well.Hanks
@muistooshort I did that mistake in my original question if you check the history.Mansuetude
@muistooshort agreed. I just don't understand what exactly it's doing under the hood. I would expect it to override the default method with the one we've defined. What I don't get is that in my pry it starts printing :inspect every time a string is printed.Pasquinade
T
8

The splat operator * first applies to_a to the object if it is not an array and to_a is defined on it. For numerals, falseclass, and strings, to_a is not defined, and they remain themselves. For nilclass, to_a is defined and returns an empty array. When they are splatted, the numerals, falseclass, and strings remain themselves, but the empty array becomes absence of anything. Also see an answer to this question.

Topography answered 2/6, 2014 at 2:50 Comment(1)
Thanks for the clarification. Nice to know the proper name for it. Found some docs on ruby-doc.org.Mansuetude

© 2022 - 2024 — McMap. All rights reserved.