Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Optional Parameters and Multiple Parameters

I am trying to set the first argument to a method as being optional, followed by any number of args. For example:

def dothis(value=0, *args)

The issue I am running into is that it doesn't seem like this is actually possible? When I call dothis("hey", "how are you", "good") I was hoping it would set value to default to 0, but instead it is just making value="hey". Is there any way to accomplish this behavior?

like image 615
Andrew Backes Avatar asked Feb 28 '13 15:02

Andrew Backes


People also ask

Can parameters be optional?

The definition of a method, constructor, indexer, or delegate can specify its parameters are required or optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. Each optional parameter has a default value as part of its definition.

What's the difference between a parameter and an argument Ruby?

A parameter is the variable listed inside the parentheses in the function definition. An argument is the value that is sent to the function when it is called.

How do you accept number of arguments in Ruby?

A method defined as def some_method(**args) can accept any number of key:value arguments. The args variable will be a hash of the passed in arguments.

Can we have multiple optional parameters in C#?

In c#, we can also achieve the optional parameters by using method overloading functionality. Generally, the method overloading functionality will allow us to create multiple methods with the same name but with different parameters.


3 Answers

This is not possible directly in Ruby

There are plenty of options though, depending on what you are doing with your extended params, and what the method is intended to do.

Obvious choices are

1) Take named params using hash syntax

def dothis params
  value = params[:value] || 0
  list_of_stuff = params[:list] || []

Ruby has nice calling convention around this, you don't need to provide the hash {} brackets

dothis :list => ["hey", "how are you", "good"]

2) Move value to the end, and take an array for the first param

def dothis list_of_stuff, value=0

Called like this:

dothis ["hey", "how are you", "good"], 17

3) Use a code block to provide the list

dothis value = 0
  list_of_stuff = yield

Called like this

dothis { ["hey", "how are you", "good"] }

4) Ruby 2.0 introduced named hash parameters, which handle a lot of option 1, above for you:

def dothis value: 0, list: []
  # Local variables value and list already defined
  # and defaulted if necessary

Called same way as (1):

dothis :list => ["hey", "how are you", "good"]
like image 90
Neil Slater Avatar answered Nov 07 '22 18:11

Neil Slater


This post is a little bit old, but I want to contribute if someone is looking for the best solution for that. Since ruby 2.0, you can do that easily with named arguments defined with a hash. The syntax is easy and more readable.

def do_this(value:0, args:[])
   puts "The default value is still #{value}"
   puts "-----------Other arguments are ---------------------"
  for i in args
    puts i
  end
end
do_this(args:[ "hey", "how are you", "good"])

You can also do the same thing with the greedy keyword **args as a hash, like this:

#**args is a greedy keyword
def do_that(value: 0, **args)
  puts "The default value is still #{value}"
  puts '-----------Other arguments are ---------------------'
  args.each_value do |arg|
    puts arg
  end
end
do_that(arg1: "hey", arg2: "how are you", arg3: "good")
like image 45
Amaynut Avatar answered Nov 07 '22 19:11

Amaynut


You will need to use named parameters to accomplish this:

def dothis(args)
  args = {:value => 0}.merge args
end

dothis(:value => 1, :name => :foo, :age => 23)
 # => {:value=>1, :name=>:foo, :age=>23} 
dothis(:name => :foo, :age => 23)
 # => {:value=>0, :name=>:foo, :age=>23}
like image 39
Kyle Avatar answered Nov 07 '22 18:11

Kyle