Wrong results using named arguments

J

Jason Vogel

Source:

[a.rb]
class A

attr_accessor :id
attr_accessor :name

def initialize(id = nil, name = nil)
@id = id
@name = name
end
end

[test.rb]
require 'a'

a1 = A.new:)name => "test")
a2 = A.new:)name => "test2")

p a1
p a2

Results:
#<A:0x28c2d80 @id={:name=>"test"}, @name=nil>
#<A:0x28c2678 @id={:name=>"test2"}, @name=nil>

I expected:

#<A:0x28c2d80 @id=nil, @name="test">
#<A:0x28c2678 @id=nil, @name="test2">

So what nuby mistake am I making?

Thanks,
Jason
 
J

Jason Vogel

Sorry about the repost. Initially, I thought the original post went
successfully, but then when I went to check on it, it didn't show up...
suck.

I thought that the keyword arguments support was in Ruby 1.8. I'm used
to coding Oracle PL/SQL, so it seems really natural to me.

I had seen the hash stuff, but those were all posts about 1.6.

Thanks everyone for the replies, I'll keep going.
Jason
 
J

Jason Vogel

Okay, I have a couple of questions. If I use the Hash approach,

- How do I handle argument default values?
- How do I handle required vs. optional arguments?
- Provide some sort of clue to the calling routines what the argument
"names" are?
- Is there a way to enumerate the valid choices for values (e.g. colors
= [red,white,blue])

Jason
 
T

Timothy Hunter

Jason said:
Okay, I have a couple of questions. If I use the Hash approach,

- How do I handle argument default values?
- How do I handle required vs. optional arguments?
- Provide some sort of clue to the calling routines what the argument
"names" are?
- Is there a way to enumerate the valid choices for values (e.g. colors
= [red,white,blue])
You might find the "Method Arguments" section on page 332 in the Pickaxe
(2nd ed.) helpful, as it describes all the ways you can pass arguments
to a method.
 
A

ara.t.howard

Okay, I have a couple of questions. If I use the Hash approach,

- How do I handle argument default values?

def the_method opts = { :arg => 'default value', :another_arg => 'default value too' }
- How do I handle required vs. optional arguments?

def the_method opts = { :a => 'default a', :b => 'default b', :c => nil }

a = opts[:a] || opts['a'] # optional, they pass in nil

b = opts[:b] || opts['b'] or raise "no b!" # required

- Provide some sort of clue to the calling routines what the argument
"names" are?

def the_method opts = { :arg => 'default value', :another_arg => 'default value too' }
- Is there a way to enumerate the valid choices for values (e.g. colors
= [red,white,blue])

def the_method opts = { :a => %w( a b c ).first, :b => %w( d e f ).first }


-a
 
J

Joel VanderWerf

def the_method opts = { :arg => 'default value', :another_arg =>
'default value too' }

Not really, at least in 1.8. That sets the default for _opts_, not for
each of the named args.

def the_method opts = { :arg => 'default value', :another_arg =>
'default value too' }
p opts
end

the_method :arg => "qwe" # ==> {:arg=>"qwe"}

Note that the hash doesn't retain the default value for :another_arg.

Has this changed in 1.9? Is there a way to set the defaults for keyword
args?

...
- Is there a way to enumerate the valid choices for values (e.g. colors
= [red,white,blue])

def the_method opts = { :a => %w( a b c ).first, :b => %w( d e f
).first }

You know this gets evaluated every time you call the_method, right?

def m opts = { :foo => (puts "called m") }; end
m; m

output:

called m
called m

Anyway, this serves no purpose beyond documentation (it doesn't
validate). Why not just put this info into the rdoc for the method?
 
J

Joel VanderWerf

Joel said:
Not really, at least in 1.8. That sets the default for _opts_, not for
each of the named args.

This is one way to handle defaults for keyword args:

DEFAULTS = {
:x => 1,
:y => 2
}

def m opts = {}
opts = DEFAULTS.merge(opts)
p opts
end

m :x => 5 # ==> {:x=>5, :y=>2}

Note that #merge is non-destructive (unlike #update, aka #merge!), so it
doesn't affect DEFAULTS.
 
A

ara.t.howard

In most cases I think it is best if you define DEFAULTS inline, as in:

def m opts = {}
opts = {:x => 1,
:y => 2}.merge(opts)
p opts
end

That way it's closer to the call and thus more self-documenting, and you
don't have to worry about naming a bunch of constants in your class. The
downside is you're newing up a new defaults hash in every method call, and
executing any contained statements.

if you like that style you may like this lib

http://codeforpeople.com/lib/ruby/parseargs/parseargs-0.3.0/README

http://rubyforge.org/frs/?group_id=1024&release_id=8211

regards.

-a
 
J

Joel VanderWerf

Ryan said:
In most cases I think it is best if you define DEFAULTS inline, as in:

def m opts = {}
opts = {:x => 1,
:y => 2}.merge(opts)
p opts
end

That way it's closer to the call and thus more self-documenting, and you
don't have to worry about naming a bunch of constants in your class. The
downside is you're newing up a new defaults hash in every method call, and
executing any contained statements.

If you define default option hashes as constants, you can comment them
and they will appear in RDOC output. RDoc is even smart enough to try to
put the constant value (i.e. the defaults hash) in the doc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top