2010-07-27 9 views
6

Voglio essere in grado di fare il seguente pseudocodice:Come si trasmettono le variabili come nomi di variabili a una funzione?

  1. Pass simbolo a.
  2. Passare nel simbolo b.
  3. Passare in un'espressione utilizzando aeb
  4. Mentre cambio il valore di aeb, stampa l'output di c in ogni momento.

Idealmente, vorrei che la firma per assomigliare:

(runner a b (+ a b)) 

ma non sono sicuro che mi sto avvicinando correttamente questo ... Ho provato a cambiare la funzione di

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

e questo complica esempio:

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

ma questo fa un + su 'a e' b prima di entrare nel corridore.

Ecco il mio primo tentativo di un certo clojure:

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

Quale concetto di clojure che mi manca?

risposta

4

Gli argomenti di funzione vengono sempre valutati prima che venga richiamata la funzione. Se si vuole rinviare valutazione o rappresentare qualche calcolo o il codice come un oggetto, avete alcune opzioni:

  1. utilizzare una funzione (vedi il mio codice qui sotto)
  2. utilizzare una macro e Splice po 'di codice in qualche altro codice che genera la macro
  3. Codice di accesso come elenco quotato e eval it.

L'utilizzo di una funzione è ciò che si desidera fare il 99% delle volte. L'1% delle volte, vorrai macro. Non dovresti mai aver bisogno di eval a meno che tu non stia generando codice in fase di esecuzione o facendo cose molto difficili.

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 

Questo potrebbe anche essere scritto come (runner #(+ %1 %2) o anche semplicemente (runner +).

Non è necessario passare "a" e "" nella funzione come argomenti. doseq e for introducono i loro nomi locali, lessicalmente con scope per le cose. Non c'è ragione per cui dovrebbero usare a e b; qualsiasi nome farà. È lo stesso per fn. Ho usato x e qui perché non importa.

ho potuto ho usato a e b nel corpo fn pure, ma sarebbe stato un diverso a e b rispetto a quelli del doseq vede. Si consiglia di leggere su scope se questo non ha senso.

+2

Non è la risposta che stavo cercando, ma stavo facendo la domanda sbagliata, grazie per aver fornito un percorso verso l'illuminazione. –

0

vorrei fare la sua firma sia qualcosa di simile

(runner alen blen op)

esempio:

(runner 10 10 +)

+0

ma cosa succede se voglio fare: (corridore ab (+ (- ab) (- lettera b)) –

+0

Il concetto che ti manca è che un'operazione complessa o di una semplice operazione sono entrambi a soli operazioni - si' reinserire [1-10] [1-10] in una funzione, indipendentemente dal fatto che sia semplice o complessa, non importa purché ci siano due argomenti: – corsiKa

+0

Lol e io non possiamo fare a meno di notare ... '(+ (- ab) (- ba)) "evalora sempre a 0 :) ma capisco cosa stai dicendo. – corsiKa

0

Io non sono davvero sicuro che sto rispondendo alla domanda corretta. Sto pensando "se mi passa una funzione un simbolo invece di un valore come può utilizzare il valore che rappresenta il simbolo? È così vicino?

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

Sono sicuro che ci sia un modo più elegante rispetto all'utilizzo di eval .

0

non è abbastanza chiaro per me quello che si sta cercando di raggiungere, ma il seguente è una risposta a quello che io immagino è la tua domanda:

 
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 

nota che lo stile di cui sopra è probabile che non cosa dovresti fare. Fai una domanda migliore e ti daremo risposte migliori.

Problemi correlati