Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: How to map a function to a hash

I can't figure out how to assign a function call to a ruby hash. What I want to do is to assign a function to a hash key, and later call this function using the classic hash lookout syntax.

def Foo()
  puts "bar"
end

puts "Assigning"
test = { "foo" => Foo() }

puts "Executing"
test["foo"]

This code fails, function Foo is called after puts "Assign", during hash creation, and nothing happens after puts "Executing"

def Foo()
  puts "bar"
end

puts "Assigning"
test = { "foo" => Foo }

puts "Executing"
test["foo"]

with this code I receive an uninitialized constant Foo (NameError).

Finally with

def Foo()
  puts "bar"
end

puts "Assigning"
test = { "foo" => :Foo }

puts "Executing"
test["foo"]

I get not outputs.

Any suggestions?

Thanks to all for answres and suggestions.

What I'm going to do is to test if a hash based approach to call function is faster than an equivalent code based on if / case statements.

funcs["foo"].call

fatser than

if func_name == "foo" then
  Foo()
elsif ...
...
end

or

case func_name
when "foo"
  Foo()
when ...
  ...
end

Obviously for a big number of functions (~150) and hundreds of calling cycles

like image 477
rico Avatar asked Aug 11 '11 09:08

rico


People also ask

Can you use map with hash Ruby?

Map is a Ruby method that you can use with Arrays, Hashes & Ranges. The main use for map is to TRANSFORM data. For example: Given an array of strings, you could go over every string & make every character UPPERCASE.

How do you create a hash map in Ruby?

Creating a Hash In Ruby you can create a Hash by assigning a key to a value with => , separate these key/value pairs with commas, and enclose the whole thing with curly braces.

How do you use the map method in Ruby?

The way the map method works in Ruby is, it takes an enumerable object, (i.e. the object you call it on), and a block. Then, for each of the elements in the enumerable, it executes the block, passing it the current element as an argument. The result of evaluating the block is then used to construct the resulting array.

How do you define a hash in Ruby?

In Ruby, Hash is a collection of unique keys and their values. Hash is like an Array, except the indexing is done with the help of arbitrary keys of any object type. In Hash, the order of returning keys and their value by various iterators is arbitrary and will generally not be in the insertion order.


2 Answers

you could use lambda's instead of methods. Two options here:

hash = {:foo => lambda { puts 'bar } }

hash[:foo].call

the second (more complicated) is this:

irb(main):001:0> class Hash
irb(main):002:1>   alias :orig_anc :'[]'
irb(main):003:1>
irb(main):004:1*   def [](key)
irb(main):005:2>     if orig_anc(key).is_a? Proc
irb(main):006:3>       orig_anc(key).call
irb(main):007:3>     else
irb(main):008:3*       orig_anc(key)
irb(main):009:3>     end
irb(main):010:2>   end
irb(main):011:1> end
=> nil
irb(main):012:0> h = {:hello => 'world', :foo => lambda { puts 'bar' }}
=> {:hello=>"world", :foo=>#<Proc:0x843224c@(irb):12 (lambda)>}
irb(main):013:0> h[:hello]
=> "world"
irb(main):014:0> h[:foo]
bar
=> nil
irb(main):015:0>

The second one just allows you to skip using 'call' method

like image 167
Vlad Khomich Avatar answered Oct 03 '22 21:10

Vlad Khomich


There is no easy possibility to make your function execute simply by retrieving the hash key withput overriding Hash's [] method, as Vlad pointed out, i.e.

def foo
  puts "hi"
end

... # magic

test["foo"] # outputs hi

won't work. What you can do, though, is assign the method reference using Object#method and then invoke it using call:

def foo
  puts "hi"
end

test = { "foo" => method(:foo) }

test["foo"].call # => hi
like image 37
emboss Avatar answered Oct 03 '22 21:10

emboss