8 ms·
can anyone expound on what he means when he says that lisp macros defined syntax but not semantics? --- > The folks at Rust tried to do a decent job of fitt
by andrekandre 5y ago
can anyone expound on what he means when he says that lisp macros defined syntax but not semantics?
---
> The folks at Rust tried to do a decent job of fitting macros in the language.
> Other languages, like all of the Lisp family, managed to fit them in more gracefully, but they had a way of defining syntax where the syntax was almost entirely free of semantics. And in most languages, syntax and semantics kind of go hand in hand.
- discreteevent 5y agoAn if statement and a function call have different forms in C. They have the same form/syntax in lisp. It's like the power of everything is a file/bytestream in unix. Because everything has the same form (uniform interface) then if you write a tool it can be made to work on everything. Grep works with all processes because they all have a uniform output stream. Macros in lisp work with all constructs in the language. Usually the basic form has to be quite primitive to do this. If it is too primitive you end up with what is known as a "turing tar-pit". But people can fall in love with the power of this uniform interface so much that they do not realize that they have ended up with a tar-pit at a high level. This can happen with macros but it doesn't have to.
- andrekandre 5y agomakes sense, it seems a fundamental tension within lisp itself as another commenter said "everything is eventually a list in lisp" then i guess macros have to be the same maybe to support semantics "this is an if statement" could be some kind of metadata on the macro i suppose?
- magpi3 5y agoI am also not sure, but in compiler design semantic analysis includes checking to see variables match their types, and obviously lisp macros are partially so powerful because their is no type checking. For me this was the biggest challenge when I was introduced to lisp: everything is just a list. Powerful, yes, but in other languages the ground felt firmer underneath my feet when I knew a class was a class, a struct was a struct, and array was an array, all with their own unique syntax. In lisp everything just looks the exact same. That is part of why it is so powerful, but at the cost of semantical references that can help users understand a lisp program.
- rjsw 5y agoEither you are very old or you got a poor introduction to Lisp. It has had arrays, structures and classes for a long time.
- magpi3 5y agoI know, but syntactically speaking, when looking at a program, it is always just lists embedded in lists. That is the lack of semantic references I am thinking about. When I talk about being feeling grounded, I mean seeing a distinguishable syntactic structure that gives me a (semantic) reference point for what I am looking at.
- andrekandre 5y agothis helped it click for me, thanks
- mschaef 5y agoI may be imposing my own views on his wording, but my interpretation is that his concern is related to the fact that macros have similar syntax to everything else in the language. Consider these two forms: > (and a b c) > (and* a b c) Can you tell by looking that the the first is a macro and the second is a function? The first short circuits and evaluates only the argument forms it needs and the second always evaluates all three. That's a big difference, and not at all obvious from the syntax. In fact, it's hidden by the syntax, because the syntax is exactly the same for each. Macros are part of the power of Lisp, but they change the normal rules of evaluation (the semantics) in ways that are not necessarily obvious unless you know the specific definitions behind each symbol in function position.
- andrekandre 5y agothanks, i think that makes it more clear for ^^
- kazinator 5y agoWe can usefully be both a macro/operator and function under the same symbol: This is the TXR Lisp interactive listener of TXR 268. Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet. 1> (special-operator-p 'and) t 2> (fboundp 'and) t 3> (fun and) #<intrinsic fun: 0 param + variadic> 4> (and 23 nil (prinl 42)) nil 5> (call 'and 23 nil (prinl 42)) 42 nil 6> [and 23 nil (prinl 42)] 42 nil 7> [mapcar if '(nil t t nil) '(1 2 3 4) '(a b c d)] (a 2 3 d) 8> (if t (prinl 'true) (prinl 'false)) true true 9> [if t (prinl 'true) (prinl 'false)] true false true If we use the functional brackets, all arguments are evaluated the same way, and the leftmost value is treated as a callable object applied to the remaining values. A symbol in the leftmost position of [...] is never treated as a macro (other than symbol macro) or special operator, even if it has a such a binding.