Hacker News new | ask | show | jobs
by zimablue 2496 days ago
You couldn't write it as a function, unless you pass in the 1+2 part to an outer function (macro) as either a list of arguments (1, math.add, 2) or a string (+you have an eval fn).

At that point you're emulating lisp without the elegance, and the first approach is only possible because functions are first class objects. If you were trying to rearrange an expression that had control flow or keywords in it (eg. Modify the behaviour of an if) then you would have to reify the "if" (change the original code so it had a class to represent the if not use the keyword). So you're kind of reinventing lisp by wrapping every part of your language as an object

1 comments

I'm apparently too stupid for you :). Please excuse my ignorance. Why can't you do something like the below?

(defun swap (x y) (y x))

Then you can call it like:

(swap (2 3)) => (3 2)

In the example we wanted to be able to call (1 + 2) and have it evaluate to 3.

   (defn swap [x]
      (list (second x) (first x) (last x)))

   (swap (1 + 2))
   =>Exception! 1 isn't a function.
Clojure tried to evaluate it's argument to swap, and the argument was (1 + 2), which is a function call, where the function is 1 and the arguments are + and 2.

So we quoted it in the function call by putting ' in front of the list '(1 + 2):

    (swap '(1 + 2))
    => (+ 1 2)
Here, we stll didn't get 3 as our output... We got (+ 1 2), which is a list. Because the function returned a list, it didn't return code! It might look like code, but it's not code! It's a list.

So if I was to

   (+ (swap '(1 + 2)) (swap '(3 + 4)))
   => Crashes! Can't convert  alist to a number.
Because what it actually runs is

   (+ '(+ 1 2) '(+ 3 4))
Whereas with the macro

   (+ (swap (1 + 2)) (swap (3 + 4)))
   => 10
Works because the macro gets expanded BEFORE compile time, and our swap code gets replaced out with the code the macro generates!

    (swap (1 + 2))
actually compiles as:

    (+ 1 2)
SO at runtime, that will be 3.
In clojure if the reader (compiler) ever sees a list like `(2 3)` it evaluates it as a function call with the first item as the function so you'd need `'(2 3)` or `(list 2 3)` to generate a list literal (or more often `[2 3]` as a vector type in clojure).

You could do `(defn swap [the-list] ((second the-list) (first the-list)))` (which would invoke the second item as a function on the first item). It comes down to is the list a literal list as a parameter to something or is the first item a function to be invoked.