【发布时间】:2010-12-14 04:07:11
【问题描述】:
我正在尝试在 Scheme 中找到多参数“compose”的“最佳”实现(我知道它在某些实现中是内置的,但目前假设我使用的是没有这个的) .
对于 2 参数 compose 函数,我有这个:
(define compose
(lambda (f g)
(lambda x
(f (apply g x)))))
这样做的好处是,如果最右边的函数需要额外的参数,这些仍然可以通过组合函数传递。这具有令人愉悦的特性,即在某物之上组合身份函数不会改变函数。
例如:
(define identity
(lambda (x) x))
(define list1
(compose identity list))
(define list2
(compose identity list1))
(list2 1 2 3)
> (1 2 3)
现在要做一个“n-argument”组合我可以这样做:
(define compose-n
(lambda args
(foldr compose identity args)))
((compose-n car cdr cdr) '(1 2 3))
> 3
但这不再保留那个漂亮的“身份”属性:
((compose-n identity list) 1 2 3)
> procedure identity: expects 1 argument, given 3: 1 2 3
问题是用于 foldr 命令的“初始”函数。它已经建成:
(compose identity (compose list identity))
所以...我不确定解决这个问题的最佳方法。 “foldl”似乎是自然更好的选择,因为我希望它以 left 上的“identity”而不是 right...
但是一个幼稚的实现:
(define compose-n
(lambda args
(foldl compose identity args)))
哪个有效(必须颠倒功能应用的顺序):
((compose-n cdr cdr car) '(1 2 3))
> 3
没有解决问题,因为现在我不得不把标识函数放在左边!
((compose-n cdr cdr car) '(1 2 3))
> procedure identity: expects 1 argument, given 3: 1 2 3
就像,我需要使用“foldr”,但需要一些不同于标识函数的“初始”值......还是更好的标识函数?显然我在这里很困惑!
我想实现它 不必编写显式的尾递归“循环”......似乎应该有一种优雅的方式来做到这一点,我只是卡住了。
【问题讨论】:
标签: functional-programming scheme