Ruby puts 使用问题

runup · 2016年03月05日 · 最后由 runup 回复于 2016年03月05日 · 2433 次阅读

我自己在做一段测验,遇到下面的一个 puts 用法问题,代码如下:

def demo
  puts "this is the demo"
end

if false || demo
  puts "succ"
end

上面的代码的执行结果为如下:

#=> this is the demo

修改上面的代码,去除第一方法中的 puts 方法:

def demo
   "this is the demo"
end

if false || demo
  puts "succ"
end

上面的代码的执行结果为如下:

#=> succ

上面的测验是为了说明在 “||” 中,如果前一个字段返回 false,则结果返回后一个字段的值,但是在第一段的代码中,显示了 demo 方法的打印结果,但是为什么 “puts 'succ'” 这个打印结果没有,如果去除了 demo 方法中 puts 方法,那么 “puts 'succ'” 的结果就显示出来了,这是为何?

这个不难理解吧,一试便知:

[1] pry(main)> puts "this is the demo"
this is the demo
=> nil
[2] pry(main)> 
  1. 如果没有显式 return,则返回最后一个语句的返回值。
  2. puts 的返回值是 nil。

#1 楼 @qinfanpeng 应该是我问题没有描述清楚,puts 的用法很简单,如你所呈现的这样,我的问题是在第一段代码中,呈现了 “puts 'this is the demo'” 的值,但是为什么没有呈现 “puts 'succ'” 的结果?

if false || demo
  puts "succ"
end

你这段代码中demo返回值为 nil,条件表达式求值为 false,根本进不了你打印 ‘succ’ 那一行。

#3 楼 @qinfanpeng 一直以为 puts "this is the demo"其中的 “this is the demo” 是 puts 方法的返回值。

#2 楼 @rei 谢谢,补充了知识缺口

#5 楼 @runup 正如 rei 所说,另外我第一次回复里也说明了puts的返回值是 nil

#6 楼 @qinfanpeng

puts "this is the demo"
puts("this is the demo"){} #只有方法的参数,方法体为空,所以方法的返回值是nil

这样的理解是否合适?

#8 楼 @runup 感觉不对劲,puts的职责本身就是输出内容,然后返回 nil。puts "this is the demo"puts("this is the demo")都是对 puts 方法的调用,几乎无异,这里不涉及啥方法体的问题。

#9 楼 @qinfanpeng @rei 感谢指点的,但是其实我还是有困惑。 我翻了基础教程的书,梳理了下方法的返回值包括下面几种:

  1. return 返回值 #因为 return 是结束语句,return 后面的代码都不会被执行。
  2. 如果没有 return,放回值是方法中最后一个表达式子的结果。
  3. 出现在判断语句中。

在我一直的理解里面,方法的返回值和方法的执行结果是同样的事情(事实证明是错的),这也是我困惑的原因,如代码所示:

[1,2].size #=>2  这个方法的返回值是2,方法的执行结果也是2
Kernel.puts("this is the demo")  这个方法的执行结果是“this is the demo,但是返回值是nil

那么,如何对方法的执行结果和返回值做区分?

#10 楼 @runup 我建议不要用 “执行结果” 去理解 puts 在屏幕上打印了字符串,打印这个行为是 puts 执行过程做的事。

#10 楼 @runup 方法执行结果可以理解为方法进行某种操作所引起的变化;方法返回结果则有可能是作者根据需要返回的值,可能与执行结果有关,也可能无关。

另外不是所有方法都有返回值,你比如Java中很多方法返回void其实就是表示无返回值;Ruby中方法之所以一定有返回值,是因为任何语句都可理解为可求职的表达式,所以无论你是否显示return ,总会有返回值;和 Java中的void类似,Ruby里的nil也经常用于表示无有意义的值可返回,此时也就不建议你去使用它的返回值了,比如你这里就是不大妥当的。

也可以了解下 命令查询职责分离模式(Command Query Responsibility Segregation,CQRS)。

@qinfanpeng @rei 谢谢两位的提醒,我会慢慢消化其中的知识点。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号