In Ruby, how can you invoke a method using its default argument or with a specified argument without repeating code?
Say I have a ruby method:
def blah(foo=17)
...
end
In code I want to invoke blah with a specific argument "blah(a)" or invoke blah using its default argument "blah()" Is there any way to do that wit开发者_如何学编程hout specifying the method name twice? I'm trying to avoid:
if a.nil?
blah()
else
blah(a)
end
Because it makes the code look more complicated than it is. Best I can come up with (didn't test) is:
args=[]
args << a unless a.nil?
a.send :blah, args
I just tried a few ways, and didn't find any, but if you find yourself doing this a lot, I wonder of the benefit of using a default parameter that way. Try this instead:
def blah(foo=nil)
foo ||= 17
puts foo
end
blah()
a = nil
blah(a)
a = 20
blah(a)
This will output:
17
17
20
I don't like this answer, but I guess it works:
blah( *[a].compact )
It's hard to say without knowing what the actual problem being solved is, but I have a feeling something like this would work best:
blah(a || 17)
This statement seems to more clearly express its intent, without leaving the reader to lookup the definition of the blah
function in order to work out what the default is.
In ruby everything has a return value. So if
also has a return value. The following method works with any number of arguments. The *
expands an array so the array elemnts are individual arguments.
blah(*
if a.nil?
[]
else
[a]
end
)
You don't have to indent it this way, but this looked like the indentation to make it clearest.
I was looking for the same. (I think it is almost a bug in Ruby specs) I think I will solve this in other way ussing the option hash.
def foo(options={})
bar = options.delete(:bar) || :default
puts bar
end
foo
#=> default
foo :bar => :something
#=> something
a = nil
foo :bar => a
#=> default
It is more extensible and is readable for any rubyst.
I vote for
def blah(foo = nil)
foo ||= 17
end
too.
But if you would like to distinguish between the nil
-value and
no-argument situations, I suggest using a block like so:
def blah
foo = block_given? ? yield : 17
end
blah #=> 17
blah { nil } #=> nil
blah { 71 } #=> 71
精彩评论