Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass variables as variable names to a function?

Tags:

clojure

I want to be able to do the following pseudocode:

  1. Pass in symbol a.
  2. Pass in symbol b.
  3. Pass in an expression using a and b
  4. As I change the value of a and b, print the output of c at each moment.

Ideally, I would like the signature to look like:

(runner a b (+ a b))

but I'm not sure that I'm approaching this correctly... I've tried changing the function to

(runner 'a 'b (+ 'a 'b))

and this more complicated example:

(runner 'a 'b (+ (* 'a 'b) 'a))

but this does a + on 'a and 'b before stepping into runner.

Here's my first stab at some clojure:

(defn runner [a b c] (
  (for [i (range 10)
        j (range 10)] (println i j (c i j))

What concept of clojure am I missing?

like image 264
Jon Bristow Avatar asked Jul 27 '10 18:07

Jon Bristow


1 Answers

Function arguments are always evaluated before the function is called. If you want to defer evaluation or represent some computation or code as an object, you have a few options:

  1. Use a function (see my code below)
  2. Use a macro and splice some code into some other code that the macro generates
  3. Pass code as a quoted list, and eval it.

Using a function is what you want to do 99% of the time. 1% of the time, you'll want macros. You should never need eval unless you're generating code at runtime or doing very screwy things.

user> (defn runner [f]
        (doseq [a (range 3)
                b (range 3)]
          (println a b (f a b))))
#'user/runner
user> (runner (fn [x y] (+ x y)))
0 0 0
0 1 1
0 2 2
1 0 1
1 1 2
1 2 3
2 0 2
2 1 3
2 2 4

This could also be written as (runner #(+ %1 %2) or even simply (runner +).

There is no need to pass "a" and "b" into the function as arguments. doseq and for introduce their own local, lexically scoped names for things. There's no reason they should use a and b; any name will do. It's the same for fn. I used x and y here because it doesn't matter.

I could've used a and b in the fn body as well, but they would have been a different a and b than the ones the doseq sees. You may want to read up on scope if this doesn't make sense.

like image 197
Brian Carper Avatar answered Oct 02 '22 01:10

Brian Carper