为什么在命令行中看不到 Return 脚本的 Ruby 值?

Why Can't You See Return Value of a Ruby Script in Command Line?

我的问题是这个问题的后续问题:No return on command line when running Ruby script 因为答案没有提供解释:

获取以下文件,script.rb

def hello(names)
  names.map {|name| "#{name} is awesome!"}
end

hello(["mark", "tony", "scott"])

在命令行上使用 ruby script.rb 执行文件时,不会出现以下函数的 return 值。但是,在 IRB 中测试该方法或通过使用 PRY 进入代码会输出一个明确的 return 值。为什么通过脚本执行看不到 return 值?

P.S。我知道使用 puts 会将代码输出到终端,但我对为什么 return 值不输出感兴趣。

Ruby 脚本不能 return 一个你想要的直接值,Bash shell 的工作方式相同,Bash 函数不能直接 return 一个字符串。您可以 return 一个字符串(带标准输出)并将其分配给变量。

~:$~  cat scr.rb
~:$~  puts "Something here"
~:$~  echo $(ruby ./scr.rb) 
Something here
~:$~  myvar=$(echo $(ruby ./scr.rb))
~:$~  echo $myvar
Something here

因为IRBPry都是REPL's

REPL 代表:read, evaluate, print 循环 。而这正是 PryIRB 正在做的事情。

他们将首先读取您的输入,评估您的代码,打印代码执行的结果,然后重新开始。

当我开始编码时,我自己也曾经有过同样的问题。如果您仔细查看您的代码,您就会明白为什么它不打印任何内容。您实际上并没有在代码中询问它。想象一下有一个数千行的巨大脚本并且您想执行它。如果 ruby myscript.rb 以与 REPL 相同的方式工作,您将获得数百万个毫无意义的输出。

此外,如果您确实希望它以这种方式工作,您可以只在 REPL 会话 (require_relative 'your_script') 中要求脚本,然后如果您调用函数 hello,它将按照您描述的方式工作。

非常简单:Bash(或您使用的任何 shell)和 Ruby 是不同的编程语言。 Bash 对 Ruby 一无所知。它不知道“Ruby return”是什么,它不知道"Ruby array" 是什么,它不知道"Ruby string" 是什么。因此,您根本 不可能 return Ruby 反对 Bash.

事实上,shell 通常只是使用一些操作系统函数来执行 Ruby 脚本(例如经典的 forkexec 或类似 vforkclone)。如果你想以这种方式 return 值,操作系统内核将必须了解已经发明的每一种编程语言的语义以及未来将要发明的每一种编程语言。那是不可行的。

请注意,命令 可以 return shell 的值,即 0 到 255 之间的整数 状态代码 (0 表示 "success",非零表示 "error"),您可以通过调用 Kernel#exit.

来设置 return 值

我可以用ruvalgem。它评估每个语句和 returns 它的值。

$ ruval names.rb
def hello(names)
  names.map {|name| "#{name} is awesome!"}
end
=> hello
hello(["mark", "tony", "scott"])
=> ["mark is awesome!", "tony is awesome!", "scott is awesome!"]