【问题标题】:Currying for map in Scheme在 Scheme 中为地图柯里化
【发布时间】:2011-11-02 12:28:21
【问题描述】:

我了解 Haskell 语法。

我想 curry(部分应用)一个名为“play-note”的函数,并“手动”传递一个参数,第二个参数带有地图。

如果我可以用 Haskell 编写它,我会说:

playNote :: Time -> Instrument -> Int -> Int -> Int -> Int -> Music -- made up, but just to give you an idea

notes = [46, 47, 35, 74]  
loopGo = True

loop time = do mapM_ (playNote' time) notes 
               if loopGo then (loop (time+(second/2))) else return () -- time element removed
playNote' time pitch = playNote time drums pitch 80 11025 9 -- ignore extra args

在Scheme中,这是我所拥有的最好的:

(define notes '(46 47 35 74))  
(define *loop-go* #t)
(define play-note-prime  
   (lambda (time2)  
      (lambda (pitch)  
         (play-note time2 drums pitch 80 11025 9))))  ; drums is another variable
(define loop  
   (lambda (time)  
      (map (play-note-prime time) notes)  
      (if *loop-go*  
          (callback (+ time (/ *second* 2)) 'loop (+ time (/ second 2)))))) ; time element is more sophisticated here

Scheme 版本“编译”,但没有按照我的预期执行(咖喱第一个参数,然后是第二个)。帮助?谢谢!

编辑:
我的问题的本质是无法定义一个接受两个参数的函数,以使以下代码产生正确的结果:

map ({some function} {some value; argument 1}) {some list; each element will be an argument 2}

【问题讨论】:

  • 如果你提供一个例子来说明你是如何调用循环的,以及你在哪里传递时间和音高,我认为更容易看出这个程序与你的期望不符。
  • @Davorak:尊敬的,我认为这可能会引起更多的混乱:)。我已经澄清了问题的“核心”是什么。
  • 部分函数应用程序没有柯里化,我认为你想要前者,因为如果你柯里化播放笔记函数,那么根据定义它只能接受一个参数并返回一个接受一个参数的函数,所以会有不要让你使用 map 传递第二个参数

标签: haskell functional-programming scheme currying


【解决方案1】:

除非我错过了什么,否则srfi-26cutcute 不会提供你需要的东西吗?然后它只是您的方案实现是否提供它的问题(我认为大多数都提供)

【讨论】:

    【解决方案2】:

    你是对的——在方案中这样做的一种方法是手动创建 lambdas。以一种通用的、正确的方式实现这当然会很痛苦,即检查参数的数量(不希望有太多!)。

    Clojure(另一种 LISP 方言)是这样做的:

    http://clojuredocs.org/clojure_core/clojure.core/partial

    源丑陋吗?可能是。它有效吗?当然。

    【讨论】:

      【解决方案3】:

      回答我自己的问题:

      需要将函数定义为“零碎”地接受参数:换句话说,它并不是真正的柯里化。我在上面尝试过,但没有做对。

      一个被部分应用的函数需要被描述为一个 lambda 或 lambda 链,每个都准确地接受将要传递的参数的数量(按接收时间的降序排列)。

      一个工作示例:

      (define nums '(3 3 1 2))
      (define f
         (lambda (num1)
            (lambda (num2)
               (expt num1 num2))))
      (define ans (map (f 5) nums))
      (print ans)
      

      将 f 定义为接受所有参数将不起作用:

      (define f
         (lambda (num1 num2)
            (expt num1 num2))) ; Can't be curried
      

      【讨论】:

      • 许多 Scheme 后裔语言(例如 Racket 或 MIT Scheme)都允许您的 f 函数使用此简写:(define ((f num1) num2) (expt num1 num2)
      猜你喜欢
      • 1970-01-01
      • 2010-10-16
      • 1970-01-01
      • 2016-06-17
      • 2011-04-14
      • 2022-11-25
      • 2013-06-03
      • 1970-01-01
      • 2017-05-16
      相关资源
      最近更新 更多