如何绕过咖喱评估其论点?

时间:2017-08-24 12:23:27

标签: racket currying

假设我有一些功能,让我们称之为get-io-data,例如从shell命令获取数据。现在我想要一个检查某些东西的函数:check-io-data。似乎应该是等同于定义它的方式最终会有所不同。使用传统的'定义我得到一个函数,根据评估时(get-io-data)的结果给出结果。但是,如果我使用curry,我将得到一个函数,该函数取决于定义时(get-io-data)的结果。为了让它更容易混淆,这是一个例子:

使用传统定义:

(define (check-io-data x) (equal? (get-io-data) x))
...
(check-io-data 0) ;; Now (get-io-data) is being evaluated

使用咖喱:

(define check-io-data (curry equal? (get-io-data))) ;; Now (get-io-data) is being evaluated
...
(check-io-data 0)

我想我知道为什么这些是不同的,因为在第一种情况下,整个函数体可能以一种特殊的方式进行评估,因为它是一个函数体,而在第二种情况下,我定义的东西是是一个功能的结果;并且此函数在define-time进行评估,以获取实际定义并评估其评估参数的函数。

有没有办法做到这一点,或者只是不会工作?从理论上讲,这两个定义不应该完全相同吗?

1 个答案:

答案 0 :(得分:1)

简单回答

语法是,

(define (check-io-data data) 
  ((curry equal?) (get-io-data) data))

讨论

因为check-io-data是一个参数的函数,所以它必须这样定义。因为equal?是一个arity = 2的函数,所以在curry时它必须传递两个参数。

以示意图的形式,这个:

> (define f (lambda (x) (equal? 'curried-argument x)))
> (f 'curried-argument)
#t
> (f 1)
#f

相当于:

> (define (f x) ((curry equal?) 'curried-argument x))
> (f 'curried-argument)
#t
> (f 1)
#f

说明性示例

#lang racket

;;; Use a generator to simulate
;;; a non-idempotent procedure
(require racket/generator)
(define get-io-data
  (infinite-generator
   (yield 1)
   (yield 2)
   (yield 3)))

(define (check-io-data x)
  ((curry equal?) (get-io-data) x))

(check-io-data 1)  ; #t
(check-io-data 1)  ; #f
(check-io-data 1)  ; #f
(check-io-data 1)  ; #t

结论

一个curried函数必须define本身作为一个函数[即(define (name arg...)(body))]以确定由lambda创建的curry的arity。