I simboli in Julia sono gli stessi di Lisp, Scheme o Ruby. Tuttavia, a mio avviso , le risposte a tali domande non sono davvero soddisfacenti . Se leggi quelle risposte, sembra che la ragione per cui un simbolo è diverso da una stringa è che le stringhe sono mutabili mentre i simboli sono immutabili, e anche i simboli vengono "internati", qualunque cosa significhi. Le stringhe sono mutabili in Ruby e Lisp, ma non sono in Julia, e quella differenza è in realtà un'aringa rossa. Anche il fatto che i simboli siano internati, ovvero l'hash implementato dal linguaggio per confronti rapidi di uguaglianza, è anche un dettaglio di implementazione irrilevante. Potresti avere un'implementazione che non contenga simboli e la lingua sarebbe esattamente la stessa.
Quindi cos'è un simbolo, davvero? La risposta sta in qualcosa che Julia e Lisp hanno in comune: la capacità di rappresentare il codice della lingua come una struttura di dati nella lingua stessa. Alcune persone chiamano questa "omoiconicità" ( Wikipedia ), ma altri non sembrano pensare che da soli sia sufficiente che una lingua sia omoiconica. Ma la terminologia non ha molta importanza. Il punto è che quando una lingua può rappresentare il proprio codice, ha bisogno di un modo per rappresentare cose come assegnazioni, chiamate di funzioni, cose che possono essere scritte come valori letterali, ecc. Ha anche bisogno di un modo per rappresentare le proprie variabili. Cioè, hai bisogno di un modo per rappresentare - come dati - il foo
lato sinistro di questo:
foo == "foo"
Ora stiamo arrivando al nocciolo della questione: la differenza tra un simbolo e una stringa è la differenza tra foo
sul lato sinistro di quel confronto e "foo"
sul lato destro. A sinistra, foo
è un identificatore e valuta il valore associato alla variabile foo
nell'ambito corrente. A destra, "foo"
è una stringa letterale e restituisce il valore di stringa "pippo". Un simbolo in Lisp e in Julia è il modo in cui rappresenti una variabile come dati. Una stringa rappresenta solo se stessa. Puoi vedere la differenza applicandoti eval
a loro:
julia> eval(:foo)
ERROR: foo not defined
julia> foo = "hello"
"hello"
julia> eval(:foo)
"hello"
julia> eval("foo")
"foo"
La :foo
valutazione del simbolo dipende da quale - se non altro - la variabile foo
è vincolata, mentre "foo"
valuta sempre "pippo". Se vuoi costruire espressioni in Julia che usano variabili, allora stai usando dei simboli (che tu lo sappia o no). Per esempio:
julia> ex = :(foo = "bar")
:(foo = "bar")
julia> dump(ex)
Expr
head: Symbol =
args: Array{Any}((2,))
1: Symbol foo
2: String "bar"
typ: Any
Ciò che quella roba scaricata mostra, tra le altre cose, è che c'è un :foo
oggetto simbolo all'interno dell'oggetto espressione che ottieni citando il codice foo = "bar"
. Ecco un altro esempio, la costruzione di un'espressione con il simbolo :foo
memorizzato nella variabile sym
:
julia> sym = :foo
:foo
julia> eval(sym)
"hello"
julia> ex = :($sym = "bar"; 1 + 2)
:(begin
foo = "bar"
1 + 2
end)
julia> eval(ex)
3
julia> foo
"bar"
Se provi a farlo quando sym
è associato alla stringa "foo"
, non funzionerà:
julia> sym = "foo"
"foo"
julia> ex = :($sym = "bar"; 1 + 2)
:(begin
"foo" = "bar"
1 + 2
end)
julia> eval(ex)
ERROR: syntax: invalid assignment location ""foo""
È abbastanza chiaro capire perché questo non funzionerà - se hai provato ad assegnare "foo" = "bar"
a mano, anche non funzionerebbe.
Questa è l'essenza di un simbolo: un simbolo viene utilizzato per rappresentare una variabile nella metaprogrammazione. Una volta che hai i simboli come tipo di dati, ovviamente, diventa tentato di usarli per altre cose, come le chiavi hash. Ma questo è un uso accidentale e opportunistico di un tipo di dati che ha un altro scopo primario.
Nota che ho smesso di parlare di Ruby qualche tempo fa. Questo perché Ruby non è omoiconico: Ruby non rappresenta le sue espressioni come oggetti Ruby. Quindi il tipo di simbolo di Ruby è una specie di organo vestigiale - un adattamento residuo, ereditato da Lisp, ma non più utilizzato per il suo scopo originale. I simboli Ruby sono stati cooptati per altri scopi - come chiavi hash, per estrarre i metodi dalle tabelle dei metodi - ma i simboli in Ruby non sono usati per rappresentare le variabili.
Il motivo per cui i simboli vengono utilizzati in DataFrames piuttosto che nelle stringhe, è perché è un modello comune in DataFrames per associare i valori di colonna alle variabili all'interno delle espressioni fornite dall'utente. Quindi è naturale che i nomi delle colonne siano simboli, poiché i simboli sono esattamente ciò che usi per rappresentare le variabili come dati. Al momento, devi scrivere df[:foo]
per accedere alla foo
colonna, ma in futuro potresti essere in grado di accedervi come df.foo
invece. Quando ciò diventa possibile, solo le colonne i cui nomi sono identificatori validi saranno accessibili con questa comoda sintassi.
Guarda anche: