gpt4 book ai didi

functional-programming - 方案:使用fold实现n参数编写

转载 作者:行者123 更新时间:2023-12-04 03:47:06 28 4
gpt4 key购买 nike

我正在尝试在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参数”撰写,我可以这样做:
(define compose-n
(lambda args
(foldr compose identity args)))

((compose-n car cdr cdr) '(1 2 3))
> 3

但这不再保留那个不错的“identity”属性:
((compose-n identity list) 1 2 3)
> procedure identity: expects 1 argument, given 3: 1 2 3

问题是用于foldr命令的“初始”功能。它建立了:
(compose identity (compose list identity))

所以...我不确定最好的解决方法。 “foldl”似乎是自然更好的替代方法,因为我想从左边的“identity”开始,而不是右边的...

但是一个幼稚的实现:
(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

就像,我需要使用“文件夹”,但需要与身份函数...或更好的身份函数不同的“初始”值?显然我在这里很困惑!

我想实现它而不必编写显式的尾递归“循环” ...似乎应该有一种优雅的方法来做到这一点,我只是被困住了。

最佳答案

您可能想尝试this version(使用SRFI 1中的reduce):

(define (compose . fns)
(define (make-chain fn chain)
(lambda args
(call-with-values (lambda () (apply fn args)) chain)))
(reduce make-chain values fns))

这不是火箭科学:当我在#scheme IRC channel 上发布此内容时, Eli指出这是 compose的标准实现。 :-)(作为奖励,它也可以很好地配合您的示例。)

关于functional-programming - 方案:使用fold实现n参数编写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1693181/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com