Ruby - передача блоков методам - PullRequest
39 голосов
/ 11 ноября 2008

Я пытаюсь ввести пароль Ruby с помощью Highline gem , и, поскольку у меня есть пароль, введенный пользователем дважды, я бы хотел устранить дублирование блоков, которые я передаю. Например, простая версия того, что я делаю сейчас:

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 ]

70 голосов
/ 11 ноября 2008

Код Дэвида будет хорошо работать, но это более простое и короткое решение:

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
13 голосов
/ 11 ноября 2008

Вот как вы должны это сделать, чисто и просто:

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)
4 голосов
/ 11 ноября 2008
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)}
2 голосов
/ 21 мая 2010

Вот пример, который будет добавлять к индексу метод 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
0 голосов
/ 11 ноября 2008

Я не думаю, что язык поддерживает такую ​​конструкцию. Единственный способ, которым я могу это обобщить, это:

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.echo в false, вам нужно будет добавить код только в одном месте.

...