我正在尝试学习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表达式表示法中向我解释:发送关键字的定义吗?
答案 0 :(得分:5)
Ruby建立在“一切都是对象”范式的基础之上。也就是说,包括数字在内的所有内容都是一个对象。
运算符,正如我们在普通的ruby代码中看到的那样,对于各个对象的方法调用只是语法糖:
getPromise(URL+'/olympic/2016/ranking/4')
.then(function(data){
console.log("Response "+JSON.parse(data).Country);
/////////// here
return getPromise(URL+'/iso/country/'+JSON.parse(data).Country);
})
.then(function(data){
console.log("Data "+data)
})
.catch(function(err){
console.log(err)
});
以上就是Ruby如何处理3.14.+(42)
#⇒ 45.14
简短符号。反过来,它可能使用通用Object#send
:
3.14 + 42
后者应理解为:“将带有参数[s](3.14.send :+, 42
#⇒ 45.14
)的消息:+
发送给接收方42
。”
答案 1 :(得分:4)
Ruby是一种面向对象的语言。在面向对象的编程中,我们通过让对象向其他对象发送消息来做事。例如,
foo.bar(baz)
表示self
将消息bar
发送到通过解除引用本地变量foo
获得的对象,将通过解除引用本地变量baz
获得的对象作为参数传递。 (假设foo
和baz
是局部变量。它们也可以是消息发送,因为如果它是self
,Ruby允许你省略接收器,如果它是空的则允许你省略参数列表注意,此时解析器将静态地知道这一点,因为局部变量是在解析时静态创建的。)
在您的代码中,有几个消息发送:
a + b
将消息+
发送给变量a
中的对象,并在变量b
中传递对象
puts add 1, 2
发送消息add
到self
,将文字整数1
和2
作为参数发送,然后将消息puts
发送到self
传递上述消息的结果作为参数发送。
请注意,这与<{1}} / Object#send
无关。这两个是反射方法,允许您在源代码中动态地而不是静态地指定消息。它们通常通过委托AST解释器委托给的同一个私有内部运行时例程在内部实现。 不是反过来。解释器不调用Object#public_send
(否则,您可以通过猴子修补Object#send
在Ruby中自定义方法查找规则,您可以轻松尝试不是这种情况),而是Object#send
和解释器都调用相同的私有内部实现细节。