6 ms·
To me, the entire point of Lisp, the thing that sets it apart from other languages, is unhygeinic macros. Since that is my view, I can only recommend Common Lis
by tines 6y ago
To me, the entire point of Lisp, the thing that sets it apart from other languages, is unhygeinic macros. Since that is my view, I can only recommend Common Lisp. CL is the opposite of modern, but just because something is modern doesn't make it good, nor does old make bad.
- bjoli 6y agoAs someone who has written a lot of CL and now deals mostly in scheme, why is an unhygienic macro system important? I don't think it matters much, and frankly I think something like vanilla syntax-case isn't hygienic enough. Either I don't want to care about accidentally capturing identifiers (and be very explicit when I do want it - Day like in srgi-72), or I want to have a system where I deal with explicitly (defmacro) Which I am using matters very little.
- varjag 6y agoIn a lisp-1 like Scheme it's a lot easier to shoot yourself in the foot with unhygienic macros.
- bjoli 6y agoI don't think that matters. Either you write a macro that is correct that won't break because of unwanted intersection with the place of expansion, or your macro is wrong. Edit: barring code-walking macro of course. Once you start using those, the bets are off. Edit2: of course, I don't think overwriting core forms count either. That is poor bedside manners :)
- varjag 6y agoRather than rehash the ancient argument once again, I defer to this post: https://www.xach.com/naggum/articles/3225161536947499@naggum.net.html https://www.xach.com/naggum/articles/3225161536947499@naggum... (KMP was on both Common Lisp and Scheme standard committees; Erik Naggum was an eloquent, if controversial, Lisp expert)
- tines 6y agoCorrect me if I'm wrong, but Lisp-2 vs. Lisp-1 has nothing to do with hygiene, it just splits Scheme's single problem (lexically binding values in macros) into two problems (lexically binding values in macros, and lexically binding functions in macros). The real problem, which Naggum includes, is the lack of GENSYM (if scheme indeed lacks it), and lack of first class symbols, as he mentioned.
- ska 6y agoIt's somewhat orthogonal, yes, but a lisp-1 just has more ways to run into the name collision.
- deckard1 6y ago> it just splits Scheme's single problem (lexically binding values in macros) into two problems (lexically binding values in macros, and lexically binding functions in macros). Bingo. Lisp-2 and GENSYM are attempting to solve the same issue in two different use cases. And, if I may add, GENSYM looks a bit lazy and half-assed next to the scortch-the-earth multiple namespaces of Lisp-2. It's like they blew up Lisp with dynamite and then sat down and said "whatever" when the same problem appears in macros. > The real problem, which Naggum includes, is the lack of GENSYM Guile Scheme has both GENSYM and DEFMACRO (unhygienic). I think quite a few Scheme systems err on the side of practical concerns. But that doesn't erase that fact that GENSYM is an ugly hack to get macros to work.
- varjag 6y ago> Lisp-2 and GENSYM are attempting to solve the same issue in two different use cases. Now this is… post-hoc, Lisp-2 is the original form of LISP and predates the concepts of macros. > And, if I may add, GENSYM looks a bit lazy and half-assed next to the scortch-the-earth multiple namespaces of Lisp-2. I would agree. However in reality we have a system that is half-assed vs a system that nobody likes to use.
- lispm 6y ago
- Jtsummers 6y agoAs an attempt at an answer: Unhygienic macros offer you more "power". With care, or another macro, you can express exactly the things you want with hygienic macros in a system like CL which lacks them, but the reverse isn't true. I cannot think of anything off the top of my head which would be particularly useful with unhygienic macros, but there probably is a use-case. My best guess (and just a guess) might be the SERIES and SCREAMER packages which redefine defun, but I could see it going both ways. A hygienic macro within the SERIES package would know the local definition and use it, but one from without would use cl:defun. With either hygienic or unhygienic macros this can create problems as in either case you may think you're using a particular defun when you're really using the other. NB: My CL macros are written carefully so they'd be roughly equivalent to the hygienic macros of Scheme, but with more boilerplate. At least when it comes to most variables, but I don't take care to ensure the functions used in my macros are not replaced in the local context where they're used.
- bjoli 6y agoI don't believe anything that can be written with unhygienic macros can't be written in a hygienic macro system. Macros written using implicit renaming is written just like CL macros, and with enough libraries you can do something similar with syntax-case. Heck, implementing an unhygienic defmacro over a regular lambda is something like 7 lines of syntax-case. In guile you could even use lambda* to get optional and keyword arguments.
- Jtsummers 6y agoSo, again, I don't think I know for certain why I'd want to do this, but here's an example of different behavior with the two: (defmacro my-not (x) `(not ,x)) (flet ((not (x) x)) (my-not 't)) In a hygienic macro system, that local definition of not will have zero impact on the execution. In an unhygienic macro system, that local definition is used instead of what the macro writer probably intended. That's a stupid, trivial example that would hopefully never be written. My best guess for wanting something like this, per my previous comment, would be a system like SCREAMER or SERIES which could make use of this local redefinition to produce a different-than-standard behavior. How would you write a hygienic macro which would make use of the local redefinition of not without also having to pass the redefinition to the macro?
- tines 6y agoThe unhygeinic part isn't as important as the fact that CL's macros (and other macro systems) are not simple pattern matching and substitution. But the lack of hygiene completes the circle for the concept that the program is simply a data structure, and macros are just imperative functions from syntax to syntax, and they can do anything that a normal function can do, like make HTTP requests. The destruction of the distinction between your code and the compiler, and the recursive relationship between the reader (and CL has reader macros, another dimension), macroexpander, and evaluator, is what is so mind-opening about lisp to me, and CL embodies that trifecta with the most ideological purity (imo).
- bjoli 6y agoIf you are arguing defmacro vs. syntax-rules you are indeed correct. The lowest common denominator of the scheme macro world is indeed a pattern substitution one (with hygiene). No procedure application at expansion time allowed. However, all schemes include a lower level macro system that allows you to break hygiene when you want to, most of them by asking explicitly (explicit renaming macro systems being an exception). r6rs, a standard that was disliked by some, standardises a lower level macro system called syntax-case that superficially looks the same as syntax-rules but gives you all the power of unhygienic macro systems (in guile for example, the old unhygienic defmacro is implemented using syntax-case. A very trivial thing to do, I might add). So, to re-hash: syntax-case macros are procedural. They allow for the full power of scheme at expansion time, and allows you to introduce bindings unhygienically using datum->syntax.
- deleted 6y ago[deleted]
- iainctduncan 6y agoThere are various hybrid schemes that support CL style macros. I'm using S7 myself, because embedding in a C host is what I'm after. I love it, it has support for CL macros with gensym and first class environments, and embeds easily in C.
- tines 6y agoWhat's S7? I've never heare of it.
- Jtsummers 6y agoA reference to this Scheme implementation: https://ccrma.stanford.edu/software/snd/snd/s7.html https://ccrma.stanford.edu/software/snd/snd/s7.html And from GP's own site (presumably, name is the same): https://iainctduncan.github.io/scheme-for-max-docs/s7.html https://iainctduncan.github.io/scheme-for-max-docs/s7.html
- iainctduncan 6y agoIt's a minimal embeddable Scheme created by Bill Schottstaedt at CCRMA, the Stanford computer music centre. it's similar in scope to Guile or TinyScheme (from which it was originally forked), and is linguistically similar to Clojure and Janet in that it is fundamentally Scheme, but borrows heavily from Common Lisp (keywords, environments, CL macros). It's mostly used in computer music projects (Common Music, Snd, Radium, and others), but not only - there are some folks on the mailing list who use it as an embeddable DSL for "regular" engineering projects too. I built Scheme For Max on S7, and have been very happy with the choice for my constraints.