Ruby 的 AST 中的 'send' 关键字是什么意思?
What is the meaning of the 'send' keyword in Ruby's AST?
我正在尝试学习 Ruby 词法分析器和解析器 (whitequark parser),以进一步了解从 Ruby 脚本进一步生成机器代码的过程。
在解析以下 Ruby 代码字符串时。
def add(a, b)
return a + b
end
puts add 1, 2
它导致以下 S 表达式符号。
s(:begin,
s(:def, :add,
s(:args,
s(:arg, :a),
s(:arg, :b)),
s(:return,
s(:send,
s(:lvar, :a), :+,
s(:lvar, :b)))),
s(:send, nil, :puts,
s(:send, nil, :add,
s(:int, 1),
s(:int, 3))))
谁能解释一下结果 S 表达式符号中 :send 关键字的定义?
Ruby 建立在“一切皆对象”范式之上。也就是说,包括数字在内的一切都是对象。
运算符,正如我们在普通 ruby 代码中看到的那样,只不过是一个语法糖,用于各个对象的方法调用:
3.14.+(42)
#⇒ 45.14
以上就是Ruby如何对待3.14 + 42
简写法。反过来,它可以使用泛型 Object#send
:
编写
3.14.send :+, 42
#⇒ 45.14
后者应理解为:“将带有参数[s] (42
) 的消息:+
发送给接收者3.14
。”
Ruby 是一种面向对象的语言。在面向对象的编程中,我们通过让对象向其他对象发送消息来做事。例如,
foo.bar(baz)
表示self
向解引用局部变量foo
得到的对象发送消息bar
,将解引用局部变量baz
得到的对象作为争论。 (假设 foo
和 baz
是局部变量。它们也可以是消息发送,因为 Ruby 允许你省略接收者,如果它是 self
和参数列表如果它是空的。请注意,这将在此时被解析器静态知道,但是,因为局部变量是在解析时静态创建的。)
在您的代码中,有几个消息发送:
a + b
将消息 +
发送到变量 a
中的对象,传递变量 b
中的对象
puts add 1, 2
发送消息 add
到 self
将文字整数 1
和 2
作为参数传递,然后将消息 puts
发送到 self
将上述消息发送的结果作为参数传递。
请注意,这与 Object#send
/Object#public_send
没有任何关系。这两个是反射方法,允许您动态指定消息而不是在源代码中静态指定消息。它们通常通过委托给 AST 解释器委托给的相同私有内部运行时例程来在内部实现。 不是相反。解释器不调用Object#send
(否则,您可以通过猴子修补Object#send
自定义Ruby中的方法查找规则,您可以轻松尝试情况并非如此),而是 Object#send
和解释器都调用相同的私有内部实现细节。
我正在尝试学习 Ruby 词法分析器和解析器 (whitequark parser),以进一步了解从 Ruby 脚本进一步生成机器代码的过程。
在解析以下 Ruby 代码字符串时。
def add(a, b)
return a + b
end
puts add 1, 2
它导致以下 S 表达式符号。
s(:begin,
s(:def, :add,
s(:args,
s(:arg, :a),
s(:arg, :b)),
s(:return,
s(:send,
s(:lvar, :a), :+,
s(:lvar, :b)))),
s(:send, nil, :puts,
s(:send, nil, :add,
s(:int, 1),
s(:int, 3))))
谁能解释一下结果 S 表达式符号中 :send 关键字的定义?
Ruby 建立在“一切皆对象”范式之上。也就是说,包括数字在内的一切都是对象。
运算符,正如我们在普通 ruby 代码中看到的那样,只不过是一个语法糖,用于各个对象的方法调用:
3.14.+(42)
#⇒ 45.14
以上就是Ruby如何对待3.14 + 42
简写法。反过来,它可以使用泛型 Object#send
:
3.14.send :+, 42
#⇒ 45.14
后者应理解为:“将带有参数[s] (42
) 的消息:+
发送给接收者3.14
。”
Ruby 是一种面向对象的语言。在面向对象的编程中,我们通过让对象向其他对象发送消息来做事。例如,
foo.bar(baz)
表示self
向解引用局部变量foo
得到的对象发送消息bar
,将解引用局部变量baz
得到的对象作为争论。 (假设 foo
和 baz
是局部变量。它们也可以是消息发送,因为 Ruby 允许你省略接收者,如果它是 self
和参数列表如果它是空的。请注意,这将在此时被解析器静态知道,但是,因为局部变量是在解析时静态创建的。)
在您的代码中,有几个消息发送:
a + b
将消息 +
发送到变量 a
中的对象,传递变量 b
puts add 1, 2
发送消息 add
到 self
将文字整数 1
和 2
作为参数传递,然后将消息 puts
发送到 self
将上述消息发送的结果作为参数传递。
请注意,这与 Object#send
/Object#public_send
没有任何关系。这两个是反射方法,允许您动态指定消息而不是在源代码中静态指定消息。它们通常通过委托给 AST 解释器委托给的相同私有内部运行时例程来在内部实现。 不是相反。解释器不调用Object#send
(否则,您可以通过猴子修补Object#send
自定义Ruby中的方法查找规则,您可以轻松尝试情况并非如此),而是 Object#send
和解释器都调用相同的私有内部实现细节。