Racket,将列表转换为值

时间:2015-04-03 15:32:58

标签: macros arguments racket

我正在设计一个包含两部分的程序。一个在我的电脑上,另一个在Raspberry Pi上。

我经常通过TCP / IP发送消息,从我的计算机上的程序发送到Raspberry Pi上的程序。所以基本上它的作用是发送目的地,消息和参数列表。

然后在Raspberry Pi上我读取了目的地(生物在树莓派上的某个对象),然后用参数将消息发送给该对象。

在覆盆子pi上的对象中,我有许多看起来像这样的程序:

(define (a-procedure argument1 argument2 ... argument-N)
  ...)

但问题是在树莓派上我收到一个参数列表。 我不想改变所有程序(在树莓派上),所以他们采用参数列表而不是多个参数。

如此直观我认为宏可以完成这项工作。 我从来没有使用过宏,也从未向我讲过,所以我对这个概念很陌生。我在文档中搜索了一下,这就是我提出的:

(define-syntax rotate
  (syntax-rules ()
    [(a-procedure (list a)) (x a)]
    [(a-procedure (list a ...)) (x a ...)]))

问题在于它总是调用“x”程序。

所以现在我希望它调用的过程也可以是变量的(不是硬编码的,因为我不想为raspberry pi上的每个过程制作这样的宏......)。

例如:

(callWithArguments (+ (list 1 2 3))) ; --> (+ 1 2 3)
(callWithArguments (* (list 1 2 3))) ; --> (* 1 2 3)

为此,我尝试了这个:

(define-syntax callWithArguments
  (syntax-rule ()
    [(a-procedure (list a)) (a-procedure a)]
    [(a-procedure (list a ...)) (a-procedure a ...)]))

但在这个例子中,“a-procedure”不是变量。 如果我试着像上面提到的那样打电话给我:

 a-procedure: undefined;
 cannot reference an identifier before its definition

我试图用“syntax-rules-id”来做,但没有成功。

我还阅读了有关多个值的文档。 我看到了一个“呼叫价值”的程序。

所以我尝试了这个:

(call-with-values (lambda () 
                    (for-each (lambda (arg) arg) argumentList)) 
                  a-procedure)

现在程序是可变的(不是硬编码程序),但问题是它只考虑了for-each返回的最后一个值。 我没有找到将列表转换为多个值'(1 2 3 4) --> (values 1 2 3 4)

的方法

1 个答案:

答案 0 :(得分:3)

我认为你已经过度设计了这个。如果要调用列表中包含多个参数的过程,只需使用apply。所以这个:

(callWithArguments (+ (list 1 2 3)))

可以表达为:

(apply + (list 1 2 3))

但是如果你想用评估表达式的宏,试试这个:

(define-syntax callWithArguments
  (syntax-rules ()
    [(_ (a-procedure a-list))
     (apply a-procedure a-list)]))

(callWithArguments (+ (list 1 2 3)))
=> 6

或者,如果您对转换表达式感兴趣而未实际评估它,请使用列表拼接:

(define-syntax callWithArguments
  (syntax-rules ()
    [(_ (a-procedure a-list))
     `(a-procedure ,@a-list)]))

(callWithArguments (+ (list 1 2 3)))
=> '(+ 1 2 3)