【问题标题】:How can we set a variable after the user chooses from a HighLine menu in Ruby?用户从 Ruby 的 HighLine 菜单中选择后,我们如何设置变量?
【发布时间】:2014-07-06 23:42:51
【问题描述】:

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 不起作用,而是返回“未定义的局部变量或方法”错误。

【问题讨论】:

    标签: ruby string variables menu highline


    【解决方案1】:

    当方法/块/过程完成执行时,局部变量被销毁。但是,您可以使 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,这意味着它可以看到在创建块时存在于块外的变量。另一方面,块在执行时无法看到块外的变量——即使变量与块可以看到的变量同名。例如,

    def do_stuff(&block)
      x = 1
      block.call
    end
    
    x = 10
    do_stuff {puts x}
    
    --output:--
    10
    

    【讨论】:

    • 哇,这很简单。因此,如果我正确理解这一点,在块中创建的任何变量最终都会被销毁,失去它们存储的任何值。然而,如果变量是在块之前创建的,它会保留块内赋予它的任何值吗?
    【解决方案2】:

    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 看到的内容分解.choice(:meow) {|q| q = 'foo'}。它需要一个名称 (: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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多