functional-programming - 将 curry 映射到参数列表

标签 functional-programming scheme racket currying

我正在 Racket 中做一些练习,遇到了一个我似乎无法查询文档的问题。

我想为除数列表生成以下柯里式:

(define multlist '[3 5])
(define modfuncs (map (lambda x ;@ make some modulos
                          (curry modulo x)) multlist))

这会生成一个柯里化(Currying)过程列表,这听起来很有希望,但是当我尝试测试其中一个过程时,出现以下错误:

-> (car modfuncs)
#<procedure:curried>
-> ((car modfuncs) 3)
; modulo: contract violation
;   expected: integer?
;   given: '(3)
;   argument position: 1st
; [,bt for context]

假设这不是一个糟糕的方法,我如何取消引用传递给 curry/mapmultlist 值调用以便这些函数能够正确评估?

最佳答案

您实际上做得正确,尽管有一个小错误:

(lambda x (curry modulo x))

这并不像你想象的那样。您真正想要的是:

(lambda (x) (curry modulo x))

看出区别了吗?在前者中,x 不在参数列表中,因此它实际上会传递一个传递给函数的所有参数的列表,而不是单个参数。

您可以使用以下简单程序亲自查看此行为:

((lambda x x) 1 2 3)
; => '(1 2 3)

因此,您的 curry 函数正在接收 x 的一个数字列表,而不是一个实际的整数。


所以也许更令人满意的答案是:为什么 Racket 这样做?嗯,这实际上是 Racket/Scheme 的 rest parameter syntax 的结果。在 lambda 的最后一个参数之前插入一个点使该参数成为一个剩余参数,它成为一个包含传递给函数的所有其他参数的列表。

((lambda (a b . rest) rest) 1 2 3 4 5)
; => '(3 4 5)

然而,这实际上不仅仅是一种特殊的语法。点符号实际上与 Racket 的阅读器如何读取语法中的列表和对有关。上面的参数列表实际上变成了一个由以下 cons 序列组成的“不正确”列表:

(cons 'a (cons 'b 'rest))

没有 rest 参数的相同函数将有一个正确列表作为其参数声明,如下所示:

(cons 'a (cons 'b null))

那么,原始的 x 单独存在又如何呢?嗯,这是一个不正确的列表,没有前面的参数!执行 ( .rest) 没有任何意义,这将是一个语法错误,因为您将尝试创建一个没有 car 元素的对。等价的只是完全删除对语法。

关于functional-programming - 将 curry 映射到参数列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28448661/

相关文章:

racket - 从字符的可读表中删除 Racket 的默认读取器程序 |

list - 附加列表以显示在 Racket 的文本字段中

haskell - 为什么这个 Haskell 代码可以成功地处理无限列表?

functional-programming - 如何在对象的多个方法上使用 functools.partial 并无序卡住参数?

c++ - Haskell 中的面向对象编程

scheme - 模块中的未绑定(bind)标识符 - DrRacket

scheme - Dr Racket 的 MiniKanren 支持

c++ - 如何将私有(private)成员函数作为参数传递

lisp - 方案中的 RAII?

方案 Racket 计算列表无限循环中的最大元素