mercoledì 15 giugno 2011

Sintassi Alternatives lambda

La discussione sulla mailing list-dev lambda ha iniziato ad affrontare il problema di ciò che la sintassi del linguaggio Java per le espressioni lambda / letterali di funzione dovrebbe assomigliare. Vediamo un esempio un po non banale e cercare di prendere in giro i problemi fuori.
Il popolo Perl ha un ottimo esempio di qualcosa che utilizza una funzione fa riferimento in modo un po 'funzionale - la chiamano la Trasformata di Schwartz (ma credo che sia originariamente un trucco Lisp volte chiamato decorare-sort-undecorate). Poiché ci sono solo i polli ci JVM qui, l'ho riscritto in Clojure (in realtà è uno dei miei esempi nel capitolo 9 del libro).
Ecco un frammento di codice Clojure che definisce una funzione per eseguire la trasformazione di Schwartz. Fondamentalmente, essa fornisce un modo molto semplice di ordinamento di un elenco basato su una funzione ausiliaria (chiamata "funzione di codifica") forniti dal chiamante.
(Defn schwarz [x f]

(Map # (ennesima% 1 0)

(Sort-da # (ennesima% 1 1)

(Map # (lasciate [w% 1]

(W lista (f w))) x))))
Il codice è fare tre fasi distinte - la creazione di un elenco composto da coppie (i valori originali in coppia con il valore ottenuto applicando la funzione di codifica per i valori originali), allora l'ordinamento le coppie in base ai valori della funzione di codifica. Finalmente un nuovo elenco è costruita tenendo solo il valore originale di ciascuna coppia nel ordinato elenco-di-coppie (e scartando i valori della funzione di codifica).
Ciò che potrebbe apparire come tale nelle varie proposte varianti di sintassi di Java?Diamo un rapido sguardo a ciascuno di essi (si noti che perché il sistema di tipo Java è molto più statica, molte delle nostre dichiarazioni di tipo sono più che un po 'prolisso):
/ / Strawman, con parentesi tonde per le espressioni lambda singola espressione
pubblico schwarz Lista <T> (List <T> x, Funzione <T, coppia <T, V estende Comparable <T>>> f)
{

ritorno mappa (# (w T) (makelist (w, f.apply (w))), x)

. Sort (# (coppia <T, V estende Comparable <T>> l) (l.get (1)))

. Map (# (coppia <T, V estende Comparable <T>> l) (l.get (0)));
}
/ / Strawman, con bretelle per tutte le espressioni lambda
pubblico schwarz Lista <T> (List <T> x, Funzione <T, coppia <T, V estende Comparable <T>>> f)
{

ritorno mappa (# (w T) {makelist (w, f.apply (w))}, x)

. Sort (# (coppia <T, V estende Comparable <T>> l) {l.get (1)})

. Map (# (coppia <T, V estende Comparable <T>> l) {l.get (0)});
}
/ / BGGA
pubblico schwarz Lista <T> (List <T> x, Funzione <T, Coppia <T,V>> f)
{

ritorno mappa ({w T - makelist> (w, f.apply (w))}, x)

. Sort ({coppia <T, V estende Comparable <T>> l - l.get> (1)})

. Map ({coppia <T, V estende Comparable <T>> l - l.get> (0)});
}
/ / SotL
pubblico schwarz Lista <T> (List <T> x, Funzione <T, Coppia <T,V>> f)
{

ritorno mappa (# {w T - makelist> (w, f.apply (w))}, x)

. Sort (# {coppia <T, V estende Comparable <T>> l - l.get> (1)})

. Map (# {coppia <T, V estende Comparable <T>> l - l.get> (0)});
}
/ / Elenco Redmond pubblica schwarz <T> (Lista <T> x, Funzione <T, coppia <T, V estende Comparable <T>>> f)
{

ritorno mappa ((w T) -> {makelist (w, f.apply (w))}, x)

. Sort ((coppia <T, V estende Comparable <T>> l) -> {l.get (1)})

. Map ((coppia <T, V estende Comparable <T>> l) -> {l.get (0)});
}


Come valutare loro? I miei criteri sono:
Bisogno di iniziare con un segno visibile che identifica, in modo che lambda distinguersi dal codice circostante. Il # è un carattere utile per questo.Ha bisogno di usare la sintassi {} delimitazione. Le chiusure sono una sorta di blocco, quindi dovrebbero essere a blocchi, come nel codice.Deve essere tutto d'un pezzo, così la sintassi ha una consistenza visiva e la lambda appare come una singola unità.Preferibilmente, deve avere una forma specializzata breve per letterali di funzione che non tengono parametri (lambda nullaria).Sulla base di questi criteri, Redmond è la peggiore scelta possibile per me - e la mia esperienza di scrittura alla Scala per il libro lo conferma - ho trovato Scala letterali di funzione molto più difficile da usare senza problemi di quelli in altre lingue. BGGA è un po 'meglio, ma non mi piace la mancanza di un semplice segno di identificazione che mi dice "Ciao, io sono un lambda".
Questo porta a una scelta tra il SotL e Strawman sempre con-tutore. La scelta di questi due è un po 'arbitraria. Strawman-sempre-brace sembra, ai miei occhi come una vera e propria dichiarazione di metodo Java, ma con il "nome magico" # - mentre SotL è genuinamente nuova sintassi, ma si sente più vicino alla Redmond e stili BGGA - così potrebbe essere un compromesso accettabile per gli sviluppatori che stanno bene con quelle forme

Nessun commento:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.