Especificamente: estou tentando usar o pacote DataFrames de Julia, especificamente a função readtable () com a opção de nomes, mas isso requer um vetor de símbolos.
- o que é um símbolo?
- por que eles escolheriam isso ao invés de um vetor de strings?
Até agora, encontrei apenas algumas referências à palavra símbolo na língua Julia. Parece que os símbolos são representados por ": var", mas não está claro para mim o que são.
Além: eu posso correr
df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )
Minhas duas perguntas com marcadores ainda permanecem.
Respostas:
Os símbolos em Julia são os mesmos que em Lisp, Scheme ou Ruby. No entanto, na minha opinião , as respostas a essas perguntas relacionadas não são realmente satisfatórias . Se você ler essas respostas, parece que a razão pela qual um símbolo é diferente de uma string é que as strings são mutáveis, enquanto os símbolos são imutáveis e os símbolos também são "internados" - o que quer que isso signifique. As strings são mutáveis em Ruby e Lisp, mas elas não estão em Julia, e essa diferença é realmente um arenque vermelho. O fato de os símbolos serem internados - isto é, hash pela implementação da linguagem para comparações rápidas de igualdade - também é um detalhe irrelevante da implementação. Você pode ter uma implementação que não armazene símbolos e o idioma seria exatamente o mesmo.
Então, o que é realmente um símbolo? A resposta está em algo que Julia e Lisp têm em comum - a capacidade de representar o código da linguagem como uma estrutura de dados na própria linguagem. Algumas pessoas chamam isso de "homoiconicidade" ( Wikipedia ), mas outras não parecem pensar que isso seja suficiente para que um idioma seja homoicônico. Mas a terminologia realmente não importa. O ponto é que, quando uma linguagem pode representar seu próprio código, ela precisa de uma maneira de representar coisas como atribuições, chamadas de função, coisas que podem ser escritas como valores literais etc. Ela também precisa de uma maneira de representar suas próprias variáveis. Ou seja, você precisa de uma maneira de representar - como dados - o
foo
lado esquerdo disso:Agora estamos chegando ao cerne da questão: a diferença entre um símbolo e uma string é a diferença entre
foo
o lado esquerdo dessa comparação e"foo"
o lado direito. À esquerda,foo
há um identificador e ele avalia o valor associado à variávelfoo
no escopo atual. À direita,"foo"
é uma string literal e avalia o valor da string "foo". Um símbolo no Lisp e na Julia é como você representa uma variável como dados. Uma string apenas representa a si mesma. Você pode ver a diferença aplicandoeval
a eles:O que o símbolo
:foo
avalia depende de qual - ou alguma coisa - a variávelfoo
está vinculada, enquanto"foo"
sempre apenas avalia como "foo". Se você deseja construir expressões em Julia que usam variáveis, então você está usando símbolos (se você conhece ou não). Por exemplo:O que esse material despejado mostra, entre outras coisas, é que há um
:foo
objeto de símbolo dentro do objeto de expressão que você obtém citando o códigofoo = "bar"
. Aqui está outro exemplo, construindo uma expressão com o símbolo:foo
armazenado na variávelsym
:Se você tentar fazer isso quando
sym
estiver vinculado à string"foo"
, não funcionará:É bem claro para ver por que isso não funcionará - se você tentou atribuir
"foo" = "bar"
manualmente, também não funcionará.Esta é a essência de um símbolo: um símbolo é usado para representar uma variável na metaprogramação. Depois de ter símbolos como um tipo de dados, é claro, torna-se tentador usá-los para outras coisas, como chaves de hash. Mas esse é um uso casual e oportunista de um tipo de dados que tem outro objetivo principal.
Note que eu parei de falar sobre Ruby há um tempo. Isso ocorre porque Ruby não é homoicônico: Ruby não representa suas expressões como objetos Ruby. Portanto, o tipo de símbolo de Ruby é uma espécie de órgão vestigial - uma adaptação restante, herdada de Lisp, mas não mais usada para seu propósito original. Os símbolos Ruby foram cooptados para outros fins - como chaves de hash, para extrair métodos das tabelas de métodos - mas os símbolos no Ruby não são usados para representar variáveis.
Quanto ao motivo pelo qual os símbolos são usados nos DataFrames, e não nas cadeias, é porque é um padrão comum nos DataFrames vincular valores de colunas a variáveis dentro de expressões fornecidas pelo usuário. Portanto, é natural que os nomes das colunas sejam símbolos, pois os símbolos são exatamente o que você usa para representar variáveis como dados. Atualmente, você precisa escrever
df[:foo]
para acessar afoo
coluna, mas, no futuro, poderá acessá-la comodf.foo
alternativa. Quando isso se tornar possível, apenas as colunas cujos nomes são identificadores válidos estarão acessíveis com esta sintaxe conveniente.Veja também:
fonte
eval(:foo)
e em outroeval(sym)
. Existe uma diferença significativa entreeval(:foo)
eeval(foo)
?eval(:foo)
dá valor ao qual a variávelfoo
está vinculada, ao passo queeval(foo)
chama eval nesse valor. Escrevereval(:foo)
é equivalente a apenasfoo
(no escopo global) assimeval(foo)
éeval(eval(:foo))
.