【问题标题】:Block in Ruby compared to SmalltalkRuby 中的 Block 与 Smalltalk 的比较
【发布时间】:2011-02-28 08:38:54
【问题描述】:

Ruby 中的块是什么意思?它看起来与 Smalltalk 相似,但您不能向它发送消息。

例如在smalltalk中:

[:x | x + 3] value: 3

返回 6。但在 ruby​​ 中:

{|x| x + 3}.call 3

会导致语法错误。

不过,您可以在 ruby​​ 中将消息传递给 lambda:

irb(main):025:0> ->(x){x+3}.call 3
=> 6

那么在 Ruby 中,block 不是 block,而 lambda 是 block?这是真的?我的意思是,ruby lambda 和 smalltalk 块之间有什么区别吗?如果这是真的,那么什么是红宝石块?

更新:

从下面的评论和答案,再加上一些谷歌搜索,我想我 对 Ruby 块有更多的了解。在 Ruby 中,通常一段代码计算一个值,每个值都是一个对象。但是,块不评估值。所以它不是一个对象。相反,它可以充当对象的部分。例如,在 {|x| x + 3} 可以作为对象 proc {|x| 的一部分x + 3 }。

但这确实让我感到困惑。在 smalltalk 中,几乎每个表达式都可以划分为对象(绑定到变量是例外)。似乎在 Ruby 中,还有更多的例外。

【问题讨论】:

标签: ruby smalltalk


【解决方案1】:

Ruby 块不是第一个也是最重要的东西:一个对象。它是一个句法结构,显然也有一个等价的实现——但它不是一个对象,因此不能接收消息。这让你的例子

{|x| x + 3}.call 3

不合语法。 Lambdas, procs - 这些是包装一个块的对象,并且有一个执行该块的call 方法。

因此,块只是一段代码,可以在参数列表之外传递给方法——不多也不少。例如,如果您将它传递给 Proc.new 构造函数,它将包装它并为您提供一个您可以处理的对象:

Proc.new {|x| x + 3}.call 3

【讨论】:

  • 我错误地认为 Ruby 块是我们作为参数传递给方法的某个对象。感谢您的澄清。
  • 因此,如果我理解正确,这也意味着当您将 ruby​​ 块作为参数传递给方法时,VM 会以某种方式将其包装到 Proc.new 中?
  • 我不知道内幕,但我确实认为这是不正确的 - 除非您使用 & 标记这样做。隐式块(无包装):def yield3; yield 3; end; yield3() {|x|puts x}; - 显式 proc(没有通过块):def callprocwith3(func); func.call(3); end; callprocwith3(Proc.new {|x|puts x}) - 转换为 proc(包装一个块):def callblockwith3(&func); func.call(3); end; callblockwith3() {|x|puts x}; - 都做大致相同的事情,但你处理它的方式是不同的。我本可以省略空括号 (),但这样更清楚什么是参数,什么不是参数。
  • @mathk 不,您不能将 ruby​​ 块作为参数传递给方法。并且 Ruby 会报错,而不是自动将块转换为 Proc 实例。真奇怪。但在 Ruby 中,块不是对象。而且您不能将其作为参数传递给方法。我认为最好避免使用“发送块”这个词,因为你不能“发送”它(就像发送一个对象一样)。将块视为某种关键字或语法糖,以将一段代码与其他内容相关联。至少这个考虑让我的大脑更舒服了。
【解决方案2】:

精度:

我什至会说,在 smalltalk 中,甚至绑定都是由对象组成的。 想想 MethodContext。 您实际上在做的是将对象存储在 MethodContext 中。 所以

a := Object new

可以改写为:

thisContext at: 1 put: Object new.

但显然你不会这样写,因为你需要知道是 temps 变量。

【讨论】:

    【解决方案3】:

    Smalltalk 中的块 是一个匿名对象。在语法上,它由 [ ... ] 对分隔。

    当计算时,它会返回最后一个在自身内部计算的表达式,并且它的协议中有很多方法。

    这是来自 Smalltalk 的 Blocks 的 Class cmets(在本例中为 Dolphin Smalltalk 6.03 社区版)

    “块封装了稍后要执行的语句序列。块可以在它们所在的点从封闭的词法范围捕获(或“关闭”)运行时状态,例如临时变量的值已创建。当评估块时,就像在定义它的词法范围内一样执行,除了块可能具有在评估时绑定的参数。块可以作为带有消息的参数传递给其他对象并由这些对象评估在适当的时候,从而形成一个非常强大和通用的“可插拔”机制,这是一个核心特性,它提供了 Smalltalk 的大部分功能。

    相比之下,Ruby 中的块 只是一个参数字符串。它在语法上由 { ... } 对分隔,但它没有自己的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 1970-01-01
      • 2014-08-29
      • 1970-01-01
      • 2016-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多