在compose函数中反转函数用法

时间:2017-03-05 00:22:12

标签: macros scheme racket

compose函数首先应用最后一个函数,即它以相反的顺序应用发送的函数。例如:

((compose sqrt add1) 8)

上面将添加1到8,然后找到9的sqrt。

我想创建一个mycompose函数,它首先应用第一个发送的函数,然后应用第二个,第三个等等。因此,在上面的示例中,首先需要应用sqrt,然后再应用add1。我可以管理以下内容:

(define (mycompose L arg)
  (let loop ((L L)
             (res arg))
    (cond
      [(empty? L) res]
      [else (loop (rest L) ((car L) res))])))

(mycompose (list sqrt add1) 8)

我相信有更好的方法。特别是,上面可以使用宏来实现,还允许多个参数轮流发送到每个函数?

1 个答案:

答案 0 :(得分:3)

您描述的这种“逆向组合”通常称为画眉the point-free package provides a thrush function可以完全按照您的要求进行操作。但是,假设你想自己实现它。好吧,最简单的方法是重用compose的现有实现,因为thrush只是compose且反转的参数:

(define (thrush . fs)
  (apply compose (reverse fs))

事实上,这是无点程序包实现thrush的方式。不过,这可能让您感到不满意,因为您不知道compose是如何实现的。好吧,幸运的是,我们可以通过简单的折叠从头开始实现thrush

(define (thrush . fs)
  (for/fold ([f values])
            ([g (in-list fs)])
    (λ args (call-with-values (thunk (apply f args)) g))))

这里真正的技巧是使用call-with-values,它可以正确处理返回多个值的函数。就像Racket的compose一样,这将接受多个值并将它们作为多个参数传递给管道中的函数,从而在函数输入和函数输出之间创建良好的对称性。