Closed johnwcowan closed 3 years ago
I am not an expert on the issue, but it seems that the basic definition (avoid capture problem) is fulfilled. Can you please provide some more resources for your claim?
It sounds like you are also accusing Common Lisp hygiene of not being hygiene?
I think it's a fair assertion that Common Lisp - and by extension Janet-style macros are non-hygienic, whereas Scheme-style macros are hygienic. Indeed, Common Lisp programmers would argue that the lack of hygiene is what gives Common Lisp macros their power. I think it's perfectly reasonable to explain how to avoid unwanted capture in Common Lisp/Janet-style macros while avoiding the rather technical term "hygiene", which at least in common modern parlance refers to the Scheme-style macro system.
@subsetpark Thanks for the explanation. I was not aware of this higher Lisp game. Then maybe it makes sense to tame the docs, what is your opinion?
Well, I'm not sure if I know exactly what the offending language on the website is, anyway. The janet-lang.org repo has the following para:
After expansion, @code
y
wrongly refers to the @codex
inside the macro (which is bound to 8) rather than the @codex
defined to be 10. The problem is the reuse of the symbol @codex
inside the macro, which overshadowed the original binding. This problem is called the @link[https://en.wikipedia.org/wiki/Hygienic_macro#The_hygiene_problem]{hygiene problem} and is well known in many programming languages. Some languages provide complicated solutions to this problem, but Janet opts for a much simpler—if not primitive—solution.
Which is to say, it links to the Hygienic Macro wikipedia page to give a gloss on what the hygiene problem is - but it doesn't claim that the macro system in Janet is hygienic. Is there elsewhere that it makes that claim?
Edit: Maybe John is concerned that the heading "Hygiene" could be read as "How Janet is Hygienic" rather than "The Problem of Hygiene"?
You can manually escape functions and even other macros in the macro definition:
(defmacro my-mac
"Emits (+ x 1)."
[x]
~(,+ ,x 1))
In the above macro definition, +
is properly escaped - the functional value of +
is used, not the symbol '+.
(macex1 '(my-mac 11)) #-> (<function +> 11 1)
Nested macro "hygiene" is a bit more difficult but still doable - macros live in the function namespace, so we can manually apply
them (if needed). Internal macros in the core often do this.
(defmacro my-mac-uses-let
"A macro evaluates body where `x` is defined to be 10."
[& body]
(apply let ['x 10] body))
This is slightly different from Common Lisp because Janet is a Lisp-1, not a Lisp-2 (going on the premise that Janet is actually a Lisp, which is beside the point).
Now you could of course argue that this isn't "hygiene", and I don't even disagree. However, it is true that macros can be written to be hygienic - and I would say this is true in Common Lisp as well.
Either way, this is a WNF.
Well, I'm not sure if I know exactly what the offending language on the website is, anyway. The janet-lang.org repo has the following para:
After expansion, @code
y
wrongly refers to the @codex
inside the macro (which is bound to 8) rather than the @codex
defined to be 10. The problem is the reuse of the symbol @codex
inside the macro, which overshadowed the original binding. This problem is called the @link[https://en.wikipedia.org/wiki/Hygienic_macro#The_hygiene_problem]{hygiene problem} and is well known in many programming languages. Some languages provide complicated solutions to this problem, but Janet opts for a much simpler—if not primitive—solution.Which is to say, it links to the Hygienic Macro wikipedia page to give a gloss on what the hygiene problem is - but it doesn't claim that the macro system in Janet is hygienic. Is there elsewhere that it makes that claim?
If you link to something called #The Hygiene Problem
and you claim to have a solution to it, it seems to me that you are claiming the macro system is (when properly used withgensym
) hygienic. But Janet (and yes, Common Lisp as well) doesn't in fact offer a complete solution to the hygiene problem. What is more, the workarounds in Common Lisp that reduce the impact of the hygiene problem, namely being a Lisp-2 and storing symbols in packages, are not present in Janet.
I recommend that the section title be changed to "Variable Capture" and the following two sentences be removed:
This problem is called the
@link[https://en.wikipedia.org/wiki/Hygienic_macro#The_hygiene_problem]{hygiene problem}
and is well known in many programming languages.
Some languages provide complicated solutions to this problem, but Janet opts for a much
simpler—if not primitive—solution.
That is clearer, I think, and will dispose of this issue. There is also a typo in this section: change "more useful that a macro" to "more useful than a macro".
This has been addressed in https://github.com/janet-lang/janet-lang.org/commit/cf0b33ad98b0e1f8922c8e1970b78e5a4ae99d84 - I think it is important to leave in the reference to the hygiene problem, but I have renamed the section and made clear that we do not have hygienic macros as presented in the original paper.
@johnwcowan Let me know if there are any other issues here, otherwise feel free to close this issue.
EDIT: some awkward phrasing has been fixed as well in https://github.com/janet-lang/janet-lang.org/commit/f26aaed60fd22fff92b7d7c8aa11027c3b5af9d2
LGTM.
Gensym-based hygiene, such as Common Lisp prgrammers use, prevents the macro definition from accidentally affecting the macro call, but cannot prevent the macro call from affecting the macro definition. If the macro definition makes use of
+
, for example, it will not work correctly in a calling context where the user has rebound the meaning of+
.Modifying the handling of macro calls is insufficient to solve this problem: instead, it is necessary to apply a suitable hygienic expansion algorithm to all of the code. The simplest thing to do is to simply remove the claim that Janet macros can be hygienic from the documentation.