Skip to content

Instantly share code, notes, and snippets.

@philoskim
Last active January 31, 2019 03:04
Show Gist options
  • Save philoskim/2b8f401c82a220f74d0e02832c8ebc54 to your computer and use it in GitHub Desktop.
Save philoskim/2b8f401c82a220f74d0e02832c8ebc54 to your computer and use it in GitHub Desktop.

Clojure and ClojureScript QnA

1. Macros in ClojureScript

1.1. Question

Clojure, ClojureScript 매크로 동작이 서로 다른가요?

"Clojure Programming" 에 나온 예제

(defmacro reverse-it [form]
  (clojure.walk/postwalk #(if (symbol? %)
                            (symbol (clojure.string/reverse (name %)))
                            %)
                         form))

를 실행했는데 Clojure REPL에서는 잘 됐지만 CLJS REPL(lumo사용)에서는 제대로 동작을 안 하네요. 분명 뭔가 놓치고 있는데.. 뭔지를 모르겠습니다.

1.2. Answer

클로저스크립트의 매크로는 클로저에서와는 약간 다른 방식으로 처리됩니다.

클로저스크립트에서 매크로를 사용하려면, 매크로 코드는 *.clj 파일에 정의해 놓아야 합니다. 클로저스크립트 컴파일러가 매크로 코드를 만나면, 내부적으로 클로저 컴파일러를 호출해 매크로 확장을 한 후, 그 결과만을 넘겨받아 처리하기 때문입니다.

먼저 매크로를 .clj 파일에 정의해 놓습니다.

example.macro.clj
(ns example.macro
  (:require [clojure.string :as str]
            [clojure.walk :as walk]))

(defmacro reverse-it [form]
  (walk/postwalk #(if (symbol? %)
                    (symbol (str/reverse (name %)))
                    %)
                 form))

다음은 lumo REPL에서 매크로를 호출하는 예입니다. 이때 require가 아니라 require-macros를 사용해야 합니다.

$ ls -l
drwxr-xr-x  2 philos philos 4096  1월 31 11:21 example

$ ls example
macro.clj

$ lumo
Lumo 1.9.0
ClojureScript 1.10.439
Node.js v10.9.0
 Docs: (doc function-name-here)
       (find-doc "part-of-name-here")
 Source: (source function-name-here)
 Exit: Control+D or :cljs/quit or exit

cljs.user=> (require-macros '[example.macro :refer [reverse-it]])
nil

cljs.user=> (reverse-it
       #_=>   (qesod [gra (egnar 5)]
       #_=>     (nltnirp (cni gra))))
1
2
3
4
5
nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment