2013-04-17 40 views
3

我正在学习Scheme中的宏系统,我认为实现curried函数将是一个好的开始。这是我制作的:使用宏的Scheme中的Currying函数

(define-syntax function 
    (syntax-rules() 
     ((_() body ...) (lambda() body ...)) 
     ((_ (param) body ...) (lambda (param) body ...)) 
     ((_ (param_1 param_2 params ...) body ...) (lambda (param_1 . rest) 
      (let ((k (function (param_2 params ...) body ...))) 
       (if (null? rest) k (apply k rest))))) 
     ((_ name params body ...) (define name (function params body ...))))) 

此代码按预期工作。举例如下我可以定义一个add功能:

(function add (x y) (+ x y)) 

然后我可以正常调用它:

(add 2 3) ; => 5 

此外,我可以很容易地部分地应用它:

(map (add 10) '(2 3 5 7)) ; => (12 13 15 17) 

现在我正在考虑允许具有其他参数的函数被粘贴。所以我增加了一个新的语法规则:

((_ (param . params) body ...) (lambda (param . params) body ...)) 

不幸的是,当我尝试使用这个法则它给了我一个错误创建一个函数:

(function add (x . y) (apply + `(,x ,@y))) 

这是错误消息:

Error: invalid syntax in macro form: (x . y) 

    Call history: 

    <eval> (##sys#= len7 0) 
    <eval> (loop11 (##sys#cdr l6) (##sys#+ len7 -1)) 
    <eval> (##sys#cdr l6) 
    <eval> (##sys#+ len7 -1) 
    <eval> (##sys#= len7 0) 
    <eval> (loop11 (##sys#cdr l6) (##sys#+ len7 -1)) 
    <eval> (##sys#cdr l6) 
    <eval> (##sys#+ len7 -1) 
    <eval> (##sys#= len7 0) 
    <eval> (##sys#eq? l6 (quote())) 
    <eval> (##sys#car tail15) 
    <eval> (##sys#cdr tail15) 
    <eval> (##sys#cons (rename14 (##core#syntax lambda)) (##sys#cons param body)) 
    <eval> (rename14 (##core#syntax lambda)) 
    <eval> (##sys#cons param body) 
    <syntax>  (##core#lambda add (x . y) (apply + (quasiquote ((unquote x) (unquote-splicing y))))) <- 

我做错了什么?

回答

3

[评论是正确的;这个答案不是咖喱,它是部分评价。]

只是你知道,你不需要使用define-syntax来支持咖喱。通常在不需要时使用语法会被忽视,因为1)语法引入了不同的评估规则,2)语法不能用作值。

这里有两种实现方式,一个是(左)咖喱一个右咖喱:

> (define add-5 (curry + 5)) 
> (add-5 5) 
10 
+2

这是**不**创建_curried_函数;它正在创建_partially applied_函数。用'(define(fxyz)(+ x(* yz)))(define g(curry f 1))','((g 2)3)'应该返回7.但是你必须调用'((curry g 2)3)。而在OP代码之后,'(函数g(xyz)(+ x(* yz)))','(g 1 2 3)'=='((g 1 2)3)'=='(( (g 1)2)3)'== 7。 –

2

你不说你正在使用什么版本的Scheme。它似乎不支持宏中的“点”模式。

球拍,它看起来像你的代码的工作:

#lang racket 

(define-syntax function 
    (syntax-rules() 
     ((_() body ...) (lambda() body ...)) 
     ((_ (param) body ...) (lambda (param) body ...)) 
     ((_ (param_1 param_2 params ...) body ...) (lambda (param_1 . rest) 
                (let ((k (function (param_2 params ...) body ...))) 
                (if (null? rest) k (apply k rest))))) 

     ((_ (param . params) body ...) (lambda (param . params) body ...)) 
     ((_ name params body ...) (define name (function params body ...))))) 

(function add (x . y) (apply + `(,x ,@y))) 

(add 2 3) 

运行这将产生答案

5 

顺便说一句,我想我会写这两个宏;名称'功能'的双重目的有点简单... :)

+0

我用鸡方案版本'4.7:

(define (curry func . curry-args) (lambda args (apply func (append curry-args args)))) (define (rcurry func . curry-args) (lambda args (apply func (append args curry-args)))) 

以此作为例子。 0'。 –

+2

听起来像鸡计划不支持这种模式写作。也许你想尝试一下Racket? ... :) –