Live data from Hacker News

Clojure macros continue to surprise me

tonsky.me

1–10 of 31 posts

Re: Clojure macros continue to surprise me

#4
> What if our macro read the source file?

> Like, actually went to the file system, opened a file, and read its content? We already have the file name conveniently stored in file, and luckily Clojure keeps sources around.

> So this is what I ended up with:

> (defn slurp-source [file key]

Looks like a function to me (which is good).

Re: Clojure macros continue to surprise me

#7

> What if our macro read the source file? > Like, actually went to the file system, opened a file, and read its content? We already have the file name conveniently stored in file , and luckily Clojure keeps sources around. > So this is what I ended up with: > (defn slurp-source [file key] Looks like a function to me (which is good).

it can't be a function because the source is only guaranteed to be available at compile time, rather than at runtime.

Re: Clojure macros continue to surprise me

#8
post #7

> What if our macro read the source file? > Like, actually went to the file system, opened a file, and read its content? We already have the file name conveniently stored in file , and luckily Clojure keeps sources around. > So this is what I ended up with: > (defn slurp-source [file key] Looks like a function to me (which is good).

it can't be a function because the source is only guaranteed to be available at compile time, rather than at runtime.

A macro is a perfectly normal function. It's simply called at compile time, with its contents as its argument.

Re: Clojure macros continue to surprise me

#9
post #8
post #7

Earlier quoted context omitted.

it can't be a function because the source is only guaranteed to be available at compile time, rather than at runtime.

A macro is a perfectly normal function. It's simply called at compile time, with its contents as its argument.

no you're misunderstanding me.

I'm saying that the macro's purpose is to read the source file and produce something at compile time. It's not a "normal" (read: runtime) function, as this feature cannot be implemented using a function that only executes at runtime.

Re: Clojure macros continue to surprise me

#10
post #9
post #8

Earlier quoted context omitted.

A macro is a perfectly normal function. It's simply called at compile time, with its contents as its argument.

no you're misunderstanding me. I'm saying that the macro's purpose is to read the source file and produce something at compile time. It's not a "normal" (read: runtime) function, as this feature cannot be implemented using a function that only executes at runtime.

Sure, but the macro function is a normal function - it has inputs, outputs, and (preferably) should be pure. There's nothing special about the macro function itself, really.

You can see it explicitly in Common Lisp, where you can easily access and replace a macro-function with a custom one that you DEFUN yourself, like this.

    CL-USER> (defun my-quote-fn (form env)
               (declare (ignore env))
               (destructuring-bind (operator &rest body) form
                 (assert (eq operator 'my-quote))
                 (list* 'quote body)))
    MY-QUOTE-FN
It's a perfectly normal function, I can call it right away:

    CL-USER> (my-quote-fn '(my-quote (+ 2 2)) nil)
    '(+ 2 2)
I can also tell the compiler that this perfectly normal function is a macro function...

    CL-USER> (setf (macro-function 'my-quote) #'my-quote-fn)
    #
...and the compiler will start using it to expand macros:

    CL-USER> (macroexpand-1 '(my-quote (+ 2 2)))
    '(+ 2 2)
    T
What is special about macros, and what you describe as the "feature that cannot be implemented", is the language's ability to call that function at compilation time and feed its output back into the compiler. This is the link that is missing in most programming languages.
Post reply on HN