Forum: Ruby Optional Message Parameters?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Nathan O. (Guest)
on 2006-04-21 01:48
(Warning: Newbie Altert!)

How do I write a method with optional params? I would think that this:

def do_this(opt1="", opt2="")
	puts opt2
end
do_this(opt2="This")


Would result in "This" being displayed. Instead, "This" becomes the
value of opt1. I'd like to set opt1 and opt2 to default to "". How do I
do that?
Guest (Guest)
on 2006-04-21 01:54
Nathan O. wrote:
> (Warning: Newbie Altert!)
>
> How do I write a method with optional params? I would think that this:
>
> def do_this(opt1="", opt2="")
> 	puts opt2
> end
> do_this(opt2="This")
>
>
> Would result in "This" being displayed. Instead, "This" becomes the
> value of opt1. I'd like to set opt1 and opt2 to default to "". How do I
> do that?
Use a hash:

def do_this( args )
  puts args[:opt2]
end
do_this :opt2=>"This" #=> This

What you're doing now is assigning to opt2 then passing it:

do_this(opt2="This")
puts opt2 #=> "This"
Nathan O. (Guest)
on 2006-04-21 01:57
> Use a hash:
>
> def do_this( args )
>   puts args[:opt2]
> end
> do_this :opt2=>"This" #=> This
>
> What you're doing now is assigning to opt2 then passing it:
>
> do_this(opt2="This")
> puts opt2 #=> "This"

I understand that this will work, but seems so inelegant. Is it really
how this is supposed to be done?
Brian M. (Guest)
on 2006-04-21 02:01
(Received via mailing list)
On 4/20/06, Nathan O. <removed_email_address@domain.invalid> wrote:
> Would result in "This" being displayed. Instead, "This" becomes the
> value of opt1. I'd like to set opt1 and opt2 to default to "". How do I
> do that?

This is usually a case where you either use * or a hash parameter. *
is good for cases where you can distinguish by value. In your case it
looks like a hash would be appropriate.

def do_this(opts)
  puts opt[:two]
end

do_this(:two => "This")

Notes: The hash parameter will always be the last parameter (ignoring
& args and other odd parameter changes when using super). This means
you can pass many things along side the hash, though the more you add
the more complex it gets to manage the interface. Rails uses this
technique heavily. Have a look at the find() code in ActiveRecord
sometime to learn how they manage such an interface (much cleaner in
more recent releases).

Future major versions of Ruby are going to have actual named
parameters. So much to look forward to in 2.0!

Brian.
Guest (Guest)
on 2006-04-21 02:02
Nathan O. wrote:
>> Use a hash:
>>
>> def do_this( args )
>>   puts args[:opt2]
>> end
>> do_this :opt2=>"This" #=> This
>>
>> What you're doing now is assigning to opt2 then passing it:
>>
>> do_this(opt2="This")
>> puts opt2 #=> "This"
>
> I understand that this will work, but seems so inelegant. Is it really
> how this is supposed to be done?

There are default values too:

def do_this( opt1, opt2="" )
  puts opt2
end

If that's what you mean.
Nathan O. (Guest)
on 2006-04-21 02:07
Brian M. wrote:
> On 4/20/06, Nathan O. <removed_email_address@domain.invalid> wrote:
>> Would result in "This" being displayed. Instead, "This" becomes the
>> value of opt1. I'd like to set opt1 and opt2 to default to "". How do I
>> do that?
>
> This is usually a case where you either use * or a hash parameter. *
> is good for cases where you can distinguish by value. In your case it
> looks like a hash would be appropriate.
>
> def do_this(opts)
>   puts opt[:two]
> end
>
> do_this(:two => "This")

*? I don't even know how I'd google that :-)

> Notes: The hash parameter will always be the last parameter (ignoring
> & args and other odd parameter changes when using super). This means
> you can pass many things along side the hash, though the more you add
> the more complex it gets to manage the interface. Rails uses this
> technique heavily. Have a look at the find() code in ActiveRecord
> sometime to learn how they manage such an interface (much cleaner in
> more recent releases).

*Woosh!* That was the sound of this discussion going over my head at
Mach 2!

> Future major versions of Ruby are going to have actual named
> parameters. So much to look forward to in 2.0!

Definitely looking forward to that!
Simen (Guest)
on 2006-04-21 02:18
> *? I don't even know how I'd google that :-)

The star is used to have fun with parameters. Watch:

def have_fun(*args)
  args.each{|arg| puts arg}
end

have_fun 1, 2, 3 # outputs 1, 2, 3

It basically takes any additional parameters provided and puts it into
an array (with the exception of blocks):

def some_args( opt1, opt2, *otheropts )
  otheropts
end

some_args nil, nil, "have", "fun" # => ["have", "fun"]

You can use it the other way to:

arguments = ["Hello", "world"]
send("puts", *arguments) # Outputs the arguments

See http://redhanded.hobix.com/bits/wonderOfTheWhenBeFlat.html for
creative uses.
John G. (Guest)
on 2006-04-23 08:57
(Received via mailing list)
On 4/20/06, Nathan O. <removed_email_address@domain.invalid> wrote:
> Would result in "This" being displayed. Instead, "This" becomes the
> value of opt1. I'd like to set opt1 and opt2 to default to "". How do I
> do that?

Nathan, looks like you're expecting Ruby to be like Python, but Ruby
doesn't have keyword args -- it just looks at the order of the stuff
pass in to a method, and assigns them to the method parameters in that
order.

In the method call you show above (do_this(opt2="This")), what's
happening (I think) is that some local variable named opt2 (local to
the arg list?) is being created in your argument list, and then the
string "This" is being assigned to it. Then, after that business is
done being evaluated, that string gets passed into the method where
it's assigned to parameter opt1.
This topic is locked and can not be replied to.