OK, quindi sarebbe facile eseguire la propria funzione con l'applicazione all'interno, oppure utilizzare una versione di reverse dedicata che funziona meglio (ma solo) nelle stringhe. Tuttavia, le cose principali da considerare qui sono l'arità (quantità e tipo di parametri) della funzione str e il fatto che il reverse funzioni su una raccolta.
(doc reverse)
clojure.core/reverse
([coll])
Returns a seq of the items in coll in reverse order. Not lazy.
Ciò significa che il contrario non funziona solo sulle stringhe, ma anche su tutte le altre raccolte. Tuttavia, a causa inverso si aspetta una raccolta come parametro, si tratta di una stringa come un insieme di caratteri
(reverse "Hello")
e restituisce uno pure
(\o \l \l \e \H)
Ora, se abbiamo appena sostituiamo le funzioni per la raccolta, si può individuare la differenza:
(str '(\o \l \l \e \H))
"(\\o \\l \\l \\e \\H)"
mentre
(str \o \l \l \e \H)
"olleH"
La grande differenza tra i due è la quantità di parametri. Nel primo esempio, str accetta un parametro, una raccolta di 5 caratteri. Nel secondo, str accetta 5 parametri: 5 caratteri.
Cosa si aspetta la funzione str?
(doc str)
-------------------------
clojure.core/str
([] [x] [x & ys])
With no args, returns the empty string. With one arg x, returns
x.toString(). (str nil) returns the empty string. With more than
one arg, returns the concatenation of the str values of the args.
Così, quando si dà a un parametro (una raccolta), tutti i ritorni str è un toString della collezione. Ma per ottenere il risultato desiderato, è necessario alimentare i 5 caratteri come parametri separati per str, invece della raccolta stessa. Applica è la funzione che viene utilizzata per "entrare" nella raccolta e farlo accadere.
(apply str '(\o \l \l \e \H))
"olleH"
Funzioni che gestiscono più parametri separati spesso visto in Clojure, quindi è bene rendersi conto quando e perché è necessario utilizzare applicarsi. L'altro lato da capire è, perché l'autore della funzione str ha fatto accettare più parametri invece di una collezione?Di solito, c'è una buona ragione. Qual è il caso d'uso prevalente per la funzione str? Non concatenare sicuramente una raccolta di caratteri separati, ma concatenando valori, stringhe e risultati delle funzioni.
(let [a 1 b 2]
(str a "+" b "=" (+ a b)))
"1+2=3"
E se avessimo uno str che ha accettato una singola raccolta come parametro?
(defn str2
[seq]
(apply str seq)
)
(str2 (reverse "Hello"))
"olleH"
Cool, funziona! Ma ora:
(let [a 1 b 2]
(str2 '(a "+" b "=" (+ a b)))
)
"a+b=(+ a b)"
Hmmm, ora come risolvere quello? :)
In questo caso, fare in modo che str accetta più parametri che vengono valutati prima dell'esecuzione della funzione str, fornisce la sintassi più semplice. Ogni volta che è necessario utilizzare str su una raccolta, applicare è un modo semplice per convertire una raccolta in parametri separati.
Realizzare uno str che accetta una raccolta e fare valutare ogni parte all'interno richiederebbe uno sforzo maggiore, darebbe una mano solo in casi di utilizzo meno comuni, comporterebbe un codice o una sintassi più complicati o limiterebbe la sua applicabilità. Quindi potrebbe esserci un modo migliore per invertire le stringhe, ma invertire, applicare e str sono i migliori in quello che fanno.
Ah ha senso, grazie. Sono ancora un po 'troppo radicato nell'universo di Haskell dove le stringhe sono solo liste collegate – djhworld