Ruby - 将块传递给方法

时间:2008-11-11 17:31:55

标签: ruby highline

我正在尝试使用Highline gem进行Ruby密码输入,因为我有两次用户输入密码,所以我想消除我传入的块上的重复。例如,我现在正在做的简单版本是:

new_pass = ask("Enter your new password: ") { |prompt| prompt.echo = false }
verify_pass = ask("Enter again to verify: ") { |prompt| prompt.echo = false }

我想改变它是这样的:

foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ") foo
verify_pass = ask("Enter again to verify: ") foo

遗憾的是,这不起作用。这样做的正确方法是什么?

5 个答案:

答案 0 :(得分:70)

David的代码可以正常工作,但这是一个更简单,更简洁的解决方案:

foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ", &foo)
verify_pass = ask("Enter again to verify: ", &foo)

在定义方法时,您还可以使用&符号将块分配给变量:

def ask(msg, &block)
  puts block.inspect
end

答案 1 :(得分:13)

这是你应该如何做到的,简洁明了:

def ask(question)
    yield(question)
end

proc = Proc.new { |question| puts question }
new_pass = ask("Enter your new password: ", &proc)
verify_pass = ask("Enter again to verify: ", &proc)

答案 2 :(得分:4)

foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ") {|x| foo.call(x)}
verify_pass = ask("Enter again to verify: ") {|x| foo.call(x)}

答案 3 :(得分:2)

这是一个示例,它将使用yield方法为索引添加前缀,并使用call方法附加索引。

class Array
  def alter_each!
    self.each_with_index do |n, i|
      self[i] = yield(n,i)
    end
  end
  def modify_each!(add_one = true, &block)
    self.each_with_index do |n, i|
      j = (add_one) ? (i + 1) : i
      self[i] = block.call(n,j)
    end
  end
end

a = ["dog", "cat", "cow"]

a.alter_each! do |n, i|
  "#{i}_#{n}"
end

a.modify_each! false do |n,i|
  "#{n}_#{i}"
end

puts a

答案 4 :(得分:-3)

我不认为该语言支持这样的结构。我能看到以任何方式概括这一点的唯一方法是:

def foo(prompt)
  prompt.echo = false
end
new_pass = ask("Enter your new password: ") { |prompt| foo(prompt) }
verify_pass = ask("Enter again to verify: ") { |prompt| foo(prompt) }

它并没有真正缩短代码,但它确实删除了一些重复 - 如果你想做的不仅仅是设置prompt.echofalse,你只需要在一个代码中添加代码的地方。