Passing a hash of args


#1

Is there a way to pass each item is a hash as a successive argument to a
function?

ie:

time = {
:year => 2003
:month => 03
:day => 24
}
Time.local(time)

(that wouldn’t work but you get the idea)

Cheers


#2

On Mon, Jan 09, 2006 at 07:55:42AM +0900, Jonathan L. wrote:

Time.local(time)

(that wouldn’t work but you get the idea)

Hashes aren’t ordered. Otherwise you could just do
Time.local(*time.values).

Time.local(*[:year, :month, :day].map {|key| time[key]}) is DRYer but
more
typing than Time.local(time[:year], time[:month], time[:day])

I look forward to someone else coming up with something clever.

marcel


#3

Jonathan L. wrote:

}

Time.local(*time.values.reverse)

– Daniel


#4

On Sun, 08 Jan 2006 23:00:42 -0000, Daniel H.
removed_email_address@domain.invalid wrote:

:day => 24
}
Time.local(time)

(that wouldn’t work but you get the idea)

Time.local(*time.values.reverse)

Pretty sure that’d only work with some hashes, and only if you had less
than a bucketful of entries?

Cheers,


#5

On Jan 9, 2006, at 12:18 AM, Ross B. wrote:

Yes, my mistake. (too late to be thinking here…)

James’s suggestion seems to be the best.

– Daniel


#6

On Mon, 2006-01-09 at 08:01 +0900, James Edward G. II wrote:

=> Mon Mar 24 00:00:00 CST 2003
Cool. Thanks everyone. I didn’t realise you could do *myvar when calling
a method as well as when defining them. I was basically looking for a
way to do the following (which I’ve managed to solve without use of a
hash):

class Time
UNITS = [ :year, :month, :day, :hour, :min, :sec, :usec ]

def to_precision(unit)
args = []
0.upto(UNITS.index(unit)) { |unit| args <<
method(UNITS[unit]).call }
Time.local(*args)
end
end

Is that a sensible way to do it?

Cheers


#7

On Jan 8, 2006, at 4:55 PM, Jonathan L. wrote:

}
Time.local(time)

Well, Hashes are unordered by definition, but as long as we declare
an order it’s doable:

time = {
?> :year => 2003,
?> :month => 03,
?> :day => 24

}
=> {:month=>3, :year=>2003, :day=>24}

Time.local(*time.values_at(:year, :month, :day))
=> Mon Mar 24 00:00:00 CST 2003

Hope that helps.

James Edward G. II


#8

On Mon, 2006-01-09 at 10:26 +0900, removed_email_address@domain.invalid wrote:

Is that a sensible way to do it?

I would do:

send(UNITS[unit])

in preference to the method/call thing. Maybe:

args = (0…UNITS.index(unit)).map { |unit| send(UNITS[unit]) }

Awesome, thanks. I did feel the method/call bit was slightly ugly.

Cheers


#9

Hi –

On Mon, 9 Jan 2006, Jonathan L. wrote:

Time.local(*time.values_at(:year, :month, :day))
def to_precision(unit)
args = []
0.upto(UNITS.index(unit)) { |unit| args <<
method(UNITS[unit]).call }
Time.local(*args)
end
end

Is that a sensible way to do it?

I would do:

send(UNITS[unit])

in preference to the method/call thing. Maybe:

args = (0…UNITS.index(unit)).map { |unit| send(UNITS[unit]) }

David


David A. Black
removed_email_address@domain.invalid

“Ruby for Rails”, from Manning Publications, coming April 2006!