macros - 宏是否有副作用?

  显示原文与译文双语对照的内容
0 0

可以( 或应该) 宏展开有副作用? 例如,下面是一个宏实际上就是去找他,抓取网页的内容在编译时:

#lang racket
(require (for-syntax net/url))
(require (for-syntax racket/port))
(define-syntax foo
  (lambda (syntx)
    (datum->syntax #'lex
                   (port->string
                     (get-pure-port
                       (string->url
                         (car (cdr (syntax->datum syntx)))))))))

然后,我能做 (foo "http://www.pointlesssites.com/")它就会被替换为 "rn<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"rnt <and so on>"

这是一种不错的做法,还是不? 这事我garunteed Racket此代码才运行一次? 如果我添加一个 (display "running...")行的宏,它只输出一次,但我才不想那么从一个例子。

ps我之所以问你是因为我真的认为有时是很有用。 例如是库它允许你加载( 在编译时) 发现文档从Google API Discovery服务并自动为其创建包装器。 我想会是一件很实际的库中的发现文档web,而不是从本地文件获取。

此外,给的示例宏使用了另一种形式的副作用: 我曾经建立了一个宏的转换的一个很小的子集Racket into ( eta展开) Lambda微积分( 当然,仍可运行在Racket ) 。 只要宏完成翻译函数,它会将结果存储在字典中,以便以后调用的宏可以进一步利用的函数定义在自己的翻译。

时间:原作者:5个回答

0 0

" Short Answer

没事的宏具有副作用,但应确保程序不会更改行为提前编译此文件后。

较长的回答

宏的副作用是个强大的工具,可以让你的事情使程序更易于编写,或启用根本东西,就不可能有。 但还是有一些陷阱需要注意的时使用宏中的副作用。 幸运的是,声音吵死人了提供的所有工具,以确保可以正确执行此操作。

最简单类型的宏副作用上,可以使用一些外部状态查找要生成的代码。 你的示例列表中读取Google API问题( 描述) 属于这种。 一种更加简洁的示例是 include宏:

#lang racket
(include "my-file.rktl")

此的内容读入 myfile.rktl并将其删除来替代就位于 include使用非向量形式。

现在, include不是好方法结构程序,但这是个非常良性的某种副作用的宏。 也是一样,如果编译文件提前为如果不,因为的结果 include属于该文件。

另一个简单的例子,这是好将如下所示:

#lang racket
(define-syntax (show-file stx)
  (printf "using file ~an" (syntax-source stx))
  #'(void))
(show-file)

这是因为在 printf获取仅在编译时执行,所以如果你编译程序,它使用 show-file提前( 与 raco make),则该 printf然后会发生,不会发生在程序运行时,那可能是意图。

幸运的是,声音吵死人了是一个允许你编写宏的技术如 show-file有效地。 其基本思想是将残余代码由该插件执行副作用。 特别是,可以使用Rackets begin-for-syntax表单来实现这种效果。 下面就是我会写 show-file:

#lang racket
(define-syntax (show-file stx)
  #'(begin-for-syntax
      (printf "using file ~an" (syntax-source stx))))
(show-file)

现在,不需要时发生 show-file展开printf发生在的代码 show-file生成 。 这样程序中的正常工作总是存在提前编译。

有其他用途的宏也有副作用的。 其中一个显著特点Racket用于跨模块通信,因为 require不生成值的要求模块可以获取之间进行通信模块,最有效的方法是使用副作用。 若要使此作用于新出现的编译需要几乎完全相同的技巧, begin-for-syntax.

这是一个主题Racket社区,我特别想了很多有关,和有若干学术论文讨论这是如何实现的:

Composable和Compilable Macros : 想在什么时候? ,马修Flatt icfp 2002

office 2007

Selectors Level 3 W3C Recommendation29 September 2011

原作者:
0 0

在Common Lisp函数eval时允许你决定什么时候宏将被展开。

原作者:
...