天道酬勤,学无止境

Why does the break statement in ruby behave differently when using Proc.new v. the ampersand sign?

The break statement for blocks (as per The Ruby Programming Language) is defined as follows:

it causes the block to return to its iterator and the iterator to return to the method that invoked it.

Therefore when the following code is run, it results in a LocalJumpError.

def test
    puts "entering test method"
    proc = Proc.new { puts "entering proc"; break }
    proc.call # LocalJumpError: iterator has already returned
    puts "exiting test method"
end
test

While the following code does not throw a LocalJumpError. What is special about the ampersand sign? Doesn't the ampersand sign implicitly use Proc.new?

def iterator(&proc)
    puts "entering iterator"
    proc.call # invoke the proc
    puts "exiting iterator" # Never executed if the proc breaks
end

def test
    iterator { puts "entering proc"; break }
end
test

In other words, I read the ampersand sign as a means of in-lining the Proc.new call. At which point the behavior should be just the same as the first code snippet.

def iterator (p = Proc.new { puts "entering proc"; break})
...
end

Disclaimer: I am newb learning the language (ruby 1.9.2), and therefore will appreciate references and a detailed synopsis.

评论

break makes the block and the caller of the block return. In the following code:

proc = Proc.new { break }

The "caller" of the block which is converted to a Proc object is Proc.new. break is supposed to make the caller of the block return, but Proc.new has already returned.

In this code:

def iterator(&b); b.call; end
iterator { break }

The caller of the block is iterator, so it makes iterator return.

Here's the answer.

Ampersand is used to convert a proc to a block and a block to a proc.

I changed the example so as to relate to your case:

def run_my_code(&my_code)
 puts 'before proc'
 my_code.call
 puts 'after proc'
end
run_my_code { puts "passing a block, accepting a proc"; break}
=> before proc
   passing a block, accepting a proc

As you can see it didn't reach the 'after proc'

def run_my_code
 yield
