PushkarKadam
PushkarKadam

Reputation: 339

Default arguments in ruby

I am trying to set up default parameter and I would like to skip passing an argument and assign particular arguments in the function call. But, I am not able to get the desired output.

require "json"
def stun(voltage = 0,frequency = 0,range = "",scope = "")
    body = {
        :voltage => voltage,
        :frequency => frequency,
        :range => range,
        :scope => scope
    }
    response = body.to_json
end


stun(voltage = 1,frequency = 2,scope = "universal")

As you can see in the code above, I am trying to assign value to scope while keeping the range parameter an empty string. I am getting the following response.

"{\"voltage\":1,\"frequency\":2,\"range\":\"universal\",\"scope\":\"\"}"

My desired output would be to have range as an empty string and scope as "universal"

Upvotes: 20

Views: 31590

Answers (2)

Simple Lime
Simple Lime

Reputation: 11035

You've set up default values for the arguments, but you're still using positional arguments, the first argument will always go to voltage, the second to frequency, the third to range, the fourth to scope. Since you are passing 3 arguments, you end up passing voltage, frequency, and range.

Those equal signs in the method call, aren't doing what you think. Instead of telling ruby which parameter is getting assigned, you are creating a local variable with those names:

stun(voltage = 1,frequency = 2,scope = "universal")
puts [voltage, frequency, scope].inspect # => [1, 2, "universal"]

Ruby does have a way, with named parameters, to do what you want though:

def stun(voltage: 0, frequency: 0, range: "", scope: "")
    body = {
        :voltage => voltage,
        :frequency => frequency,
        :range => range,
        :scope => scope
    }

    response = body.to_json
end

puts stun(voltage: 1, frequency: 2, scope: "universal")
# => {"voltage":1,"frequency":2,"range":"","scope":"universal"}

This is available (I believe) since Ruby 2.0. If you use these though, you'll always need to pass the parameters with their names, for instance:

stun(1, 2, "", "universal")

raises wrong number of arguments (given 4, expected 0) now. This isn't a bad thing, in my opinion, just something to keep in mind.

Upvotes: 37

gangelo
gangelo

Reputation: 3182

Have you considered passing a hash?

def stun(params)
    body = {
        voltage: 0,
        frequency: 2,
        range: '',
        scope: ''
    }
    body.merge!(params)
    response = body.to_json
end

stun({voltate: 1, frequency: 2, scope: 'universal'})
=> "{\"voltage\":0,\"frequency\":2,\"range\":\"\",\"scope\":\"universal\",\"voltate\":1}"

Upvotes: 3

Related Questions