15
votes

Every Common Lisp programmer knows that macros are a powerful tool. Common Lisp macros have been used, among other things, to add object orientation on top of Lisp without changing the language specification; read-macros are another construct with mind bending capabilities.

Another program which allows meta-programming is Forth. Forth does it in a slightly different manner, using 'words' and 'generate words'.

I would like to know, from someone who dabbled in both languages, if common lisp macros and forth constructs are comparable in breadth/power: is there something you can do with the former which you can't do with the latter? Or vice-versa?

Of course, I am not talking about Turing-completeness of the two languages: I am talking about metaprogramming capabilities. C is Turing-complete but only a fool would state that C macros are comparable in power to Common Lisp ones.

3
This is much more specific than the previous version, Lisp and Forth macros [on hold], which is good. Of course, now that question has reopen votes, and this has a close vote, so there's some confusion about which of these should actually stay open. It's much clearer what you're looking for in this question, but it's still probably off topic, because "comparison question are a poor fit for [Stack Overflow], because there are no bounds to the answers which can be posted to them.".Joshua Taylor
The close reason too broad applies here: "There are either too many possible answers, or good answers would be too long for this format." This is not a bad question at all; it's just not a particularly good fit for Stack Overflow. This question could be great in comp.lang.lisp, for instance.Joshua Taylor
The particular subquestion, "is there something you can do with the former which you can't do with the latter? Or vice-versa?" is probably the most specific here. It still might admit too many answers, but if there's something that one can do that the other can't, it's probably possible to give a relatively canonical answer.Joshua Taylor
Against closing for too broad. Example answer: "in LANG1 you can't implement foo, which has been implemented in LANG2, because you lack bar, which LANG1 has and LANG2 has not." In the Why are some questions marked "on hold"? there is no mention of "too many answer" as a reason questions should be closed.user3750103
Actually, it's right there in the page that you linked to: "too broad - if your question could be answered by an entire book, or has many valid answers, it's probably too broad for our format There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow down the answer set or to isolate an issue that can be answered in a few paragraphs."Joshua Taylor

3 Answers

8
votes

In my view, Common Lisp macros are similar to Forth immediate words. (Actually, they are most similar to Lisp reader macros.)

  • They are both procedural macros, i.e. can use full power of the language.

  • They both have access to the source code input.

  • They both can output anything expressible in the language. (E.g. an object-oriented extension in Lisp, or basic control flow constructs in Forth.)

The main difference, perhaps, would be that Forth "macro" input are character strings, while Lisp macros operate on a parse tree.

8
votes

I'm a Forth implementor and have broad experience in Forth, half a dozen implementations, a few hundred projecteuler problems. I also did a small object oriented extension (small, i.e. a dozen lines or so). My experience in LISP is much more at the course level, but I think it is fair to say that the meta programming facilities of LISP are more systematic, and in practice more powerful.

It is relatively easy to build abstractions on top of abstractions in LISP. In Forth if I want to define a matrix on a linear space defined by objects with non-trivial definitions .. I switch to Python.

The reason is also evident, at least to me. The creators of LISP where mathematicians, while Chuck Moore is the ultimate example of a practical programmer, never wasting his time on a theoretical problem.

This extends to this question in the following way. A lisp macro has a structure in the context of Lisp and at least suggests a meaning that is in line with general lisp principles. A Forth immediate word is just another program and can mean and do anything, including making a dogs dinner out of it.

3
votes

Sorry if the discussion bellow may seem a little bit vague, but there is too much to say.

I have only theoretical knowledge of Lisp, not hands on.

On the other side, Forth could have (but normal Forth hasn't) a complete metaprogramming inside the language. But metaprogramming is contemplated and possible but without a coherent syntax. I think the same happens in Lisp.

I have implemented a very clean solution with includes that possibility in a small paradigm of Forth like language. In order to have metaprogramming we should be able to refer to what we write. So when we write a program to be executed immediatelly as:

bread eat

we should be able too to refer to the same phrase with the intent instead of executing it to keep it for later reference. That could be done writing e.g.

{ bread eat } 

The phrase above could have as consequence to leave the created object on the stack. But as we created a new word as { and } we have the right to refer to that too.

So, we could like to refer to:

{ bread 

How could we refer to that ? A tentative syntax is: {{ { bread }}.

If we give the name XXX to the previous phrase we could write the initial phrase as:

XXX eat }

and the phrase above should work correctly in leaving on the stack the

{ bread eat }

As I don't know if what I say is exactly what are you looking for let it suffice to say that by the above reasoning and their implementation inside Forth each word gets an execution level and that defines which is the level of metaprogramming of the word.

Obviously, we have the first infinity level and every successive level. So execution levels are based on the mathematical infinity.

I have implemented the above inside a kind of Forth and at the first level (bellow infinity) everything works smoothly. So for example a am able to change the syntax of:

{ bread eat } { tomatos eat } x 3 = if 

into:

{ bread eat | tomatos eat } x 3 = if 

That is done by defining | as } { as bellow:

{{ } { }} "|" define

or if you like it better as:

2{ } { 2} "|" define 

The method above takes inside the language with a correct syntax the meta language and makes it language.

So in my opinion, both Lisp and Forth have the possibility of metaprogramming, but both lack that possibility as an integrating part of the language.

I have more details on that on napl.wikispaces.com.