首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Racket:跨模块使用宏

Racket:跨模块使用宏
EN

Stack Overflow用户
提问于 2011-07-27 00:09:56
回答 1查看 932关注 0票数 1

为了教给自己更高级的球拍宏,我开始创建宏来增加可变结构中的字段:

代码语言:javascript
复制
 `(increment! instance name field)` 

=>

(set-name-field instance (get-name-field instance))

我生成了一个可以工作的宏,并决定在多个模块之间共享将是有用的。不幸的是,由于结构变异器不在定义宏的模块的范围内,因此会发生扩展错误。

下面是演示这个问题的一个人为的例子。我想知道:

  1. 我是不是用惯用的方式写了宏代码?这是正确的做法吗?
  2. 如何控制宏的扩展,使其在未在其原始上下文中找到的标识符存在的情况下运行?

谢谢。

代码语言:javascript
复制
#lang racket/load

(module util racket

  (define-syntax increment!
    (lambda (stx)
      (syntax-case stx ()
        [(increment! s sn fn i)
         (with-syntax 
             ([set! (string->symbol 
                     (format "set-~a-~a!" (syntax-e #'sn) (syntax-e #'fn)))]
              [get (string->symbol 
                    (format "~a-~a" (syntax-e #'sn) (syntax-e #'fn)))])
           #'(set! s (+ i (get s))))]
        ;; default increment of 1
        [(increment! s sn fn) #'(increment! s sn fn 1)])))

  (provide increment!)
  )

(module bank racket
  (require 'util)
  (struct money (dollars pounds euros) #:mutable #:transparent)

  (let ([m (money 0 50 20)])
    (increment! m money pounds 100)
    (increment! m money dollars)
    m)
  )

(require 'bank)

结果在

展开:模块中的未绑定标识符:set-money-磅!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-07-27 02:14:20

你不能就这么做。问题是,您正在生成具有正确名称的符号,但您只返回符号为- is,这意味着with-syntax为它们提供了一些默认(错误)的词法上下文。相反,您应该使用datum->syntax并为其提供正确的上下文。

下面是您的代码的修订,如您所期望的那样工作。要了解更多有关它的信息,请参阅我最近关于不卫生宏的博客帖子

然而,这不是一个强有力的解决办法。当setter和getter有不同的名称时会发生什么?一个更健壮的解决方案是使用结构名称并从其中提取正确的信息(在语法时,在宏中) --有关这方面的详细信息,请参阅手册。在邮寄名单上提出有关它的问题也很好,因为可能有更好的方法来获得您想要的东西,或者如果您正在寻找类似点符号的功能,则会有更好的解决方案。

代码语言:javascript
复制
#lang racket/load

(module util racket
  (define-syntax increment!
    (lambda (stx)
      (syntax-case stx ()
        [(increment! s sn fn i)
         (let ([id (lambda (fmt)
                     (let ([str (format fmt (syntax-e #'sn) (syntax-e #'fn))])
                       (datum->syntax #'sn (string->symbol str))))])
           (with-syntax ([set! (id "set-~a-~a!")]
                         [get (id "~a-~a")])
             #'(set! s (+ i (get s)))))]
        ;; default increment of 1
        [(increment! s sn fn) #'(increment! s sn fn 1)])))
  (provide increment!))

(module bank racket
  (require 'util)
  (struct money (dollars pounds euros) #:mutable #:transparent)
  (let ([m (money 0 50 20)])
    (increment! m money pounds 100)
    (increment! m money dollars)
    m))

(require 'bank)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6838115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档