end
my_proc = Proc.new  { puts "passing a proc instead of block"; break}
run_my_code &my_proc
=> passing a proc instead of block
   LocalJumpError: break from proc-closure
   from (pry):75:in `block in <main>'

In your second example you have a proc in result, the proc breaks from iterator and returns to test function.

def iterator(&proc)
  puts 'entering iterator'
  proc.call
  puts 'exiting iterator'
end

def test
  puts 'before test'
  iterator { puts 'entering proc'; break }
  puts 'after test'
end

=>before test
entering iterator
entering proc
after test

It has to do with the difference between blocks, procs and lambdas - and their respective scopes.

I wrote a post about it back in 2009 that you might find useful: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-the-difference/

Hope this helps.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 何时使用lambda,何时使用Proc.new?(When to use lambda, when to use Proc.new?)
    问题 在Ruby 1.8中,一方面proc / lambda与另一方面Proc.new之间存在细微的差异。 这些区别是什么? 您能提供有关如何决定选择哪一个的指导吗? 在Ruby 1.9中,proc和lambda是不同的。 这是怎么回事? 回答1 使用lambda创建的Proc.new和使用Proc.new创建的Proc.new之间的另一个重要但细微的区别是它们如何处理return语句: 在由lambda创建的proc中, return语句仅从proc本身返回在Proc.new创建的proc中, return语句有点令人惊讶:它不仅从proc还从封装proc的方法中返回控制! 这是由lambda创建的proc的return 。 它的行为可能与您预期的一样: def whowouldwin mylambda = lambda {return "Freddy"} mylambda.call # mylambda gets called and returns "Freddy", and execution # continues on the next line return "Jason" end whowouldwin #=> "Jason" 现在,这是一个由Proc.new创建的proc的return执行相同的操作。 您将看到以下其中一种情况,其中Ruby打破了广受赞誉的
  • 为什么显式收益在Proc中有所作为?(Why does explicit return make a difference in a Proc?)
    问题 def foo f = Proc.new { return "return from foo from inside proc" } f.call # control leaves foo here return "return from foo" end def bar b = Proc.new { "return from bar from inside proc" } b.call # control leaves bar here return "return from bar" end puts foo # prints "return from foo from inside proc" puts bar # prints "return from bar" 我认为return关键字在Ruby中是可选的,无论您是否要求,您总是会return ing。 鉴于此,我发现foo和bar具有不同的输出是令人惊讶的,这取决于foo在Proc f包含显式return的事实。 有人知道为什么会这样吗? 回答1 Ruby具有三个构造: 块不是对象,而是由{ ... }或do ... end 。 proc是由Proc.new或proc创建的Proc对象。 lambda是由lambda (或Ruby 1.8中的proc )创建的Proc 。 Ruby具有三个从某事物返回的关键字:
  • Ruby中的proc和lambda有什么区别?(What's the difference between a proc and a lambda in Ruby?)
    问题 您什么时候会使用一个而不是另一个? 回答1 一种区别是它们处理参数的方式。 使用proc {}和Proc.new {}创建proc是等效的。 但是,使用lambda {}为您提供了一个过程,可以检查传递给它的参数数量。 来自ri Kernel#lambda : 与Proc.new等效,除了生成的Proc对象检查调用时传递的参数数量。 一个例子: p = Proc.new {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28@(irb):1> p.call 1, 2 # => 5 p.call 1 # => NoMethodError: undefined method `**' for nil:NilClass p.call 1, 2, 3 # => 5 l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c@(irb):5 (lambda)> l.call 1, 2 # => 5 l.call 1 # => ArgumentError: wrong number of arguments (1 for 2) l.call 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2) 此外,正如Ken所指出的那样
  • Ruby:Proc#call与收益率(Ruby: Proc#call vs yield)
    问题 thrice Ruby中以下两种实现在行为上有什么区别? module WithYield def self.thrice 3.times { yield } # yield to the implicit block argument end end module WithProcCall def self.thrice(&block) # & converts implicit block to an explicit, named Proc 3.times { block.call } # invoke Proc#call end end WithYield::thrice { puts "Hello world" } WithProcCall::thrice { puts "Hello world" } 通过“行为差异”,我包括错误处理,性能,工具支持等。 回答1 我认为第一个实际上是另一个的语法糖。 换句话说,没有行为上的差异。 第二种形式允许的是将块“保存”在变量中。 然后可以在其他时间点调用该块-回调。 好的。 这次我去做了一个快速基准测试: require 'benchmark' class A def test 10.times do yield end end end class B def test(&block) 10.times do block
  • Ruby块的最佳解释? [关闭](Best explanation of Ruby blocks? [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 7年前关闭。 改善这个问题 您可以共享的Ruby块的最佳解释是什么? 用法和编写代码可能会花费很多时间? 回答1 我对此回答提供了自己的解释,并做了一些修改: Ruby中的“块”与通用编程术语“代码块”或“代码块”不同。 假装一下以下(无效的)Ruby代码实际上有效: def add10( n ) puts "#{n} + 10 = #{n+10}" end def do_something_with_digits( method ) 1.upto(9) do |i| method(i) end end do_something_with_digits( add10 ) #=> "1 + 10 = 11" #=> "2 + 10 = 12" ... #=> "9 + 10 = 19" 尽管该代码无效,但它的意图(将某些代码传递给某个方法并让该方法运行该代码)可以在Ruby中以多种方式实现。 这些方法之一是“块”。 Ruby中的Block非常非常类似于一种方法:它可以接受一些参数并为其运行代码。 每当您看到foo{ |x,y,z| ... } foo{ |x,y,z| ... }或foo do |x,y,z| ... end foo do |x
  • 如何在Ruby中编写switch语句(How to write a switch statement in Ruby)
    问题 如何在Ruby中编写switch语句? 回答1 Ruby改用case表达式。 case x when 1..5 "It's between 1 and 5" when 6 "It's 6" when "foo", "bar" "It's either foo or bar" when String "You passed a string" else "You gave me #{x} -- I have no idea what to do with that." end Ruby使用===运算符将when子句中的对象与case子句中的对象进行比较。 例如, 1..5 === x ,而不是x === 1..5 。 如上所述,这可以实现复杂的when子句。 可以测试范围,类和各种各样的东西,而不仅仅是相等性。 不像switch在许多其他语言的语句,Ruby的case并没有落空,所以没有必要每次结束when以break 。 您还可以在单​​个when子句中指定多个匹配项,例如when "foo", "bar" 。 回答2 case...when处理类case...when表现出一些意外。 这是由于它使用===运算符。 该运算符可以按预期使用文字,但不能使用类: 1 === 1 # => true Fixnum === Fixnum # => false 这意味
  • equal?,eql?,===和==之间有什么区别?(What's the difference between equal?, eql?, ===, and ==?)
    问题 我试图了解这四种方法之间的区别。 我知道默认情况下==调用方法是否equal? 当两个操作数都引用完全相同的对象时,它返回true。 默认情况下===也调用==哪个调用equal? ...好吧,如果这三个方法都没有被覆盖,那么我猜=== , == equal? 做完全一样的事情? 现在是eql? 。 这是做什么的(默认情况下)? 它是否调用操作数的哈希值/ ID? 为什么Ruby有这么多相等标志? 他们应该在语义上有所不同吗? 回答1 我将在这里大量引用对象文档,因为我认为它有一些很好的解释。 我鼓励您阅读它,以及这些方法的文档,因为它们在其他类(例如String)中被覆盖。 旁注:如果您想在不同的物体上自己尝试一下,请使用以下方法: class Object def all_equals(o) ops = [:==, :===, :eql?, :equal?] Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })] end end "a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false} == —通用“平等” 在对象级别,仅当obj和other是同一对象时, ==返回true。 通常
  • Ruby有Python没有的,反之亦然?(What does Ruby have that Python doesn't, and vice versa?)
    问题 已锁定。 该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。 它目前不接受新的答案或互动。 关于Python和Ruby的讨论很多,我都发现它们完全无济于事,因为它们都绕开了为什么功能X吸收了语言Y的理由,或者声称语言Y没有X,尽管实际上确实如此。 我也确切地知道为什么我偏爱Python,但这也是主观的,并且不会帮助任何人选择,因为他们在开发中可能没有和我一样的爱好。 因此,客观列出差异会很有趣。 因此,没有“ Python的lambdas很烂”。 相反,请解释Ruby的lambda可以做什么,而Python则不能。 没有主观性。 示例代码很好! 请在一个答案中没有几个差异。 然后,将您所知道的正确或不正确(或主观的)否决。 同样,语法上的差异也不是很有趣。 我们知道Python用缩进来做,而Ruby用括号和尾来做,@在Python中被称为self。 更新:这现在是社区Wiki,因此我们可以在此处添加较大的差异。 Ruby在类主体中有一个类引用 在Ruby中,您已经在类主体中引用了该类(自身)。 在Python中,直到类构造完成后,您才可以引用该类。 一个例子: class Kaka puts self end 在这种情况下,self是类,并且此代码将打印出“ Kaka”。 无法打印出类名,也无法以其他方式从Python中的类定义主体(外部方法定义)访问该类。
  • 在Ruby中显式返回的好样式吗?(Is it good style to explicitly return in Ruby?)
    问题 来自Python背景,在样式方面总是有“正确的方法”(“ Pythonic”的方法),我想知道Ruby是否也存在这种情况。 我一直在使用自己的样式准则,但我正在考虑发布我的源代码,我希望它遵守可能存在的任何未成文规则。 明确输入方法的return是“ Ruby之道”吗? 我已经看到有和没有它都完成了,但是有正确的方法吗? 也许有合适的时机吗? 例如: def some_func(arg1, arg2, etc) # Do some stuff... return value # <-- Is the 'return' needed here? end 回答1 旧的(也是“已回答”的)问题,但是我会花两分钱作为答案。 TL; DR-不必这样做,但是在某些情况下,它可使您的代码更加清晰。 尽管不使用显式返回可能是“ Ruby方式”,但它使使用不熟悉的代码或不熟悉Ruby的此功能的程序员感到困惑。 这是一个有些人为的示例,但请想象有一个像这样的小功能,该功能在传递的数字上加一个,然后将其分配给实例变量。 def plus_one_to_y(x) @y = x + 1 end 这是否意味着要返回一个值的函数? 很难说出开发人员的含义,因为它既分配了实例变量,又返回了分配的值。 假设很久以后,另一个程序员(也许不太熟悉Ruby如何根据执行的最后一行代码返回结果
  • 为什么我可以在Java中抛出null? [复制](Why can I throw null in Java? [duplicate])
    问题 这个问题已经在这里有了答案: 为什么“ throw null”不会在Java中创建编译错误? (4个答案) 1年前关闭。 运行此命令时: public class WhatTheShoot { public static void main(String args[]){ try { throw null; } catch (Exception e){ System.out.println(e instanceof NullPointerException); System.out.println(e instanceof FileNotFoundException); } } } 响应为: true false 这对我来说真是太棒了。 我本以为这会带来编译时错误。 为什么我可以在Java中抛出null,为什么将其转换为NullPointerException? (实际上,鉴于我抛出的是null,因此我不知道这是否是“ upcast”) 除了一个非常愚蠢的面试问题(请没人在面试中问这个问题)之外,我看不出有任何理由throw null 。 也许您想被解雇,但这就是...我的意思是,为什么还有人会throw null呢? 有趣的事实IntelliJ IDEA 12告诉我,我的行, e instanceof NullPointerException ,将始终为false。
  • “猴子修补”在Ruby中到底意味着什么?(What does 'Monkey Patching' exactly Mean in Ruby?)
    问题 根据维基百科,猴子补丁是: 一种在不更改原始源代码的情况下扩展或修改动态语言的运行时代码的方法。 来自同一条目的以下陈述使我感到困惑: 在Ruby中,“猴子补丁”一词被误解为对类的任何动态修改,并且通常用作在运行时动态修改任何类的同义词。 我想知道Ruby中猴子修补的确切含义。 它正在执行以下操作还是其他操作? class String def foo "foo" end end 回答1 简短的答案是没有“确切”的含义,因为它是一个新颖的术语,并且不同的人使用它的方式也不同。 至少可以从Wikipedia文章中看出这一点。 有些人坚持认为它仅适用于“运行时”代码(我想是内置类),而有些人会使用它来指代任何类的运行时修改。 就我个人而言,我更喜欢更具包容性的定义。 毕竟,如果仅将术语用于内置类的修改,那么我们将如何引用所有其他类的运行时修改? 对我来说重要的是,源代码和实际运行的类之间存在差异。 在Ruby中,“猴子补丁”一词被误解为对类的任何动态修改,并且通常用作在运行时动态修改任何类的同义词。 上面的声明断言Ruby的用法是不正确的-但是术语会不断演变,但这并不总是一件坏事。 回答2 我听到的有关猴子修补/鸭打孔的最好解释是帕特里克·尤因(Patrick Ewing)在RailsConf 2007中 ...如果走路像鸭子,说话像鸭子,那就是鸭子,对吗? 因此
  • 如何从PowerShell中的ForEach-Object退出(How to exit from ForEach-Object in PowerShell)
    问题 我有以下代码: $project.PropertyGroup | Foreach-Object { if($_.GetAttribute('Condition').Trim() -eq $propertyGroupConditionName.Trim()) { $a = $project.RemoveChild($_); Write-Host $_.GetAttribute('Condition')"has been removed."; } }; 问题1:如何从ForEach-Object退出? 我尝试使用“ break”和“ continue”,但是不起作用。 问题2:我发现我可以在foreach循环中更改列表...我们无法在C#中做到这一点...为什么PowerShell允许我们这样做? 回答1 项目#1。 在foreach循环中放置一个break确实会退出循环,但不会停止管道。 听起来您想要这样的东西: $todo=$project.PropertyGroup foreach ($thing in $todo){ if ($thing -eq 'some_condition'){ break } } 项目#2。 PowerShell使您可以在该数组的foreach循环中修改该阵列,但是这些更改在退出循环之前不会生效。 尝试运行下面的代码作为示例。 $a=1,2,3
  • __FILE__在Ruby中是什么意思?(What does __FILE__ mean in Ruby?)
    问题 我一直在Ruby中看到以下内容: require File.dirname(__FILE__) + "/../../config/environment" __FILE__是什么意思? 回答1 它是对当前文件名的引用。 在文件foo.rb , __FILE__将被解释为"foo.rb" 。 编辑: Ruby 1.9.2和1.9.3的行为似乎与Luke Bayes在其评论中所说的有所不同。 使用这些文件: # test.rb puts __FILE__ require './dir2/test.rb' # dir2/test.rb puts __FILE__ 运行ruby test.rb将输出 test.rb /full/path/to/dir2/test.rb 回答2 __FILE__的值是在加载文件时创建和存储(但从未更新)的相对路径。 这意味着,如果您在应用程序中的其他任何地方都对Dir.chdir进行了任何调用,则此路径将Dir.chdir正确扩展。 puts __FILE__ Dir.chdir '../../' puts __FILE__ 解决此问题的一种方法是将扩展的__FILE__值存储在任何应用程序代码之外。 只要您的require语句在定义的顶部(或者至少在对Dir.chdir任何调用之前),则此值在更改目录后将继续有用。 $MY_FILE_PATH =
  • Python中的所有对象都是像Ruby这样的对象吗?(Is everything an object in Python like Ruby?)
    问题 我读到另一个有关Stack Overflow的问题,Python就像Ruby,因为它涉及“一切都是对象”,而Python中的一切都是对象,就像Ruby一样。 这是真的? Python中的所有对象都是像Ruby这样的对象吗? 两者在这方面有何不同?或者它们实际上是相同的吗? 例如,您可以拿一个数字来做我所看到的Ruby事情吗: y = 5.plus 6 可以在Python中以相同的方式完成吗? 回答1 DiveIntoPython-一切都是对象 Python中的所有内容都是对象,几乎所有内容都具有属性和方法。 所有函数都具有内置属性__doc__ ,该属性返回函数源代码中定义的doc string 。 sys模块是一个对象,具有(除其他外)名为path的属性。 依此类推。 尽管如此,这还是个问题。 什么是物体? 不同的编程语言以不同的方式定义“对象”。 在某些情况下,这意味着所有对象都必须具有属性和方法。 在其他情况下,这意味着所有对象都是可子类化的。 在Python中,定义较为宽松; 有些对象既没有属性也没有方法(第3章中有更多介绍),并且并非所有对象都是可子类化的(第5章中有更多介绍)。 但是,从可以将其分配给变量或将其作为参数传递给函数的意义上说,所有事物都是对象(第4章中将对此进行详细介绍)。 Ruby Docs-从Python转换为Ruby 与Python一样
  • 应该警告新手的Ruby Gotchas是什么? [关闭](What are the Ruby Gotchas a newbie should be warned about? [closed])
    问题 从目前的情况来看,这个问题不适合我们的问答形式。 我们希望答案得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意测验或进一步的讨论。 如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 8年前关闭。 我最近学习了Ruby编程语言,总而言之,它是一门好语言。 但是令我惊讶的是,它并不像我期望的那么简单。 更准确地说,“最小惊喜规则”在我看来并不十分受人尊敬(当然,这是非常主观的)。 例如: x = true and false puts x # displays true! 和著名的: puts "zero is true!" if 0 # zero is true! 您会警告Ruby新手的其他“陷阱”是什么? 回答1 维基百科Ruby陷阱 从文章: 以大写字母开头的名称被视为常量,因此局部变量应以小写字母开头。 字符$和@并不表示Perl中的变量数据类型,而是用作范围解析运算符。 要表示浮点数,必须在后面加上零数字( 99.0 )或显式转换( 99.to_f )。 附加点( 99. )是不够的,因为数字易受方法语法的影响。 非布尔数据的布尔评估是严格的: 0 , ""和[]都评估为true 。 在C中,表达式0 ? 1 : 0 0 ? 1 : 0等于0 (即假)。 但是,在Ruby中,由于所有数字的计算结果均为true ,因此它的结果为1
  • 匿名函数中的Scala返回语句(Scala return statements in anonymous functions)
    问题 为什么匿名函数中的显式return语句(使用return关键字的显式语句)从封闭的命名函数中返回,而不仅仅是从匿名函数本身中返回? 例如,以下程序导致类型错误: def foo: String = { ((x: Integer) => return x) "foo" } 我知道建议避免使用return关键字,但是我对为什么显式和隐式return语句在匿名函数中具有不同的语义感兴趣。 在下面的示例中, m结束执行后,返回语句“幸存”,并且程序导致运行时异常。 如果匿名函数没有从封闭函数返回,则将无法编译该代码。 def main(args: Array[String]) { m(3) } def m: (Integer => Unit) = (x: Integer) => return (y: Integer) => 2 回答1 从形式上讲,返回定义为始终从最近的封闭命名方法返回 return表达式return e必须出现在某些封闭的命名方法或函数的主体内。 源程序中最内部封闭的命名方法或函数f必须具有显式声明的结果类型,并且e的类型必须符合该结果类型。 返回表达式对表达式e求值,并返回其值作为f的结果。 返回表达式之后的任何语句或表达式的求值均被省略。 因此,它在lambda中没有不同的语义。 与常规方法不同的是,通过lambda创建的闭包可以避免对封装方法的调用
  • 为什么String switch语句不支持null大小写?(Why doesn't String switch statement support a null case?)
    问题 我只是想知道为什么Java 7 switch语句不支持null大小写,而是抛出NullPointerException ? 请参见下面的注释行(示例取自有关开关的Java教程文章): { String month = null; switch (month) { case "january": monthNumber = 1; break; case "february": monthNumber = 2; break; case "march": monthNumber = 3; break; //case null: default: monthNumber = 0; break; } return monthNumber; } 这样可以避免在每次使用switch之前都进行null检查的if条件。 回答1 正如damryfbfnetsi在评论中指出的那样,JLS§14.11具有以下注释: 禁止将null用作开关标签的禁令会阻止人们编写永远无法执行的代码。 如果switch表达式是引用类型,即String或装箱的原始类型或枚举类型,则如果表达式在运行时评估为null ,则将发生运行时错误。 根据Java编程语言的设计人员的判断,这比静默跳过整个switch语句或选择在default标签(如果有)之后执行该语句(如果有的话)更好。 (强调我的) 尽管最后一句跳过了使用case
  • 单元测试代码覆盖率-您有100%的覆盖率吗?(Unit testing code coverage - do you have 100% coverage?)
    问题 您的单元测试是否构成100%的代码覆盖率? 是或否,以及为什么或为什么不这样做。 回答1 否,原因如下: 达到100%的覆盖范围确实很昂贵,而90%或95%的覆盖范围并不明显。 即使覆盖率达到100%,您的代码也不是完美的。 看一下这种方法(实际上,它取决于您在谈论的是哪种coverage-分支coverage ,行coverage ……): public static String foo(boolean someCondition) { String bar = null; if (someCondition) { bar = "blabla"; } return bar.trim(); } 和单元测试: assertEquals("blabla", foo(true)); 测试将成功,您的代码覆盖率为100%。 但是,如果添加另一个测试: assertEquals("blabla", foo(false)); 那么您将获得NullPointerException 。 就像您第一次测试达到100%的水平一样,您不一定要编写第二个测试! 通常,我认为关键代码必须覆盖几乎100%,而其他代码可以覆盖85-90% 回答2 对于所有90%覆盖率测试人员: 这样做的问题在于,难以测试的10%的代码也是包含90%的错误的不平凡的代码! 这是我经过多年的TDD经验得出的结论。 毕竟
  • In gradle tasks of type Exec, why do commandLine and executable behave differently?
    Does anyone know why in tasks of type Exec commandline and executable behave differently in terms of inheriting environment vars? For example, I cannot run this Task because Gradle fails to find ruby from my environment: task checkRubyVersionCommandLine(type: Exec) { commandLine 'ruby -v' } Yet this works fine: task checkRubyVersionExecute(type: Exec) { executable = 'ruby' args = ['-v'] } What is commandLine for, or how can I get it to pick up the variables from the shell it is executed from? Why does executable just work?
  • 在Ruby中更改Proc的绑定(Change the binding of a Proc in Ruby)
    问题 我有以下代码: l = lambda { a } def some_function a = 1 end 我只想通过lambda和一个特殊的作用域来访问a ,该作用域已在示例中的some_function内部定义a已经存在的位置,或者稍后不久就在与该作用域相同的范围内: l = lambda { a } a = 1 l.call 然后,我发现在调用l ,它仍在使用其自己的绑定,而不是调用它的新绑定。 然后我尝试将其用作: l.instance_eval do a = 1 call end 但这也失败了,我无法解释原因,这很奇怪。 我知道解决方案之一是使用eval ,在其中可以特殊绑定并在文本中执行一些代码,但是我真的不想这样使用。 而且,我知道它能够使用全局变量或实例变量。 但是,实际上我的代码在更深的嵌入式环境中,因此,如果不是很必要,我不想破坏完整的部分。 我已经在文档中引用了Proc类,并且发现了一个引用Proc上下文的函数名称binding 。 尽管该函数仅提供一种访问其绑定的方法,但不能更改它,除非使用Binding#eval 。 它也评估文本,这正是我不喜欢做的事情。 现在的问题是,我是否有更好(或更优雅)的方式来实现这一目标? 还是使用eval已经是常规方式? 编辑以回复@Andrew: 好的,这是我在编写词法分析器时遇到的一个问题