2015-07-30 7 views
17

Homoiconicity in Lisp è facile vedere:In che senso lingue come Elixir e Julia homoiconic?

(+ 1 2)

è sia la funzione di chiamata a + con 1, 2 come argomenti, oltre ad essere un elenco contenente +, 1 e 2. È contemporaneamente sia codice che dati.

in un linguaggio come Julia, però:

1 + 2

So che possiamo analizzare questo in una Expr a Julia:

:(1 + 2)

E poi siamo in grado di ottenere l'AST e manipolarlo:

julia> Meta.show_sexpr(:(1+2)) (:call, :+, 1, 2)

Quindi, possiamo manipolare l'AST di un programma in Julia (ed Elixir). Ma sono omoiconici nello stesso senso di Lisp- è qualsiasi snippet di codice in realtà solo una struttura di dati nella lingua stessa?

Non vedo come codice come 1 + 2 in Julia è, immediatamente, dati-like come (+ 1 2) in Lisp è solo una lista. E 'ancora omicida, allora?

+3

Potresti essere interessato a sapere che Julia non afferma che sia omoiconico, almeno almeno. Il motivo principale è che è mal definito, così sostenendo di essere così sollevato l'ira di alcuni puristi. Non troverai la parola nella documentazione o nel sito web. – IainDunning

+1

@IainDunning Interessante davvero - forse è sicuro dire poi che lingue come Julia ed Elixir supportano metaprogrammazione e macro, ma non in virtù dell'omoiconicità. – user2666425

+2

Sì, penso che fosse la logica per rimuoverlo. Julia potrebbe non essere omoiconica, ma puoi fare la maggior parte delle cose a cui ti associ (penso in modo informale come la capacità incorporata relativamente facile di scrivere codice per manipolare il codice). – IainDunning

risposta

24

Nelle parole di Bill Clinton, "Dipende da quale sia il significato della parola 'è' è". Bene, ok, non proprio, ma dipende da quale sia il significato della parola "omoiconico". Questo termine è sufficientemente controverso che non diciamo più che Julia è omoiconica, quindi puoi decidere autonomamente se si qualifica. Invece di cercare di definire homoiconicity, cito quello Kent Pitman (che conosce una cosa o due riguardo Lisp) ha detto in una Slashdot interview nel 2001:

mi piace la volontà di Lisp di rappresentare se stesso. La gente spesso lo spiega come la sua capacità di rappresentare se stesso, ma penso che sia sbagliato. La maggior parte delle lingue sono in grado di rappresentare se stesse, ma semplicemente non ne hanno la volontà. I programmi Lisp sono rappresentati da liste e i programmatori ne sono consapevoli. Non avrebbe importanza se fosse stato un array. È importante che sia la struttura del programma che è rappresentata, e non la sintassi dei caratteri, ma oltre a ciò la scelta è piuttosto arbitraria. Non è importante che la rappresentazione sia la scelta giusta®. È solo importante che sia una scelta condivisa e condivisa in modo che ci possa essere una ricca comunità di programmi che manipolano programmi che "fanno trading" in questa rappresentazione comune.

Non definisce l'omoiconicità - probabilmente non vuole entrare in un argomento di definizione più di me. Ma lui è al centro della questione: quanto è volente un linguaggio rappresentare se stesso? Lisp è disposto all'estremo - non puoi nemmeno evitarlo: la rappresentazione del programma come dato è semplicemente seduta lì, a fissarti in faccia.Julia non utilizza sintassi S-espressione, così che la rappresentazione di codice come dati è meno evidente, ma non è nascosto molto profondo:

julia> ex = :(2a + b + 1) 
:(2a + b + 1) 

julia> dump(ex) 
Expr 
    head: Symbol call 
    args: Array(Any,(4,)) 
    1: Symbol + 
    2: Expr 
     head: Symbol call 
     args: Array(Any,(3,)) 
     1: Symbol * 
     2: Int64 2 
     3: Symbol a 
     typ: Any 
    3: Symbol b 
    4: Int64 1 
    typ: Any 

julia> Meta.show_sexpr(ex) 
(:call, :+, (:call, :*, 2, :a), :b, 1) 

julia> ex.args[3] 
:b 

julia> ex.args[3] = :(3b) 
:(3b) 

julia> ex 
:(2a + 3b + 1) 

codice julia è rappresentato dal tipo Expr (e simboli e atomi), e mentre la corrispondenza tra la sintassi della superficie e la struttura è meno immediatamente evidente, è ancora lì. E ancora più importante, la gente sa che il codice è semplicemente dati che possono essere generati e manipolati, quindi esiste una "ricca comunità di programmi che manipolano il programma", come dice KMP.

Questa non è solo una presentazione superficiale del codice di Julia come una struttura di dati - questo è il modo in cui Julia rappresenta il suo codice a sé. Quando si immette un'espressione in REPL, viene analizzata negli oggetti Expr. Gli oggetti Expr vengono quindi passati a eval, che "li abbassa" a oggetti un po 'più regolari Expr, che vengono quindi passati a digitare inferenza, tutti implementati in Julia. Il punto chiave è che il compilatore usa esattamente la stessa rappresentazione del codice che vedi. La situazione non è poi così diversa in Lisp. Quando si guarda il codice Lisp, in realtà non si vedono gli oggetti lista - quelli che esistono solo nella memoria del computer. Quello che vedi è una rappresentazione testuale di letterali di lista, che l'interprete Lisp analizza e trasforma in oggetti lista che poi evalora, proprio come Julia. La sintassi di Julia può essere vista come una rappresentazione testuale per i valori letterali Expr: la Expr sembra essere una struttura dati un po 'meno generale di una lista.

Non conosco i dettagli, ma ho il sospetto che Elixir è simile - forse José segnalerà

Vedi anche:.

+0

Quindi è più una PEPL, non una REPL. Poiché non legge le espressioni dei dati (come fa il Lisp), ma analizza le espressioni del programma in dati specializzati di tipo expr. –

+4

Non sono sicuro che sia una differenza - S-exprs, nonostante la loro sintassi minima, ha ancora bisogno di essere analizzato, quindi un Lisp REPL è davvero un PEPL. Penso che la differenza principale sia che il tipo 'Expr' non è generale - è specifico per rappresentare il codice. – StefanKarpinski

+0

La differenza è che l'analisi del linguaggio di programmazione in Lisp non viene eseguita in READ sull'input di testo, ma leggermente diversa in EVAL sulle strutture di dati Lisp. EVAL potrebbe non convertire i dati Lisp in una struttura dati di espressione - i valutatori possono essere implementati senza tale passaggio. –

Problemi correlati