Lisp / Clojure: rimozione di parentesi non necessarie tramite convenzioni

3

Sono affascinato da Lisp perché è simple yet powerful . Sono solo un principiante e so che ci sono state molte discussioni sulla rimozione delle parentesi di Lisp e dei suoi dialetti. Eppure chiedo a Lisp ninja di prendersi qualche minuto per rispondere a questo.

Ci saranno effetti collaterali in Lisp / Clojure se avessero seguito 2 convenzioni di seguito:

;; function declaration
defn function-name param-1 .... param-n
  ...
  function-body ;; not (function-body)
  ...

;; function call
function-name param-1 ... param-n ;; not (function-name param-1 ... param-n)

Mentre usi ancora () o [] per espressioni in linea e nidificate.

(println "hello, ") (println "world !!!") ;; inline    
= a (- 2 3) ;; nested
    
posta user115126 17.01.2014 - 12:35
fonte

3 risposte

9

Puoi farlo e molto altro ancora usando espressioni dolci . Esiste già una implementazione funzionante di sweet-expressions per Scheme , che ti incoraggio a studiare. L'idea di base è quella di sostituire il lettore standard di espressioni S con un lettore di espressioni dolci; tutto il resto rimane lo stesso, e tu conservi l'omoiconicità e la capacità di usare le macro.

La domanda è come implementare le espressioni dolci in Clojure, poiché le parentesi graffe sono già utilizzate come notazione per mappe, insiemi e metadati .

    
risposta data 17.01.2014 - 14:01
fonte
4

I lisp sono molto unici nel modo in cui sono definiti. I Lisp non sono definiti in termini di testo ma in termini di strutture dati Lisp. Per esempio. in Python una definizione di funzione è definita in questo modo:

the letter d followed by the letter e followed by the letter f followed by whitespace followed by an identifier denoting the name followed by the character ( followed by …

Mentre in un Lisp una definizione di funzione è definita in questo modo:

a list with three elements, the first of which is the string "def", the second of which is a list of strings denoting the names of the parameters, and the third is the code of the function also represented as a list

Allo stesso modo, una chiamata di funzione è una lista il cui primo elemento è una stringa che indica il nome della funzione da chiamare e gli altri elementi sono gli argomenti della funzione.

In che modo annoti quelle liste e le stringhe è irrilevante. È possibile utilizzare la sintassi Lisp tradizionale, è possibile utilizzare JSON, YAML, XML o qualsiasi altra cosa. L'importante è che il codice sia solo una struttura dati. In che modo la struttura dei dati è rappresentata è irrilevante.

    
risposta data 17.01.2014 - 17:44
fonte
0

Come menzionato da Chris, espressioni dolci sono ciò che stai cercando.

per quanto riguarda Clojure, puoi scrivere codice indentato con un plugin chiamato indent-clj . Si finirebbe con qualcosa di simile:

defn factorial [n]
  if (<= n 1)
    1
    (* n (factorial (- n 1)))

Le espressioni dolci menzionano anche infisso, discusso qui per Clojure Clojure deve ancora usare il #[...] reader forma, quindi è possibile utilizzare #[n <= 1] per le espressioni infix. Questo non otterrebbe mai il supporto, ma qui è comunque:

defn factorial [n]
  if #[n <= 1]
    1
    #[n * (factorial #[n - 1])]

Un modo completamente supportato per implementare infix oggi è usare una macro, naturalmente, o persino la funzionalità letterale con tag Clojure per creare un tag infisso personalizzato, ad esempio #nfx (...) . È un po 'prolisso, quindi non vedo alcun beneficio nel modo normale:

defn factorial [n]
  if #nfx (n <= 1)
    1
    #nfx (n * (factorial #nfx (n - 1)))

Le espressioni dolci introducono anche espressioni "neoteriche", ovvero la tradizionale funzione chiamata sintassi f(...) . Questo sembra impossibile in Clojure, poiché gli spazi attorno ai delimitatori della raccolta sono facoltativi (ad esempio (a(b)) è un elenco valido).

    
risposta data 20.08.2015 - 14:59
fonte

Leggi altre domande sui tag