【问题标题】:Scheme - have a function return a functionScheme - 有一个函数返回一个函数
【发布时间】:2012-09-11 00:43:24
【问题描述】:

我想通过以下方式使用此代码: 如果我输入:

((function1 5) 2)

其中 function1 基于5 执行其过程,并返回一个基于2 执行某些内容的function2。这可以吗?

【问题讨论】:

    标签: function functional-programming lisp scheme currying


    【解决方案1】:
    (define (multiplyBy n) (lambda (x) (* n x)))
    ((multiplyBy 5) 2)
    

    我相信会做你想做的事。

    【讨论】:

    • 这种技术叫什么?您能否指出R6RS 中描述的位置?我搜索了“高阶函数”和“柯里化函数”(这是我听到的描述),但找不到文档中使用的语言。
    • 我不确定它的正式名称是什么——它或多或少是11.2.111.4.2 部分所做内容的扩展。 (define) [第三种形式] 将一些形式和主体分配给变量名;主体恰好是一个返回函数的 lambda 表达式。 lambda 部分指定“在计算 lambda 表达式时有效的环境被记住为过程的一部分”。这意味着在执行时,首先使用其参数评估 define'd 变量,然后将它们传递到 Lamba 的环境(保存在结果过程中)。
    【解决方案2】:

    继续@zebediah49 的示例,这是另一种方法:

    (define (multiplyBy n) ((curry *) n))
    ((multiplyBy 5) 2)
    > 10
    

    一般来说,对于一个有两个参数的函数(上面的例子看起来有点不同,因为* 是一个有一个或多个参数的函数):

    (define (function1 arg0) (curry <function2, receives arg1> arg0))
    

    引用curry 过程的文档:

    返回一个过程,它是proc 的柯里化版本。当第一次应用生成的过程时,除非给定它可以接受的最大参数数量,否则结果是一个接受附加参数的过程

    基本上,您被要求实现currying。引用维基百科的文章:

    在数学和计算机科学中,柯里化是一种转换具有多个参数(或参数的 n 元组)的函数的技术,它可以被称为一个函数链,每个函数都有一个参数(部分应用)。它由 Moses Schönfinkel 提出,后来被 Haskell Curry 重新发现。因此,有人说将其命名为 schönfinkeling 更为正确。

    请注意,所有这些都是等价的:

    (define ((function1 arg0) arg1) <body>)
    (define (function1 arg0) (lambda (arg1) <body>))
    (define (function1 arg0) (curry <function2, receives arg1> arg0))
    (define (function1 arg0) (define (function2 arg1) <body>) function2)
    

    【讨论】:

      【解决方案3】:

      我问了一圈,发现你可以这样定义一个函数:

      (define ((function1 arg0) arg1) (;procedure here...))

      这就是我想要的。我想毕竟它并没有真正得到一个函数来返回一个过程......:/感谢所有的帮助! :)

      【讨论】:

      • 其实你写的一个返回函数的函数。尝试仅使用 1 个参数调用您的 function1。你应该看到你回来了……一个函数!所以事实上,从函数返回函数的方法有很多。请参阅下面我的答案以另一种方式...
      • (define ((function1 arg0) arg1) &lt;body&gt;)(define (function1 arg0) (lambda (arg1) &lt;body&gt;)) 的语法糖,两个版本在底层是相同的
      • 我想这与 zebediah 的答案相同,但就像 Oscar 所说的那样,在语法上是不同的。谢谢各位的帮助! :)
      【解决方案4】:

      其中许多答案正确地显示了从函数返回函数的不同方式。更一般地说,您正在做的事情称为 Currying。更具体地说,“currying”是指将一个接受 n 个参数的函数转换为一个接受一个参数并返回一个接受 n-1 个参数的新函数的过程。

      对于初学者来说,这是我觉得最好看的风格:

      #lang racket
      
      ;; a curried function that multiplies two numbers
      (define (function1 arg0)
        (define (function2 arg1) 
          (* arg0 arg1))
        function2)
      

      此函数接受一个参数 (arg0),定义一个参数 (arg1) 的新函数,该函数将 arg0 和 arg1 相乘,然后返回。

      这个不像使用 lambda 的那么短,但是当你刚开始时,lambda 看起来只是一件更奇怪的东西,没有任何意义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-12
        • 2012-09-16
        相关资源
        最近更新 更多