Как передать переменные как имена переменных в функцию? - PullRequest
6 голосов
/ 27 июля 2010

Я хочу иметь возможность использовать следующий псевдокод:

  1. Передать символ a.
  2. Передать символ b.
  3. Передать выражение, используяa и b
  4. Когда я изменяю значения a и b, выводим выходные данные c в каждый момент.

В идеале мне бы хотелось, чтобы подпись выглядела следующим образом:

(runner a b (+ a b))

но я не уверен, что подхожу к этому правильно ... Я попытался изменить функцию на

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

и этот более сложный пример:

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

, но это делает a + на 'a и' b перед тем, как войти в бегун.

Вот мой первый удар при некотором замыкании:

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

Что я за замыселотсутствует

Ответы [ 4 ]

4 голосов
/ 27 июля 2010

Аргументы функции всегда оцениваются перед вызовом функции. Если вы хотите отложить оценку или представить некоторые вычисления или код в виде объекта, у вас есть несколько вариантов:

  1. Используйте функцию (см. Мой код ниже)
  2. Используйте макрос и объедините некоторый код в другой код, который генерирует макрос
  3. пароль в виде списка в кавычках и eval его.

Использование функции - это то, что вы хотите делать в 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" в функцию в качестве аргументов. doseq и for вводят свои локальные, лексически ограниченные имена для вещей. Нет причин, по которым они должны использовать a и b; подойдет любое имя. То же самое для fn. Я использовал x и y здесь, потому что это не имеет значения.

Я мог бы использовать a и b в теле fn, но они были бы отличными a и b от тех, что doseq видит. Вы можете прочитать о scope , если это не имеет смысла.

0 голосов
/ 27 июля 2010

Я не совсем уверен, что отвечаю на правильный вопрос. Я думаю: «Если я передам функции символ вместо значения, как она может использовать значение, которое представляет символ? Это близко?

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

Я уверен, что есть более элегантный способ, чем использование eval.

0 голосов
/ 27 июля 2010

Мне не совсем ясно, чего вы пытаетесь достичь, но ответ на ваш вопрос, как мне кажется, следующий:

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

Обратите внимание, что вышеприведенный стиль, вероятно, не то, что вы должны делать. Задайте лучший вопрос, и мы дадим вам лучшие ответы.

0 голосов
/ 27 июля 2010

Я бы сделал его подпись примерно такой:

(runner alen blen op)

пример:

(runner 10 10 +)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...