2010-07-27 10 views
6

Quiero ser capaz de hacer lo siguiente pseudocódigo:¿Cómo paso las variables como nombres de variable a una función?

  1. pase en un símbolo.
  2. Pase en el símbolo b.
  3. Pase una expresión usando ayb
  4. Al cambiar el valor de a y b, imprima la salida de c en cada momento.

Idealmente, me gustaría que la firma a parecerse a:

(runner a b (+ a b)) 

pero no estoy seguro de que me estoy acercando esto correctamente ... He intentado cambiar la función a

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

y esto más complicado ejemplo:

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

pero esto hace un + en 'a y' b antes de entrar en el corredor.

Aquí está mi primer intento en algún clojure:

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

Qué concepto de clojure me falta?

Respuesta

4

Los argumentos de función siempre se evalúan antes de llamar a la función. Si desea aplazar la evaluación o representar algún cálculo o código como un objeto, usted tiene algunas opciones:

  1. utilizar una función (ver mi código de abajo)
  2. utiliza una macro y un empalme de un código en alguna otra código que genera la macro
  3. Código de acceso como una lista de citas, y eval.

Usar una función es lo que quiere hacer el 99% del tiempo. 1% de las veces, querrás macros. Nunca debe necesitar eval a menos que esté generando código en tiempo de ejecución o haciendo cosas muy complicadas.

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 

Esto también se podría escribir como (runner #(+ %1 %2) o incluso simplemente (runner +).

No es necesario pasar "a" y "b" en la función como argumentos. doseq y for introducen sus propios nombres locales, de ámbito léxico para las cosas. No hay ninguna razón por la que deberían usar a y b; cualquier nombre servirá Es lo mismo para fn. Usé x y y aquí porque no importa.

que podría haber usado a y b en el cuerpo fn así, pero habría sido un diferentea y b que los doseq la ve. Es posible que desee leer en scope si esto no tiene sentido.

+2

No es la respuesta que estaba buscando, pero estaba haciendo la pregunta incorrecta. Gracias por proporcionar un camino hacia la iluminación. –

0

yo haría su firma sea algo así como

(runner alen blen op)

ejemplo:

(runner 10 10 +)

+0

pero lo que si quiero hacer: (ab corredor (+ (- ab) (- BA)) –

+0

El concepto que se está perdiendo es que una operación compleja o una simple operación están a sólo operaciones - que' Al alimentar [1-10] [1-10] en una función, ya sea simple o compleja, no importa, siempre que lleve dos argumentos. – corsiKa

+0

Lol y no puedo dejar de notar ... '(+ (- ab) (- ba)) 'siempre evalúa a 0 :) pero entiendo lo que estás diciendo. – corsiKa

0

No estoy realmente seguro de que estoy respondiendo a la pregunta correcta. Estoy pensando "Si paso una función de un símbolo en lugar de un valor cómo puede utilizar el valor que representa el símbolo? Está tan cerca?

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

Estoy seguro de que hay una manera más elegante que el uso de eval .

0

no es lo suficientemente claro para mí lo que estamos tratando de lograr, pero lo que sigue es una respuesta a lo que supongo que es su pregunta:

 
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 

Tenga en cuenta que el estilo anterior es probable que no lo que deberías estar haciendo. Haz una pregunta mejor y te daremos mejores respuestas.

Cuestiones relacionadas