换句话说,是什么让语言变得纯粹?
例如,Smalltalk 被认为是一种纯面向对象的语言。Haskell 和 Lisp 可以说是纯函数式语言。
当我们说纯粹时,这是否意味着它们无法使用其他编程范式(这与事实相去甚远),还是意味着它们被设计用于“纯粹”的 X 范式?
换句话说,是什么让语言变得纯粹?
例如,Smalltalk 被认为是一种纯面向对象的语言。Haskell 和 Lisp 可以说是纯函数式语言。
当我们说纯粹时,这是否意味着它们无法使用其他编程范式(这与事实相去甚远),还是意味着它们被设计用于“纯粹”的 X 范式?
纯这个词在不同的语境中有不同的含义。
当人们谈论 Haskell 是一种纯语言时,他们的意思是它具有引用透明性。也就是说,您可以用它的值替换任何表达式,而不会改变程序的含义。例如,在 Haskell 中:
square :: Int -> Int
square x = x * x
main = print (square 4)
表达式square 4
可以用它的值 (16) 替换,而不会改变程序的含义。另一方面,在这段 Java 代码中:
public int square(int x) {
System.out.println("Done!");
return (x*x);
}
public static void main(String [] args) {
System.out.println(square(4));
}
您不能square(4)
用它的值 (16) 替换,因为它会改变程序的含义 - 它不再打印Done!
到标准输出。在 Haskell 中,函数不可能有副作用,例如打印到标准输出或更改内存位置,因此强制执行引用透明性。
请注意,有了 pure 的含义,Lisp不是纯函数式语言,因为它的函数可能会产生副作用(如果你想挑剔的话,Haskell 不是纯函数式语言,因为存在unsafePerformIO
,但每个人都知道你如果您曾经使用过该功能,则被委托给地狱的更恶劣的圈子之一)。
当然,在不纯的语言中采用纯风格总是有可能的,许多程序员会这样做是为了更容易推理他们的程序。只是编译器没有强制执行引用透明性,因为它是纯语言。
纯函数式语言的示例包括Haskell、Clean和Miranda。不纯函数式语言的示例包括OCaml、F#和Scheme。
当人们谈论 Smalltalk 或 Ruby 是一种纯粹的面向对象语言时,他们的意思是对象和原始值之间没有区别。在 Smalltalk 和 Ruby 中,整数、布尔值和字符等值也是对象,因为它们可以接收消息 (Smalltalk) 或具有方法 (Ruby)。例如,你可以做
1.to_s
在Ruby中,即调用将整数1
转换为字符串的方法。将此与像 Java 这样的“不纯”OO 语言进行比较,其中有对象(它们是类的实例,可以有方法等)和原始值(例如int
, double
, bool
, 不能有方法)。
当 OO 语言是纯粹的时,人们常说“一切都是对象”,严格来说这不是真的(例如,if 语句不是对象),但说“每个值都是对象”是正确的”。
函数式语言中的“纯”一词可以说是“无状态”,输出不依赖于状态。
对于命令式语言,您分配 x := 0,但您可以稍后重新分配变量 x 的值。x 的值取决于当前状态。
但是对于纯函数式语言,如果 f(x) = 1,那么结果将始终为 1。