Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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



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)


Others have answered already, but I remember this being confusing for me. And sometimes it still is. I think the crux of it comes to two things. The first is that the text (f a b c) is evaluated as a function call with function 'f' receiving arguments a b and c. The second thing is that arguments are evaluated before they are passed into a function. So a b and c are evaluated first, and then given to 'f'. This is done recursively.

So (+ 1 2) first evaluates 1 and 2, which each evaluate to themselves and thus can't be simplified any further. They are then passed into '+'.

in (+ 1 (* 2 3)) the + is a function and the arguments are 1 and (* 2 3). 1 evaluates to itself. Evaluating (* 2 3) starts by evaluating 2 and 3, then applying them to '*' resulting in 6. So if we displayed an intermediate step, our form would now look like (+ 1 6), finally evaluating to 7.

To prevent the form (f a b c) from being treated as a function call, you can "quote" it by prefixing with a single quote (aka tick): '(f a b c). The evaluator now knows we intend that to just be data and not to evaluate it.

The exception to evaluating (f a b c) as a function call is if 'f' is a macro. In that case, the arguments a b and c are not evaluated and instead are passed into the macro as data.

Where this comes into play is if you want to programmatically change the code around before it's executed, and particularly where the arguments have side effects when they are evaluated (changing the state of something, like adding data to a database).


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: