为什么Ruby中puts minus(start-1)输出空、p minus(start-1)输出nil?
Ruby递归方法输出空与nil问题解答
核心原因:Ruby方法默认返回值规则
Ruby中没有显式写return的方法,默认返回最后一行执行的表达式的求值结果,你遇到的现象完全由这个规则和puts/p的特性共同导致。
方法执行与返回值拆解
我们一步步拆解minus(3)的执行流程:
- 调用
minus(3),首先执行puts 3输出3,判断3>0成立,进入if块执行puts minus(2) - 调用
minus(2),执行puts 2输出2,判断2>0成立,进入if块执行puts minus(1) - 调用
minus(1),执行puts 1输出1,判断1>0成立,进入if块执行puts minus(0) - 调用
minus(0),执行puts 0输出0,判断0>0不成立,if块不执行。此时minus(0)的最后执行表达式是整个if条件判断,条件不成立时if表达式的求值结果为nil,因此minus(0)返回nil - 回到
minus(1)的puts minus(0),等价于puts nil:puts处理nil参数时会输出空换行,且puts本身的返回值永远是nil,因此minus(1)最后执行的表达式puts nil返回nil,minus(1)整体返回nil - 同理
minus(2)、minus(3)的返回值都是nil,调用外层的puts minus(...)都会再输出一个空换行
为什么p输出的是nil
p方法和puts的输出逻辑不同:
puts会调用参数的to_s方法转换为字符串后输出,nil的to_s结果是空字符串,所以puts nil输出空行p会调用参数的inspect方法转换为字符串后输出,nil的inspect结果是字符串"nil",所以替换为p后会直接输出nil
理解偏差说明
你认为递归求值结果应该是2、1、0,是默认把方法的入参当做了返回值,实际上你的方法没有任何地方返回start的值,所有递归调用的最终返回值都是nil,和「输出没有确定值的表达式」没有关系。
你可以修改代码显式返回start验证猜想:
def minus(start) puts start if start > 0 puts minus(start - 1) end # 显式指定返回值为start start end
这时候递归调用的返回值就会是0、1、2,运行后会多输出0、1、2三行内容。
内容的提问来源于stack exchange,提问作者5pacemanSpiff
相关产品推荐
相关产品推荐

