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

ブロックは と呼ばれるものを作成しますclosure。これは、ブロックが作成されたときにブロックの外部に存在していた変数を参照できることを意味します。一方、ブロックは、ブロックが参照できる変数と同じ名前の変数を持っている場合でも、EXECUTED の時点でブロック外の変数を参照できませ。例えば、

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 )されるので、choose メソッドは任意の長さの引数とブロックを受け取ります。do ... endブロックは、choose 呼び出しに渡される場所です。

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

わかりましたので、別のメソッドが表示されますchoice: http://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)何も提供されていない場合は help をデフォルトで nil にし (したがって、私の呼び出し例では nil です)、最後に別のブロックである{|q| q = 'foo'}.

私の例は次のように評価されます。

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

なんで?q は、渡されるブロックのスコープ内でのみ定義されているためです。そのプロシージャが評価されると、アクセスできません。だからあなたがする必要があるのはこれです:

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 に答える