0

HighLine 文档显示我们可以在用户从列表中选择一个选项后显示一个字符串,如下所示:

choose do |menu|
  menu.prompt = "Please choose your favorite programming language?  "

  menu.choice(:ruby) { say("Good choice!") }
  menu.choices(:python, :perl) { say("Not from around here, are you?") }
end

除了(或代替)显示文本之外,我们如何设置变量?替换say("Good choice!")variable = 1不起作用,而是返回“未定义的局部变量或方法”错误。

4

2 回答 2

4

当方法/块/过程完成执行时,局部变量被销毁。但是,您可以使它variable不是块的局部变量:

variable = nil

choose do |menu|
  variable = 1
  menu.prompt = "Please choose your favorite programming language?  "

  menu.choice(:ruby) { say("Good choice!") }
  menu.choices(:python, :perl) { say("Not from around here, are you?") }
end

puts variable

块创建所谓的 a closure,这意味着它可以看到在创建块时存在于块外的变量。另一方面,块在执行时无法看到块外的变量——即使变量与块可以看到的变量同名。例如,

def do_stuff(&block)
  x = 1
  block.call
end

x = 10
do_stuff {puts x}

--output:--
10
于 2014-07-07T01:46:40.963 回答
0

TL;DR 响应只是您需要定义一个可在块范围之外访问的变量。

首先,查看 API 的文档:

http://rubydoc.info/gems/highline/HighLine#choose-instance_method

你会看到def choose( *items, &details ),所以选择方法接受任意长度的参数,然后也是一个块。该块是您看到do ... end被交给选择调用的地方:

choose do |menu|
  menu.choice(:meow) {|q| q = 'foo'}
end

好的,所以我们看到另一种方法,即choicehttp ://rubydoc.info/gems/highline/HighLine/Menu#choice-instance_method

# File 'lib/highline/menu.rb', line 136

def choice( name, help = nil, &action )
  @items << [name, action]

  @help[name.to_s.downcase] = help unless help.nil?
  update_responses  # rebuild responses based on our settings
end

.choice(:meow) {|q| q = 'foo'}现在让我们用我们看到的来分解choice。它需要一个 name (:meow),如果没有提供帮助,则默认为 nil (因此在我的示例中调用它是 nil ),最后采用另一个块是{|q| q = 'foo'}.

我的示例评估为:

1. meow
?  1
 => "foo"
q
=> NameError: undefined local variable or method `q' for main:Object

为什么?因为 q 仅在传入的块的范围内定义。一旦评估了该 proc,您就无法访问它。所以你需要做的是:

1.9.3-p448 :015 > choose do |menu|
1.9.3-p448 :016 >     menu.choice(:meow) { @foo = 'foo'}
1.9.3-p448 :017?>   end
1. meow
?  1
 => "foo"
1.9.3-p448 :018 > @foo
 => "foo"
于 2014-07-07T01:51:03.317 回答