我正在使用SICP讲座和文字来了解我自己的方案。我正在看一个练习,上面写着“表达式E的应用是形式的表达式(E E1,... En)。这包括n = 0的情况,对应于表达式(E)。一个Curried的应用程序E是E的应用或E的Curried应用的应用。“
(编辑:我纠正了上面的引用......我最初错误地引用了这个定义。)
任务是定义一个Curried应用程序,该程序的计算结果为3
(define foo1
(lambda (x)
(* x x)))
我真的不明白这个想法,阅读关于Curriying的维基百科条目并没有真正帮助。
任何人都可以帮助更明确地解释这里要求的内容吗?
实际上,即使给我这个问题的答案也会有所帮助,因为在这之后还有五个要解决。 ......我只是没有得到基本的想法。
补充:即使在Brian Campbell冗长的解释之后,我仍然有点失落。
(foo1 (sqrt 3)))
是否被视为foo的应用程序,因此是foo的curry应用程序?
似乎太简单了,但也许......
在DrScheme中键入(((foo1 2 )) 2)
会出现以下错误(我有点期待)
procedure application: expected procedure, given: 4 (no arguments)
重新阅读What is Currying?后,我明白我也可以将foo1重新定义为:
(define (foo1 a)
(lambda (b)
(* a b)))
然后我可以输入
((foo1 3 ) 4)
12
但是这并不能让我更接近于将3作为输出,而且看起来这并不是真正的原始foo1,它只是重新定义它。
该死的,20年的C编程还没有为此做好准备。 :-): - )
答案 0 :(得分:7)
我会为你打破这个定义,有一些例子可以帮助你弄清楚发生了什么。
表达式E的应用是形式(E E1 ... En)的表达。
以下是应用程序的示例:
(foo 1 2) ; This is an application of foo
(bar 1) ; This is an application of bar
这包括n = 0的情况,对应于表达式(E)。
(baz) ; This is an application of baz
E的Curried申请是E的申请或E Cur的Curried申请的申请............
这是你错误引用的那个;以上是我在网上找到的问题集的定义。
这个定义有两半。从第一个开始:
E的Curried应用是E的应用
(foo 1 2) ; (1) A Curried application of foo, since it is an application of foo
(bar 1) ; (2) A Curried application of bar, since it is an application of bar
(baz) ; (3) A Curried application of baz, since it is an application of baz
或者Cur的应用程序的应用
((foo 1 2) 3) ; (4) A Curried application of foo, since it is an application of (1)
((bar 1)) ; (5) A Curried application of bar, since it is an application of (2)
((baz) 1 2) ; (6) A Curried application of baz, since it is an application of (3)
(((foo 1 2) 3)) ; A Curried application of foo, since it is an application of (4)
(((bar 1)) 2) ; A Curried application of bar, since it is an application of (5)
; etc...
这能为您提供入门所需的帮助吗?
修改:是的,(foo1 (sqrt 3))
是foo1
的Curried应用程序;就这么简单。这不是一个非常好的问题,因为在许多实现中你实际上会得到2.9999999999999996或类似的东西;除非您的Scheme有某种精确algebraic numbers的表示,否则不可能有一个将返回3的值。
你的第二个例子确实是一个错误。 foo1
返回一个无效的整数。它只是后面的一些示例,其中函数应用程序的应用程序的递归情况是有效的。例如,查看foo3
。
编辑2 :我刚刚检查了SICP,看起来这里的概念直到1.3节才解释,而这个分配只提到了1.1节。如果你还没有,我建议你仔细阅读1.3节。
答案 1 :(得分:3)
Currying需要一个功能并提供 接受单一的新功能 参数,并返回指定的 函数及其第一个参数集 那个论点。
答案 2 :(得分:3)
我不认为詹姆斯的咖喱功能是正确的 - 当我在我的方案解释器中尝试它时会出现语法错误。
以下是我一直使用的“咖喱”的实现:
> (define curry (lambda (f . c) (lambda x (apply f (append c x)))))
> ((curry list 5 4) 3 2)
(5 4 3 2)
注意,它也适用于为函数计算多个参数。
还有一个人写过的宏,当你用不充分的论据来称呼你时,你可以编写隐含咖喱的函数:http://www.engr.uconn.edu/~jeffm/Papers/curry.html
答案 3 :(得分:3)
您获得的大部分答案都是“部分评估”的例子。要在Scheme中进行真正的currying,你需要语法帮助。像这样:
(define-syntax curry
(syntax-rules ()
((_ (a) body ...)
(lambda (a) body ...))
((_ (a b ...) body ...)
(lambda (a) (curry (b ...) body ...)))))
然后将其用作:
> (define adding-n3 (curry (a b c) (+ a b c)))
> (define adding-n2-to-100 (adding-n3 100))
> ((adding-n2-to-100) 1) 10)
111
> (adding-n3 1)
#<procedure>
> ((adding-n3 1) 10)
#<procedure>
答案 4 :(得分:2)
我觉得你太困惑了。卷曲函数需要F(a1,a2,... aN)类型的函数并将其转换为F(a1),它返回一个取a2的函数(返回一个取a3 ...等的函数)< / p>
所以如果你有:
(define F (lambda (a b) (+ a b)))
(F 1 2) ;; ==> 3
你可以用它来制作类似如下的东西:
(define F (lambda (a) (lambda (b) (+ a b))))
((F 1) 2) ;; ==> 3
就你的具体问题而言,这似乎很令人困惑。
(foo1 (sqrt 3))
似乎合适。我建议暂时离开并阅读本书的更多内容。
你实际上可以为你做一个简单的咖喱功能:
(define (curry f x) (lambda (y) (apply f (cons x y))))
(curry = 0) ;; a function that returns true if input is zero
答案 5 :(得分:0)
根据您的Scheme实现,可能有一些实用程序可以从错误/异常中恢复,例如,在Chicken Scheme中,有condition-case
。
(condition-case (func)
((exn) (print "error")))
我们可以定义一个函数,它接受任意数量的元素的函数并返回curryed形式:
(define curry
(lambda (func . args)
(condition-case (apply func args)
((exn)
(lambda plus
(apply curry func (append args plus)))))]))))
这有点难看,因为如果你一次使用太多的参数,你将永远不会得到最终的结果,但是这会将任何函数变成curryed形式。