两个相似定义之间的差异

时间:2015-03-05 17:39:06

标签: scheme

之间有什么区别吗?
(define make-point cons)

(define (make-point x y)
  (cons x y))

一个比另一个更有效,还是完全等同?

4 个答案:

答案 0 :(得分:3)

这里有一些不同的问题。

作为Oscar Lopez points out,一个是间接,一个是包装器。 Christophe De Troyer did some timing并注意到没有优化,间接可以花费两倍于间接的时间。这是因为别名使两个变量的成为相同的函数。当系统评估(cons ...)(make-point ...)时,它会评估变量缺点生产点并获取相同的功能。在间接版本中,生产点缺点不是相同的功能。 制作点是一个函数,可以再次调用缺点。那是两个函数调用而不是一个。所以速度可以成为一个问题,但一个好的优化编译器可能会使差异可以忽略不计。

但是,如果您以后能够更改其中任何一个变量的值,那么非常的重要区别。当您评估(定义制作点kons)时,您评估变量 kons 一次并设置 make-point <的值/ strong>到该评估时获得的一个值。当您评估(定义(生成点x y)(kons x y))时,您将生产点的值设置为新函数。每次调用该函数时,都会计算变量 kons ,因此会反映对变量 kons 的任何更改。我们来看一个例子:

(define (kons x y)
  (cons x y))

(display (kons 1 2))
;=> (1 . 2)

现在,让我们写一个间接和别名:

(define (kons-indirection x y)
  (kons x y))

(define kons-alias kons)

现在产生相同的输出:

(display (kons-indirection 1 2))
;=> (1 . 2)

(display (kons-alias 1 2))
;=> (1 . 2)

现在让我们重新定义 kons 函数:

(set! kons (lambda (x y) (cons y x))) ; "backwards" cons

围绕 kons 包装的函数,即间接,看到 kons 的新值,但别名确实如此不:

(display (kons-indirection 1 2)) 
;=> (2 . 1)  ; NEW value of kons

(display (kons-alias 1 2))
;=> (1 . 2)  ; OLD value of kons

答案 1 :(得分:2)

从语义上讲,它们相当于:make-pointcons两个元素。但第一个是创建cons函数的别名,而第二个是定义一个简单调用cons的新函数,因此它会稍微更慢,但额外的开销可以忽略不计,如果编译器是好的,甚至不存在。

答案 2 :(得分:2)

对于cons,您的两个版本之间没有区别。

对于像+这样的可变参数程序,+(lambda (x y) (+ x y))之间的区别在于后者限制了仅使用两个参数调用过程。

答案 3 :(得分:2)

出于好奇,我做了一个快速而肮脏的实验。似乎只是别名cons的速度几乎是将其包装在新函数中的两倍。

(define mk-point cons)

(define (make-point x y)
  (cons x y))

(let ((start (current-inexact-milliseconds)))
(let loop ((n 100000000))
      (mk-point 10 10)
      (if (> n 0)
          (loop (- n 1))
          (- (current-inexact-milliseconds) start))))
(let ((start (current-inexact-milliseconds)))
(let loop ((n 100000000))
      (make-point 10 10)
      (if (> n 0)
          (loop (- n 1))
          (- (current-inexact-milliseconds) start))))


;;; Result    
4141.373046875
6241.93212890625
> 

在Xubuntu上的DrRacket 5.3.6中。