球拍,将列表转换为值
Racket, transform a list into values
我正在设计一个包含两部分的程序。一个在我的电脑上,一个在 Raspberry Pi.
上
我经常通过 TCP/IP 发送消息,从我计算机上的一个程序发送到 Raspberry Pi 上的一个程序。所以基本上它所做的是发送目的地、消息和参数列表。
然后在 Raspberry Pi 上我读取了目的地(存在于 raspberry pi 上的某个对象)并使用参数将消息发送到该对象。
在 raspberry pi 上的对象中,我有很多这样的程序:
(define (a-procedure argument1 argument2 ... argument-N)
...)
但问题是在 raspberry pi 上我收到了一个参数列表。
我不想更改所有过程(在 raspberry pi 上)所以它们采用参数列表而不是多个参数。
凭直觉我认为宏可以完成这项工作。
我从来没有使用过宏,也从来没有人教过我,所以我对这个概念很陌生。我在文档中搜索了一下,这就是我想出的:
(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".
所以我尝试了这个:
(call-with-values (lambda ()
(for-each (lambda (arg) arg) argumentList))
a-procedure)
现在过程是可变的(不是硬编码过程)但问题是它只考虑了 for-each 返回的最后一个值。
我没有找到将列表转换为多个值的方法 '(1 2 3 4) --> (values 1 2 3 4)
我认为你设计得太过了。如果你想调用一个带有列表中的多个参数的过程,只需使用 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)
我正在设计一个包含两部分的程序。一个在我的电脑上,一个在 Raspberry Pi.
上我经常通过 TCP/IP 发送消息,从我计算机上的一个程序发送到 Raspberry Pi 上的一个程序。所以基本上它所做的是发送目的地、消息和参数列表。
然后在 Raspberry Pi 上我读取了目的地(存在于 raspberry pi 上的某个对象)并使用参数将消息发送到该对象。
在 raspberry pi 上的对象中,我有很多这样的程序:
(define (a-procedure argument1 argument2 ... argument-N)
...)
但问题是在 raspberry pi 上我收到了一个参数列表。 我不想更改所有过程(在 raspberry pi 上)所以它们采用参数列表而不是多个参数。
凭直觉我认为宏可以完成这项工作。 我从来没有使用过宏,也从来没有人教过我,所以我对这个概念很陌生。我在文档中搜索了一下,这就是我想出的:
(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".
所以我尝试了这个:
(call-with-values (lambda ()
(for-each (lambda (arg) arg) argumentList))
a-procedure)
现在过程是可变的(不是硬编码过程)但问题是它只考虑了 for-each 返回的最后一个值。
我没有找到将列表转换为多个值的方法 '(1 2 3 4) --> (values 1 2 3 4)
我认为你设计得太过了。如果你想调用一个带有列表中的多个参数的过程,只需使用 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)