Reputation: 872
I want to replace case
statement in ruby with Hash
. But the Hash seems to call the default value first every time when I try to lookup for other keys in the hash.
def perform_operation_one
puts 'Performing operation ONE'
end
def perform_operation_two
puts 'Performing operation TWO'
end
def exit_program
puts 'Program is exiting now'
exit(0)
end
def perform_operation(operation_code)
case operation_code
when 1
perform_operation_one
when 2
perform_operation_two
else
exit_program
end
end
I replaced the above case
statement with the Hash
def perform_operation(operation_code)
operations = Hash.new exit_program #Default value if no operation is present in operations corresponding to operation_code key
operations[1] = perform_operation_one
operations[2] = perform_operation_two
operations[operation_code]
end
Now when I execute following:
perform_operation(2)
Expected Output:
Performing operation TWO
Current Output:
Program is exiting now
Upvotes: 0
Views: 1453
Reputation: 54233
First, I think your case
is fine. It's readable and might be less bug-prone than a solution with a hash.
With a hash, you could write :
def perform_operation(operation_code)
operations = { 1 => :perform_operation_one, 2 => :perform_operation_two }
operations.default = :exit_program
send(operations[operation_code])
end
Since send
doesn't care about method privacy, you could set exit_program
, perform_operation_{one,two}
as private. As a matter of fact, they're already private when defined in main
.
Upvotes: 1
Reputation: 26768
The problem is this line:
operations = Hash.new exit_program
evaluates exit_program
right when that line of code is reached.
What you're trying to do here is pass a method as a value, which you can do, but it's not quite as simple as say Javascript, where just typing the method name would suffice. Remember, in Ruby parenthesis are optional for method calls, so your default value ends up being the return value of the exit_program
(in this case, that's undefined since the program exits).
You can lambda-fy your methods (let them be passed as values) like so:
def perform_operation(operation_code)
operations = Hash.new(-> { exit_program })
operations[1] = -> { input_from_file }
operations[2] = -> { input_from_console }
operations[operation_code].call
end
I'm basically wrapping every method in -> { }
(an anonymous function / lambda). The .call
is there because you specify that it's time to evaluate the lambda (calling the method).
Rather than using -> { }
you could also use method(:exit_program)
, method(:input_from_file)
, etc. It converts to a proc but it's basically the same thing, you still use .call
.
Upvotes: 3