你是完全正确的:计算一个什么都不返回的函数是没有意义的——如果你在谈论数学函数。但与许多数学概念一样,“函数”在许多编程语言中仅与数学函数相关,但行为或多或少有细微的不同。
我相信最好用一种不会弄错的语言来解释它:Haskell就是这样一种语言。那是一种纯粹的函数式语言,这意味着 Haskell 函数也是一个数学函数。事实上,您可以编写更数学风格的 Haskell 函数,例如
my_tan(x) = sin(x)/cos(x) -- or (preferred): tan' x = sin x / cos x
比在 C++ 中
double my_tan(double x) { return sin(x)/cos(x); }
但是,在计算机程序中,您不只是想计算函数,对吗?您还想完成一些事情,例如在屏幕上显示某些内容,通过网络发送数据,从传感器读取值等。在 Haskell 中,这些事情与纯函数很好地分开,它们都在所谓的IO
monad中起作用. 例如,putStrLn
打印一行字符的函数有 type String -> IO()
。意思是,它接受 aString
作为它的参数并返回一个操作,当从函数IO
调用时打印出该字符串,没有其他内容(括号大致是C++ 中的内容)。main
()
void
这种做 IO 的方式有很多好处,但大多数编程语言都比较草率:它们允许所有函数做 IO,也可以改变程序的内部状态。因此,在 C++ 中,您可以简单地拥有一个 function void putStrLn(std::string)
,它还“返回”一个打印字符串的 IO 操作,但没有明确告诉您。这样做的好处是,在考虑 IO monad 的实际含义时,您不需要在大脑中打多个结(它相当迂回)。此外,如果您能够真正告诉机器“现在就执行这个过程序列!”,那么许多算法都可以运行得更快。而不是仅仅在 IO monad 中询问一些计算的结果。