Actually macros are not first-class in Arc (though they are stored in the same namespace as everything else, unlike in Scheme). You can't return one from a function, for instance. They were a feature of early implementations (they're mentioned in various places in old stuff related to its development), but they were cut before the first release. When I asked pg why he removed them, his answer was:
> I don't remember. It was either because they were useless or confusing or intellectually inelegant.
Having experienced first-class macros in my own Lisp implementation, I'm inclined to agree. Though there are various promises of efficient implementations scattered through the internet, nobody actually goes into enough detail to explain it. Non-first-class macros are the way to go for efficiency, at least, and first-class macros themselves are fairly useless.
Well, here's an example where not having first-class macros is confusing:
in takes any number of arguments, and returns whether the first argument is repeated in the rest of them:
arc> (in 2 1 2 3)
t
arc> (in 0 1 2 3)
nil
Ok, let's say I have a list, and I want to find out whether something is in it:
arc> (apply in 2 (list 1 2 3))
Error: "Function call on inappropriate object #(tagged mac #<procedure: in>) (0 1 2 3)"
Oh dear. That's not right.
The solution, at least in Arc, is to use mem:
arc> (mem 2 (list 1 2 3))
(2 3)
It returns the first sub-list of its second argument such that the car of the returned list is the element searched for -- or 'nil if the element isn't in the list. So yes, you can make it work, in this case. But it's surely more confusing than having (apply in 2 (list 1 2 3)) work.
> Non-first-class macros are the way to go for efficiency, at least, and first-class macros themselves are fairly useless.
It's true that non-first-class macros can be more efficiency. But first class macros can benefit from it's nature - a lexical function with environment. Construct such macros can be fancy.
There is something very wrong with the concept of 'runtime' macros. How is a 'runtime' macro any better than a function/procedure? TBH, I have no idea what a use case would be for a 'runtime' macro. A macro is generally a compile-time source transformation. If you need that at runtime, use EVAL.
To me it's because they provide a simple way to solve the hygiene problem in an interpreter.
That is, it's easier to implement first-class macros (which allow hygiene) in an intepreter , than it is to implement scheme-style non-first-class hygienic macros...
I only say this because I know how to implement first-class macros, but I don't really understand how Scheme's hygienic macros work...
One difference is that macros (whether run-time or compile-time) use a call-by-name evaluation strategy. Hence they are a form of lazy evaluation. Functions (in scheme and lisp) are call-by-value IIRC.
[+] [-] dpkendal|14 years ago|reply
> I don't remember. It was either because they were useless or confusing or intellectually inelegant.
Having experienced first-class macros in my own Lisp implementation, I'm inclined to agree. Though there are various promises of efficient implementations scattered through the internet, nobody actually goes into enough detail to explain it. Non-first-class macros are the way to go for efficiency, at least, and first-class macros themselves are fairly useless.
[+] [-] zck|14 years ago|reply
in takes any number of arguments, and returns whether the first argument is repeated in the rest of them:
Ok, let's say I have a list, and I want to find out whether something is in it: Oh dear. That's not right.The solution, at least in Arc, is to use mem:
It returns the first sub-list of its second argument such that the car of the returned list is the element searched for -- or 'nil if the element isn't in the list. So yes, you can make it work, in this case. But it's surely more confusing than having (apply in 2 (list 1 2 3)) work.[+] [-] wsxiaoys|14 years ago|reply
Actually you can, for example:
Above code are tested in tryarc.org.> Non-first-class macros are the way to go for efficiency, at least, and first-class macros themselves are fairly useless.
It's true that non-first-class macros can be more efficiency. But first class macros can benefit from it's nature - a lexical function with environment. Construct such macros can be fancy.
[+] [-] leppie|14 years ago|reply
[+] [-] Patient0|14 years ago|reply
That is, it's easier to implement first-class macros (which allow hygiene) in an intepreter , than it is to implement scheme-style non-first-class hygienic macros...
I only say this because I know how to implement first-class macros, but I don't really understand how Scheme's hygienic macros work...
[+] [-] Oxryly|14 years ago|reply