当我执行以下操作时会发生什么?
(define ((func x) y)
(if (zero? y)
((func x) 1)
12))
我知道我可以这样做:
(define curried (func 5))
现在我可以使用咖喱。我很好奇的是函数的定义。是行吗
((func x) 1)
用x作为参数创建一个新的lambda,然后在1上调用它?或者它比那更聪明,它只是重新使用现有的。 (例如,如果我执行(curried 0)
,则((func x) 1)
行将等同于(curried 1)
- PLAI Scheme是否执行此操作?)
答案 0 :(得分:8)
在Scheme标准中,指定了
(define (f x) 42) is short for (define f (lambda (x) 42)) .
自然(非标准)概括意味着:
(define ((f x) y) (list x y)) is short for (define (f x) (lambda (y) (list x y)))
which is short for (define f (lambda (x) (lambda (y) (list x y))))
为了测试它,让我们试一下DrScheme中的例子
欢迎使用DrScheme,版本4.1.3.3-svn5dec2008 [3m]。 语言:模块;内存限制:384兆字节。
(define((f x)y)(list x y)) (f 1)
((f 1)2) (1 2)
如果我们命名临时值,可能更容易看到会发生什么:
(定义h(f 1)) (h 2) (1 2) (h 3) (1 3)
由于“PLAI Scheme”在DrScheme中实现,我相信它继承了这种快捷方式。
答案 1 :(得分:2)
自从我使用计划以来已经太久了,但您可能会发现this article很有帮助。 它描述了两个宏的实现,c-lambda和c-define,它们允许对lambda表达式进行隐式curried定义。
答案 2 :(得分:0)
我发现以下代码与运行时间相同:
原始来源:
(define ((substitute lv value) e)
(cond [(LogicVar? e)
(type-case LogicVar e
[lv-any (id) (if (symbol=? id (lv-any-id lv))
value
e)]
[lv-cons (f r)
(lv-cons ((substitute lv value) f)
((substitute lv value) r))])]
[(cons? e)
(cons ((substitute lv value) (car e))
((substitute lv value) (cdr e)))]
[else e]))
尝试优化:
(define (substitute lv value)
(local ([define inner
(lambda (e)
(cond [(LogicVar? e)
(type-case LogicVar e
[lv-any (id) (if (symbol=? id (lv-any-id lv))
value
e)]
[lv-cons (f r)
(lv-cons (inner f)
(inner r))])]
[(cons? e)
(cons (inner (car e))
(inner (cdr e)))]
[else e]))])
inner))
大量使用此功能的代码(多次,不只是一次)在两个版本的1800毫秒运行。更有趣的是,这个版本(我对正在发生的事情的可视化):
(define (substitute lv value)
(local ([define inner
(lambda (e)
(cond [(LogicVar? e)
(type-case LogicVar e
[lv-any (id) (if (symbol=? id (lv-any-id lv))
value
e)]
[lv-cons (f r)
(lv-cons ((substitute lv value) f)
((substitute lv value) r))])]
[(cons? e)
(cons ((substitute lv value) (car e))
((substitute lv value) (cdr e)))]
[else e]))])
inner))
运行时间为2000毫秒。因此,如果替换内部的替换调用每个都创建一个lambda,那么肯定会减速,但看起来情况并非快捷符号的情况。