Hacker News new | ask | show | jobs
by 6thaccount2 2496 days ago
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)

2 comments

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.