tags:

views:

121

answers:

4

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?

A: 

I would make its signature be something like

(runner alen blen op)

example:

(runner 10 10 +)

glowcoder
but what if I want to do: (runner a b (+ (- a b) (- b a))
JBristow
The concept you're missing is that a complex operation or a simple operation are both just operations - you're feeding [1-10][1-10] into a function - whether it's simple or complex doesn't matter as long as it takes two arguments.
glowcoder
Lol and I can't help but notice... `(+ (- a b) (- b a))` always evals to 0 :) but I understand what you're saying.
glowcoder
ok, but that doesn't account for (runner able baker (charlie able baker)) returning the same output as (runner foo bar (charlie foo bar) and (runner foo bar (baz foo bar)) returning a different output
JBristow
A: 

I'm not really sure i'm answering the correct question. I'm thinking "if i pass a function a symbol instead of a value how can it use the value that symbol represents? is that close?

(def a 4)
(defn my-inc [x] (+ (eval x) 1))
user> (my-inc 'a)
5

I'm sure there is a more elegant way than using eval.

Arthur Ulfeldt
A: 

It isn't clear enough to me what you're trying to achieve, but the following is an answer to what I guess is your question:

user=> (declare a b)
#'user/b
user=> (defn runner [] (+ a b))
#'user/runner
user=> (binding [a 1 b 2] (runner))
3
user=> (binding [a 2 b 3] (runner))
5

Note that the above style is likely not what you ought to be doing. Ask a better question and we'll give you better answers.

Alex Taggart
+4  A: 

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.

Brian Carper
It's not the answer I was looking for, but I was asking the wrong question. Thank you for providing a path to enlightenment.
JBristow