如何使一个Racket宏采用整数参数?

时间:2012-11-12 04:35:47

标签: syntax macros racket

我一直在尝试为'包装'函数创建一个宏,即如果我有一个函数将获取一个列表并将符号'a'与第一个元素相符,它通常被定义为lambda(l )(cons'al),但我想要一个宏,它将获取一个函数和一个整数表达式对的列表和'wrap',它通过创建一个新函数来获取旧函数的一些参数并获得其余的函数在对上,使用整数作为位置,将表达式作为值来给出函数。像这样:

(wrap list (0 'blah) (2 'bloo) (4 'blee))

应扩展为:

(lambda (a1 a2 . rest)
  (apply list 'blah a1 'bloo a2 'blee rest))

问题是,我不知道如何让宏找到该对中整数的值,它只知道它作为语法对象。我是相当新的宏,这应该是相当简单的,我只是在使用文档时遇到问题,除了宏上的简单教程之外,我在网上找不到任何信息。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

这似乎是一个想写的疯狂宏,特别是当SRFI 26使用起来更加直观时。您可以使用:

而不是(wrap list (0 'blah) (2 'bloo) (4 'blee))
(cut list 'blah <> 'bloo <> 'blee <...>)

这肯定更容易阅读。


如果真的必须编写这样一个宏,可以通过将wrap的用法转换为cut的等效用法来实现它的一种方法:

(require (for-syntax syntax/parse) srfi/26)
(define-syntax (wrap stx)
  (syntax-parse stx
    ((_ func:expr (idx:nat expr:expr) ...)
     (let* ((alist (map cons
                        (syntax->datum #'(idx ...))
                        (syntax-e #'(expr ...))))
            (upper (add1 (apply max -1 (map car alist))))
            (listfunc (lambda (i)
                        (cond ((assv i alist) => cdr)
                              (else #'<>)))))
       (with-syntax (((args ...) (build-list upper listfunc)))
         #'(cut func args ... <...>))))))

回答你的问题,关于如何获得给定语法对象的整数的关键是使用syntax->datum(用于深层语法剥离)或syntax-e(用于浅层语法剥离)。


(PS(对于球拍专家来说这个。)我对syntax-parse很新,所以我确信syntax-parse专家可以找到更好的方法来编写上述内容。我原来写的是宏作为syntax-case宏,然后打上syntax-parse语法类。就是这样。)