用ruby中的Hash替换case语句

时间:2017-02-06 07:35:09

标签: ruby hash

我想用case替换ruby中的Hash语句。但是当我尝试在哈希中查找其他键时,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

我将上述case语句替换为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

现在我执行以下操作:

perform_operation(2)

预期产出:

Performing operation TWO

当前输出:

Program is exiting now

2 个答案:

答案 0 :(得分:3)

问题在于这一行:

operations = Hash.new exit_program

在达到该行代码时对exit_program进行评估。

你在这里尝试做的是将一个方法作为一个值传递,你可以做,但它并不像Javascript那么简单,只需输入方法名就足够了。请记住,在Ruby括号中对于方法调用是可选的,因此您的默认值最终是exit_program返回值(在这种情况下,自程序退出以来未定义) )。

你可以对你的方法进行lambda-fy(让它们作为值传递),如下所示:

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

我基本上在-> { }(匿名函数/ lambda)中包装每个方法。 .call就在那里,因为您指定了评估lambda的时间(调用方法)。

除了使用-> { }之外,您还可以使用method(:exit_program)method(:input_from_file)等。它会转换为proc,但它基本上是相同的,您仍然使用{{ 1}}。

答案 1 :(得分:1)

首先,我认为你的case没问题。它具有可读性,并且可能比带有哈希的解决方案更容易出错。

使用哈希,你可以写:

def perform_operation(operation_code)
  operations = { 1 => :perform_operation_one, 2 => :perform_operation_two }
  operations.default = :exit_program
  send(operations[operation_code])
end

由于send不关心方法隐私,因此您可以将exit_programperform_operation_{one,two}设置为私有。事实上,在main中定义时,它们已经是私有的。