【问题标题】:Racket, transform a list into valuesRacket,将列表转换为值
【发布时间】:2015-06-08 17:16:05
【问题描述】:

我正在设计一个包含 2 个部分的程序。一个在我的电脑上,一个在树莓派上。

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

然后在 Raspberry Pi 上,我读取目标(存在于 raspberry 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”

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

例如:

(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)

【问题讨论】:

    标签: macros arguments racket


    【解决方案1】:

    我认为你设计过度了。如果您想调用列表中包含多个参数的过程,只需使用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)
    

    【讨论】:

    • 你是对的!我一直在寻找它,我不记得 apply 可以完成这项工作。 :)
    • 你知道他们说什么:保持简单;)。大多数情况下,一个过程可以解决问题,宏很强大,但通常你可以不使用它们而摆脱困境。将它们留在工具箱中以应对更复杂的场景。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 2022-11-18
    • 2022-01-12
    • 2022-08-17
    • 2018-11-06
    相关资源
    最近更新 更多