开发者

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

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开发者_StackOverflow中文版 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?


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.


I would make its signature be something like

(runner alen blen op)

example:

(runner 10 10 +)


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