【问题标题】:Mapping curry to a list of parameters将 curry 映射到参数列表
【发布时间】:2015-04-11 11:42:59
【问题描述】:

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

我想为除数列表生成以下modulo curries:

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

这会生成一个柯里化程序列表,这听起来很有希望,但是当我尝试测试其中一个时,我收到以下错误:

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

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

【问题讨论】:

    标签: functional-programming scheme racket currying


    【解决方案1】:

    你实际上是正确地做这件事,尽管有一个小错误:

    (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 的最后一个参数之前插入一个点会使该参数成为 rest 参数,它成为一个列表,其中包含传递给函数的所有附加参数。

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

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

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

    没有rest 参数的相同函数将有一个proper 列表作为其参数声明,它看起来像这样:

    (cons 'a (cons 'b null))
    

    那么,原来的x 一个人站着呢?好吧,这是一个不正确的列表,没有前面的参数!执行( . rest) 没有任何意义——这将是一个语法错误——因为您将尝试创建一个没有car 元素的对。等价的只是完全放弃对语法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-20
      • 1970-01-01
      • 2020-08-10
      • 2012-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多