在Ruby 2.7和Ruby 3.1中,无论是否有%符号,此脚本都执行相同的操作:
def count(str)
state = :start
tbr = []
str.each_char do
% %case state
when :start
tbr << 0
% %state = :symbol
% when :symbol
tbr << 1
% % state = :start
% end
end
tbr
end
p count("Foobar")
这是如何解析的?你可以添加更多的%或删除一些,它仍然会工作,但不是任何组合。我发现这个例子通过试验和错误。
我在教别人Ruby的时候,在他们的脚本运行正常后才注意到他们在空白处有一个随机的%,我把它推得更远一点,看看它能接受多少。
1条答案
按热度按时间jqjz2hbq1#
语法
百分比字符串型
这是一个接收消息
%
的 * 百分比字符串型 *。%
字符如果 * 开始分隔符 * 是
<
、[
、(
或{
之一,则 * 结束分隔符 * 必须是对应的>
、]
、)
或}
。否则,* 开始分隔符 * 可以是任意字符,而 * 结束分隔符 * 必须是同一字符。所以,
(that是,
%
空间)是一个 * 百分比字符串型 *,以空格作为分隔符,没有内容。即,它等效于
""
。操作员消息发送
a % b
相当于
即,将消息
%
发送到表达式a
的求值结果,将表达式b
的求值结果作为单个自变量传递。也就是说
(大致)相当于
参数列表
那么,
b
是什么呢?它是%
运算符后面的表达式(不要与 Percent String Literal 的%
符号混淆)。整个代码(大致)相当于:
AST编号
您可以通过询问Ruby自己来解决这个问题:
这里一些有趣的地方是
(id: 12, line: 5, location: (5,0)-(5,3))
处的节点,它是第一个字符串文字,以及(id: 48, line: 5, location: (5,0)-(12,7))
,它是发送的第一个%
消息:注意:这只是获取解析树的最简单的可能方法,不幸的是,它包含了很多内部细节,而这些细节与弄清楚到底发生了什么并不真正相关。还有其他方法,如
parser
gem或它的同伴ast
,它们产生了更可读的结果:语义
到目前为止,我们所讨论的都是 Syntax,即代码的语法结构。但它 * 意味着 * 什么呢?
方法
String#%
执行 String Formatting a la C的printf
family of functions。但是,由于格式字符串(%
消息的接收方)是空字符串,因此消息发送的结果也是空字符串,因为没有要格式化的内容。如果Ruby是一种纯函数式的、懒惰的、非严格的语言,那么结果将等价于:
这反过来又相当于
它相当于
它相当于
它相当于
它相当于
它相当于
很明显,这不是正在发生的事情,原因是Ruby * 不是 * 一种纯函数的、懒惰的、非严格的语言。虽然传递给
%
消息send的参数 * 与消息send的结果无关 *,但它们仍然被求值(因为Ruby是严格和渴望的),而且它们有副作用(因为Ruby不是纯功能性的),也就是说,它们重新赋值变量和改变tbr
结果数组的副作用仍然会执行。如果这段代码是用更像Ruby的风格编写的,变异和副作用更少,而不是使用函数转换,那么用空字符串任意替换结果会立即破坏它。这里没有效果的唯一原因是大量使用了副作用和变异。