Given a new context, why couldn't the same model have a decent shot at reviewing some results? It's not like they identify whether this output is from them and then go "yeah correct", that's not how they work.
Well, my main point is not to never use macros, but that in certain cases a language-native feature that can also solve a problem you would use a macro for, it's probably better (better debugging, error messages, etc).
And my other point was macro systems in other languages, which I believe are better, in part due to not having homoiconicity, like Scala or rust.
Well, I was talking about the fundamental part. Of course you can have more practical implementations, like Scala or rust's macro system, that gives you a proper typed AST.
I mentioned in other comment that homoiconicity doesn't necessarily make writing macros simpler. It makes writing trivial toy examples simpler.
But let's compare it to a modern macro system like rust's or scala's, where you get a typed object representation of the AST, and for anything non-trivial you are better off with this latter.
Also, arguably the best is to have certain features in the language itself, that can be used to build proper abstractions - so you don't have to resolve to using macros in its place.
Thank you for the reply, and I definitely agree with you on many points. I absolutely don't want to take away from Lisp that it is somehow uniquely elegant, and does have a mathematical beauty to it, this is certain.
I just feel this (and its practical ramifications) are often overexaggerated.
My issue is that a language is just as much about what it disallows, as much as about what it allows.
It's absolutely trivial to allow everything, you just have to make a Turing-complete extension either by design or accidentally.
It's much much harder to carefully choose more limiting primitives that only allow you to build stuff that keep certain important properties about them. You can't subtract stuff after the fact.
E.g. something like rust's borrow checker could not be realistically implemented as "a lisp" macro (what does lisp even mean in this case). For that to work you would literally build a rust compiler over s-expressions and you might as well leave off the s-expressions at that point.
And every part that was not compiled by that macro or whatever would be unsafe and could not interact with the "rust-lisp" compiled parts, as you can no longer assert anything about them (there is nothing mandating the usual single writer, xor multiple read-only references laws)
And that's just syntax, it doesn't give you a programming language at all.
JS is a dynamically typed language with prototypical inheritance objects that work like universal key-value maps for the most part. It is also mutable.
Clojure is a dynamically typed language with key-value maps. It is also immutable.
You can surely see where I'm going , the underlying semantic model is the meaningful part. Homoiconicity doesn't give you anything special if your language can parse itself and can eval code. It just makes these completely abstract implementations simpler.
Well, if we have a compiler that sees a constant value, it can completely optimize out one branch. But it of course depends on the semantics of the language.
But yeah you are right in case of a naive compiler.
Well, maybe because digital is better at showing small differences in this case? Like on a 50kmh road, dropping below 50 is quite noticeable in digital, less so with a line above or below another line.
But for the revs, I think it's quite clear that the analog is better.
Maybe one way to put it would be how important an exact value is? For the speed, it is. For revs, the relative value and its change is much more important and humans track movement much better.
There are plenty of languages with macros though, nothing special about lisps.
And no, language semantics absolutely don't compose. Like you can't just do some kind of optimization in one place if you do some mutation on it in another place. Optimizations work on global assumptions that every part of the codebase have to abide by. Any part not doing it will make the whole thing crumble - and "there is no stuck in lisp" is exactly why you can't have your cake and eat it too.
Well, compilers have layers - you ain't outputting assembly from the AST layer directly, usually there is some kind of IR. Like LLVM have plenty of layers.
And for a simple DSL you can usually just use a sufficiently expressive language, no need for macros. Like kotlin/Scala has html DSLs that look pretty decent.
For anything more complex though, you can't just "compose stuff", a type system is a global property so for that you literally have to write something way more complex than a local macro should contain.
So then what it is? Because otherwise it's a magical nothing-term to which everything lisp people like applies, but no criticism can ever reach it because "that's not really lisp, see it's different in this other implementation"
At the same time, you get a mushy tree as input, instead of a properly typed AST "object" with accessible "function name", "method parameters" everything that you can just refer to.
It will be the third arguments' 2nd arg with s-exprs, following your arbitrary pattern you figured you want to use. So it's very arguable which is easier to use, sure for some "party tricks" lisps will win, for anything more useful my vote would go with rust/Scala macros for sure. So again, you win nothing by homoiconicity, the by-the-compiler implemented parse function is more complex in rust, which is 100% abstracted away.
Well, as mentioned that's why you create two lambdas as the branches. This is pretty much what thunks are in some languages (like Haskell), so this example doesn't strictly require macros per se.
Can you expand on that? I am mildly experienced with Clojure, and much more so with the JVM and I see no reason for that to happen (besides perhaps some kind of module shenanigans or importing stuff that requires special flags?)
Define a goddamn language, syntax is not enough to define one! What are the semantics? Without that you are just talking about syntax trees like they would mean anything