为何调用如下定义的f()报void value expression错误,g()却正常?
嗨,这个问题其实是Ruby语法解析里一个很典型的小坑,核心在于**return关键字的绑定逻辑**和运算符优先级的碰撞!让我给你掰扯清楚:
先看两个方法的解析差异:
关于f(n)的报错原因
你写的def f(n) return n == 0 or n == 1 end,Ruby会按照它的语法规则把这行代码解析成:
(return n == 0) or (n == 1)
这里的问题出在:return语句本身是一个void表达式——它的作用是让方法退出并返回指定值,但return这个语句本身没有可被逻辑运算符(比如or)使用的“有效计算值”。当你用or去连接return语句和另一个表达式时,Ruby就会报错,因为or需要两边都是能产生实际值的表达式,而return语句的结果是void,根本没法参与逻辑运算。
举个实际调用的例子:当你调用f(2)时,Ruby先尝试执行return false(因为2==0是false),这已经让方法退出了,但同时它还要处理后面的or (2==1),这时候or左边是void值,直接触发“void value expression”错误。
关于g(n)的正常运行
而def g(n) return (n == 0 or n == 1) end里的括号起到了关键作用!括号改变了Ruby的解析顺序:它会先计算括号里的整个逻辑表达式n == 0 or n == 1,得到一个标准的布尔值(true或false),然后把这个值作为return的参数返回。整个过程中return只处理一个完整的、有实际值的表达式,完全没有涉及到用逻辑运算符连接void语句的情况,所以运行起来毫无问题。
简单总结一下:没有括号时,return只绑定了后面第一个子表达式,剩下的逻辑运算部分试图和return语句本身做运算,导致报错;加了括号后,return绑定的是整个逻辑表达式的结果,自然正常。
内容的提问来源于stack exchange,提问作者fstang

