【问题标题】:Reversing the function usage in compose function在 compose 函数中反转函数用法
【发布时间】:2017-03-05 00:22:11
【问题描述】:

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)

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

【问题讨论】:

  • 您可以将您的函数实现为(define (mycompose . fs) (apply compose (reverse fs)),这样就可以满足您的所有要求,而无需成为宏。
  • 我知道有更好的方法。谢谢。

标签: macros scheme racket


【解决方案1】:

您描述的这种“反向组合”通常称为 thrush,而 the point-free package provides a thrush function 正是您想要的。但是,假设您想自己实现它。好吧,最简单的方法是重用 compose 的现有实现,因为 thrush 只是 compose,但参数颠倒了:

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

事实上,这就是 point-free 包实现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 一样,这将接受多个值并将它们作为多个参数传递给管道中的函数,从而在函数输入和函数输出之间创建良好的对称性。

【讨论】:

    猜你喜欢
    • 2018-08-24
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2013-12-23
    • 2015-12-21
    • 2011-05-30
    相关资源
    最近更新 更多