Are there whole-program-transforming macros in Lisp or Scheme?

You quoted Noah Lavine as saying: A macro can only take a single subtree of your code, and generate a single subtree to replace it This is the case for ordinary macros, but reader macros get access to the input stream and can do whatever they like with it See the Hyperspec section 2.2 and the set-macro-character function.

You quoted Noah Lavine as saying: A macro can only take a single subtree of your code, and generate a single subtree to replace it This is the case for ordinary macros, but reader macros get access to the input stream and can do whatever they like with it. See the Hyperspec section 2.2 and the set-macro-character function.

Off the top of my head, a few approaches: First, you can. Norvig points out that: We can write a compiler as a set of macros. So you can transform an entire program, if you want to.

I've only seen it done rarely, because typically the intersection between "things you want to do to every part of your program" and "things that you need macro/AST-type transformations for" is a pretty small set. One example is Parenscript, which transforms your Lisp code ("an extended subset of CL") into Javascript. I've used it to compile entire files of Lisp code into Javascript which is served directly to web clients.It's not my favorite environment, but it does what it advertises.

Another related feature is "advice", which Yegge describes as: Great systems also have advice. There's no universally accepted name for this feature. Sometimes it's called hooks, or filters, or aspect-oriented programming.

As far as I know, Lisp had it first, and it's called advice in Lisp. Advice is a mini-framework that provides before, around, and after hooks by which you can programmatically modify the behavior of some action or function call in the system. Another is special variables.

Typically macros (and other constructs) apply to lexical scope. By declaring a variable to be special, you're telling it to apply to dynamic scope (I think of it as "temporal scope"). I can't think of any other language that lets you (the programmer) choose between these two.

And, apart from the compiler case, these two really span the space that I'm interested in as a programmer.

For lisp-like languages you can define your own compiler for a higher level language as a macro on top of the underlying Lisp, and do whatever you want with this language - introduce a type system, perform full program transforms, use your own syntax, whatever else. All you need is an ability to generate a number of top-level definitions from a single macro. Any decent Lisp allows to do that.

There is a showcase for this approach: meta-alternative.net/mbase.html - for example, there is an implementation of ML on top of Lisp, embedded into a macro.

I would add that another impressive piece of work along these lines is Qi -- a language implemented on top of CL (with macros I suppose): code.google. Com/p/qilang – Artyom Shalkhakov Jan 27 at 16:48 And probably the most impressive example: norvig. Com/paip/prolog.

Lisp – SK-logic Jan 27 at 17:00.

In Racket, you can implement whole-program-transforming macros. See the section in the documentation about defining new languages. There are many examples of this in Racket, for example the lazy language and Typed Racket.

There's always the choice of using compiler macros (they can do whole-function transformation based on a lew of criteria, but shouldn't change the value returned, as that would be confusing). There's reader macros, they transform the input "as it is read" (or "before it is read", if you prefer). I haven't done much large-scale reader-macro hacking, but I have written some code to allow elisp sourec to be (mostly) read in Common Lisp, with quite a few subtle differences in syntactic sugar between the two.

A typical approach is to write your own module system. If you just want access to all the code, you can have some sort of pre-processor or reader extension wrap source files with your own module annotation. If you then write your own require or import form, you will ultimately be able to see all the code in scope.To get started, you could write your own module form that lets you define several functions which you then compile in some clever way before emitting optimized code.

I believe those sorts of macros are called code-walking macros. I haven't implemented a code walker myself, so I am not familiar with the limits.

In Common LISP, at least, you may wrap top-level forms in PROGN and they still retain their status as top-level forms (see CLTL2, section 5.3). Therefore, the limitation of a macro generating a single subtree is not much of a limitation since it could wrap any number of resulting subtrees within PROGN. This makes whole-program macros quite possible.E.g.(my-whole-program-macro ...) = expands to => (progn (load-system ...) (defvar ...) (defconstant ...) (defmacro ...) (defclass ...) (defstruct ...) (defun ...) (defun ...) ... ).

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions