Hacker News new | ask | show | jobs
by S4M 3878 days ago
> Many languages have eval() where data can be treated as code.

I will just address this point, which IMHO is orthogonal to your question about the benefits of functional programming. Let me give you a simple example of macro: a macro print-variable that takes a variable and prints: "$variable = $value", where $variable is the variable name and $value its corresponding value. I wrote it on my Clojure REPL, and run it that way:

    user> (def x 4)
    #'user/x
    user> (print-variable x)
    x = 4
    nil 
In a language without macros, the function print-variable wouldn't have access to the string "x" once x has been defined. In a language with eval, you could do something like:

    def print-variable(variable_name):
        value = eval(variable_name)
        eval("print("+variable_name+"="+value+")")
But you would have to call that function with a string, which is not as elegant and can lead to errors as the string could be misspelled.

Now, I will show you the code of the macro in Clojure:

    (defmacro print-variable [variable]  
         `(println '~variable "=" ~variable))
What is does is take the variable you want to print, and defer its evaluation (~variable) only when you want to know what value is assigned to that variable. In the meantime, it can get the name of the variable ('~variable).

Here is what it does when I expand the macro:

    user> (macroexpand '(print-variable x))
    (clojure.core/println (quote x) "=" x)
The clojure compiler transforms the macro into the expanded code, and then injects it into the rest of the code.

Hope this helps.

1 comments

Your Python example wouldn't work. eval is still scoped lexically. You'd need to get current stack frame, get locals from the previous frame and only eval within these locals. That's what TCL `upvar` does, BTW.

Macros let you avoid this kind of problems when meta-programming (but then they bring their own problems: hygiene, for example).

Good point, I haven't really thought the Python example through. I can't find a quick fix now, so I leave it as an illustrative code (even that failing code is an inferior version of the macro, so...).