在函数式编程中,我们倾向于区分数据和函数,但是有什么区别呢?
如果我考虑一个常量,我可以将其视为一个函数,它只返回相同的值:
(def x 5)
那么数据和函数有什么区别呢?我看不出有什么区别。
数据是一个值(具有特定类型)。
例如,
5
是Integer
类型的值,"abc"
是String
类型的值。诸如 [5 "abc"]
之类的复合值的类型为 Vector
。
相同类型的两个数据值始终可以进行比较相等。
数据永远不会被执行。也就是说,控制线程(又名程序计数器或 PC)永远不会进入数据结构。
函数的唯一类型是“代码”。
函数在执行时产生一个值(具有特定类型)(可能带有参数)。
执行意味着控制线程进入代码数据结构。 那里遇到的代码和数据值可以完全控制发生的任何副作用以及返回值。
编译和解释代码都会产生相同的结果。它们之间的唯一区别是在复杂性与速度之间进行权衡的实现细节。
(eval ...)
特殊形式接受
数据作为输入并返回函数作为输出。返回的函数可以被执行(即调用),因此控制线程进入该函数。
宏最好被视为嵌入代码中的编译器扩展,并且不影响数据与代码的区别。
; A Clojure Var pointing to the value 5
(def five 5)
; A Clojure Var pointing to a function that always returns the value 5
(def ->five (fn [& args] 5))
然后使用这 2 个变量:
five => 5
(->five) => 5
括号使一切变得不同。
另请参阅:
lambda
和数据之间有什么区别 - 如果
lambda
本身实际上也只是一个必须执行的数据结构......)在同形语言中,数据可以变成 lambda
(如果它包含
lambda
的指令),反之亦然。所以也许,区别仅在于它们的类型(函数与任何其他数据结构或原始数据类型)。
原来的问题
函数和数据有什么区别?
是否首先隐含地询问
存在差异,询问函数和数据之间是否存在差异相当于询问您是否可以仅使用函数来完成“通常”通过使用数据完成的事情,反之亦然。 所以答案包含在
§2.1.3 数据意味着什么?(我相信,正如 user5536315 所暗示的那样),作者指出您可以仅使用函数来实现数据结构。 例如,
cons
是允许您创建一对
数据:的函数
(define p (cons 3 7))
(display p)
; (3 . 7)
(display (car p))
; 3
(display (cdr p))
; 7
但是“pair”只是“某物”的概念,其行为类似于通过使用两个参数调用
const
获得的对象;只要“某物”满足这些要求,它就是一对,无论你如何实现这一点。
所以你可以通过重新定义其接口函数来定义你自己的pair:(define (cons a b) ; override builtin cons
(define (pair i)
(cond ((= i 0) a)
((= i 1) b)
(else (error "caio"))))
pair)
(define (car p) ; override builtin car
(p 0))
(define (cdr p) ; override builtin cdr
(p 1))
pair
返回的
cons
function是“pair”,因为它实现了“pair”的接口,即你可以在其上调用
car
和cdr
,所以它的工作方式就像原始数据,
(define p (cons 3 7))
(display p)
; #<procedure impl (a)>
(display (car p))
; 3
(display (cdr p))
; 7
其中输出
#<procedure impl (a)>
与之前不同,因为使用内置
(cons 3 7)
的 cons
为您提供了 REPL 知道如何打印的 data结构,而使用我们新的
cons
则为您提供了 functionREPL 不知道如何打印,所以它打印
#<procedure impl (a)>
。