Common Lisp는 unhygienic macro이어서, symbol 겹침을 방지하려면 gensym을 사용해야 한다. 그런데 매크로 정의도 코드이므로 유연성이 높다.
Racket은 기본적으로 hygienic macro인데, 패턴 방식이라 만들기는 쉬운데 유연성은 낮다.
defmacro를 제공하기는 한다.
Clojure는 Common Lisp 방식인데 auto-gensym이라는 것이 있다. 매크로 정의 안에서 #으로 끝나는 변수는 gensym된 변수가 된다. 미리 let으로 gensym해서 만들어 놓을 필요가 없다. 그런데 auto-gensym은 defmacro 컴파일 시간에 미리 gensym하는 거라서 Common Lisp처럼 매크로 확장시마다 let으로 gensym하는 것과는 의미가 다르다.
참고: (출처: Clojure Guides: Language: Macros)
There is a shortcut: if a symbol ends in # within a syntax quote form, it will be expanded by the compiler into a gensym (also known as an auto-gensym):
(defmacro yes-no->boolean
[val]
`(let [b# (= ~val "yes")]
b#))
#'cljs.user/yes-no->boolean
(macroexpand-1 '(yes-no->boolean "yes"))
(cljs.core/let [b__2__auto__ (cljs.core/= "yes" "yes")] b__2__auto__)
The name that replaced b# was generated by the compiler to make unwanted variable capture very unlikely in practice, and impossible if all bindings are named with auto-gensym.
Theoretically, Clojure's approach to generating uncaptured gensyms (incrementing a global counter) can be circumvented via a mischievous macro or very bad luck.
Tip: Avoid code with __ in local binding names. This ensures auto-gensyms are never captured in unwanted ways.
'Programming' 카테고리의 다른 글
How to Make Racket Go (Almost) As Fast As C (1) | 2024.10.18 |
---|---|
Mojo vs Julia: Comparison of Two Powerful Languages (codeavail.com) (0) | 2024.10.07 |
Rust 언어의 단점 (0) | 2024.06.13 |
CodeConvert 소개 (0) | 2024.04.20 |
Python to Julia Converter (codeconvert.ai) (0) | 2024.01.30 |