Are there macros with a complete program in Lisp or schema?

I saw one answer. How does Lisp allow you to override the language itself? Question (answered Noah Lavigne):

Macros are not a complete redefinition of the language, at least as far as I know (I'm actually Schemer, I could be wrong), because there is a limitation. A macro can only take one subtree of your code and generate one subtree to replace it. Therefore, you cannot write macros that transform the entire program as cool as it would be.

After reading this, I wonder if there are macros that convert the entire program into Lisp or Scheme (or some other language).

If not, why?

  • Is this not useful and not required?
  • Could the same be done in other ways?
  • Impossible to implement it even in Lisp?
  • Perhaps, but have not tried or not implemented ever?

Update

One kind of use case for example.

Like the stumpwm code, here are some functions, everything in different Lisp source files uses the dynamic / global variable defvar * screen-list * , which is defined in primitives.lisp, but used in screen.lisp, user.lisp, window.lisp. (Here, each file has functions, a class, and options related to one aspect or object)

Now I would like to define these functions when closing, where the * screen-list * , available in the let form, it should not be a dynamic / global variable, but not moving all these functions to one place (because I do not want these functions lost space from their linked file) so that this variable is available only for these functions.

The above, for example, are equally applicable to the label and flet, so it will be possible that we could make it so that only the required variable, the function will be available to those who require it.

Note that one way could be to implement and use some defun_with_context macro for defun, where the first argument is the context, where let, flet variables are defined. But besides this, it can be achieved with the help of a macro reader like Batting and Gareth Rice.

+6
macros lisp scheme transformation
source share
7 answers

You quoted Noah Avalanche:

A macro can only take one subtree of your code and generate one subtree to replace it

This applies to regular macros, but reader macros access the input stream and can do whatever they like with it.

See Hyperspec section 2.2 and set-macro-character .

+5
source share

In Racket, you can implement macros that transform the entire program. See the section in the documentation for defining new languages . Racket has many examples, such as lazy language and Typed Racket.

+5
source share

A typical approach is to create your own modular system. If you just want to access the entire code, you may have some files with a preliminary processor or an extension of the covers of readers with your own module annotation. If you then write your own require or import form, you will eventually be able to see all the code in the area.

To get started, you can write your own module form, which allows you to define several functions that are then not compiled correctly before correcting optimized code.

+1
source share

There are several approaches above my head:

Firstly, you can. Norwig points out that:

We can write a compiler as a set of macros.

so that you can convert the whole program if you want. I have rarely seen this, because, as a rule, the intersection between “things you want to do with each part of your program” and “things for which you need macro / AST type conversions for” is a rather small set. One example is Parenscript , which converts your Lisp code ("extended subset of CL") to Javascript. I used it to compile entire Lisp code files into Javascript, which is provided directly to web clients. This is not my favorite medium, but she does what she advertises.

Another related function is the “tip”, which Yegge describes as :

Large systems also have tips. There is no universally accepted name for this feature. Sometimes called hooks, filters, or aspect-oriented programming. As far as I know, Lisp had this at first, and he called advice in Lisp. A tip is a mini-framework that provides before, around, and after interception, with which you can programmatically change the behavior of an action or function call in the system.

Another is special variables . Usually macros (and other constructions) are applied to the lexical sphere. By declaring a variable special, you say that it is applicable to the dynamic region (I think it is like a "temporary region"). I can’t think of any other language that allows you (the programmer) to choose between the two. And besides the compiler case, these two really cover the space that interests me as a programmer.

+1
source share

There is always the choice of using compiler macros (they can perform the conversion of entire functions based on a set of criteria, but should not change the return value, since this will confuse).

Macros are read here, they transform the input "how it is read" (or "before it is read," if you want). I did not do a lot of large-scale hacking of the macro reader, but I wrote some code to allow elisp sourec (mostly) to read in Common Lisp, with fairly slight differences in syntactic sugar between them.

0
source share

I believe that such macros are called macros for code conversion. I myself have not implemented a code walker, so I am not familiar with the limitations.

0
source share

In Common LISP, at least you can wrap top-level forms in PROGN, and they still retain their status as top-level forms (see CLTL2, section 5.3 ). Therefore, restricting a macro generating one subtree is not a big restriction, since it can wrap any number of resulting subtrees in PROGN. This makes software macros quite possible.

eg.

 (my-whole-program-macro ...) = expands to => (progn (load-system ...) (defvar ...) (defconstant ...) (defmacro ...) (defclass ...) (defstruct ...) (defun ...) (defun ...) ... ) 
0
source share

All Articles