如何将变量作为变量名称传递给函数?

时间:2010-07-27 18:13:04

标签: clojure

我希望能够执行以下伪代码:

  1. 传递符号a。
  2. 传递符号b。
  3. 使用a和b
  4. 传入表达式
  5. 当我更改a和b的值时,请在每个时刻打印c的输出。
  6. 理想情况下,我希望签名看起来像:

    (runner a b (+ a b))
    

    但我不确定我是否正确接近这个...我已经尝试将功能更改为

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

    这个更复杂的例子:

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

    但是在踏入跑步者之前,这在'a和'b上做了+。

    这是我对某些clojure的第一次尝试:

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

    我错过了什么概念的clojure?

4 个答案:

答案 0 :(得分:4)

在调用函数之前,始终会评估函数参数。如果您想推迟评估或将某些计算或代码表示为对象,您可以选择以下几种方法:

  1. 使用功能(请参阅下面的代码)
  2. 使用宏并将一些代码拼接到宏生成的其他代码中
  3. 将代码作为引用列表传递,并将eval传递给它。
  4. 使用函数是你想要做的99%的时间。 1%的时间,你需要宏。除非你在运行时生成代码或做了非常棘手的事情,否则你永远不需要eval

    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
    

    这也可以写成(runner #(+ %1 %2),甚至只是(runner +)

    无需将“a”和“b”作为参数传递给函数。 doseqfor为事物介绍他们自己的本地词汇范围名称。他们没有理由使用ab;任何名字都可以。 fn也是如此。我在这里使用了xy因为没关系。

    我也可以在a正文中使用bfn,但他们本来就是不同的 abdoseq看到的{{1}}。如果没有意义,您可能需要阅读scope

答案 1 :(得分:0)

我会使其签名类似于

(runner alen blen op)

示例:

(runner 10 10 +)

答案 2 :(得分:0)

我不确定我是否回答了正确的问题。我在想“如果我传递一个符号而不是值的函数,它如何使用符号所代表的值?那么接近吗?

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

我确信有比使用eval更优雅的方式。

答案 3 :(得分:0)

我不清楚你想要达到的目标,但以下是我猜你的问题的答案:

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

请注意,上述风格可能不是您应该做的。问一个更好的问题,我们会给你更好的答案。