【问题标题】:Racket macro that recursively processes a list argument递归处理列表参数的球拍宏
【发布时间】:2020-12-05 18:58:38
【问题描述】:

我正在尝试编写一个宏,它可以递归地将列表的值“解包”为单个值。例如,unwrap '(1 2 3)) 会(分别)产生:

(car '(1 2 3)) ; 1
(car (cdr '(1 2 3)) ; 2
(car (cdr (cdr '(1 2 3)) ; 3

这将像(+ (unwrap '(1 2 3))) ==> (+ 1 2 3) 一样使用。 (我知道你可以使用标准库申请,但我正在尝试编写自己的版本)。

我的问题是在编写宏时,我不知道如何递归处理传递给 unwrap 宏的列表参数。这是我尝试过的:

(define-syntax (unwrap stx)
  (syntax-case stx ()
    [(_ lst)
      #`(begin (car lst) ; error at the last step since (car '()) is invalid
               (unwrap (cdr lst)))]))

(define-syntax (unwrap stx)
  (syntax-case stx ()
    [(_ lst)
      #`(if (null? lst)
            '()
            (car (unwrap (cdr lst))))])) ; infinite loops

这些显然都是错误的,但基本上我不知道编写一个宏来检查输入列表的值(或与空列表模式匹配)并在任何一种情况下返回不同的东西。我也有可能完全错误地接近这个,所以任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: recursion macros scheme racket


    【解决方案1】:

    你想要

    (+ (unwrap '(1 2 3))) ==> (+ 1 2 3)
    

    但这是不可能的。您要求将unwrap 宏扩展为三个断开连接的表单,这是不允许的。任何宏都必须扩展为一种形式。因此,正如您在问题中所说,对于您给出的示例,apply 是正确答案。

    对于其他可能的用法,答案是备份一个步骤并询问您为什么认为这个unwrap 函数会有用:您希望在什么情况下使用它?然后设计一个不同的解决方案,在语言的限制下工作。

    【讨论】:

    • 我明白了。我有一种感觉不可能以这种方式进行扩展,但我对宏的了解还不够,无法证实我的怀疑。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 2015-04-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 2013-09-24
    • 2011-10-24
    相关资源
    最近更新 更多