Então, por que os criadores de Ruby tiveram que usar o conceito de symbols
na linguagem?
Bem, eles não precisavam "estritamente", eles escolheram. Além disso, observe que, estritamente falando, Symbol
s não fazem parte do idioma, eles fazem parte da biblioteca principal. Eles possuem sintaxe literal no nível do idioma, mas funcionariam da mesma forma se você tivesse que construí-los chamando Symbol::new
.
Eu pergunto da perspectiva de um programador não-rubi tentando entender isso. Eu aprendi muitas outras línguas e não encontrei em nenhuma delas a necessidade de especificar se eu estava lidando ou não com o que Ruby chama symbols
.
Você não disse o que são essas "muitas outras línguas", mas aqui está apenas um pequeno trecho de linguagem que possui um Symbol
tipo de dados como o Ruby:
- ECMAScript , também JavaScript
- Scala
- Scheme , Common Lisp , Clojure (também, Clojure tem palavras - chave ), basicamente todos os idiomas da família Lisp, seus sucessores e primos os têm
- Smalltalk , Newspeak e muitos outros idiomas da família Smalltalk (que provavelmente é de onde o Ruby os obteve), incluindo o Objective-C (embora de forma limitada)
- Erlang (chamados átomos ) , também Elixir e LFE
- Julia
- Prolog (chamados átomos ), o que provavelmente é de onde Erlang os obteve
Existem também outros idiomas que fornecem os recursos de Symbol
s de uma forma diferente. Em Java, por exemplo, os recursos de Ruby String
s são divididos em dois (na verdade três) tipos: String
e StringBuilder
/ StringBuffer
. Por outro lado, as características de Ruby Symbol
tipo são dobradas para o Java String
Tipo: Java String
s podem ser internado , strings literais e String
s que são o resultado de tempo de compilação expressões constantes avaliadas são automaticamente internado, geradas dinamicamente String
s podem ser internado chamando o String.intern
método Um internado String
em Java é exatamente como um Symbol
em Ruby, mas não é implementado como um tipo separado, é apenas um estado diferente do que um JavaString
pode estar disponível. (Nota: nas versões anteriores do Ruby, String#to_sym
costumava ser chamado String#intern
e esse método ainda existe hoje como um alias herdado.)
A principal questão poderia ser: o conceito de symbols
Ruby existe como uma intenção de desempenho sobre si e outras linguagens,
Symbol
s são antes de tudo um tipo de dados com semântica específica . Essa semântica também possibilita implementar algumas operações de alto desempenho (por exemplo, testes rápidos de igualdade O (1)), mas esse não é o objetivo principal.
ou apenas algo que é necessário para existir devido à maneira como a linguagem é escrita?
Symbol
s não são necessários na linguagem Ruby, o Ruby funcionaria perfeitamente sem eles. Eles são puramente um recurso de biblioteca. Há exatamente um lugar no idioma vinculado a Symbol
s: uma def
expressão de definição de método é avaliada como Symbol
denotando o nome do método que está sendo definido. No entanto, essa é uma alteração bastante recente, antes disso, o valor de retorno simplesmente não foi especificado. A RM simplesmente avaliou nil
, Rubinius avaliou um Rubinius::CompiledMethod
objeto e assim por diante. Também seria possível avaliar para um UnboundMethod
... ou apenas um String
.
Um programa em Ruby seria mais leve e / ou mais rápido que seu, digamos, equivalente em Python ou Node? Se sim, seria por causa disso symbols
?
Não tenho certeza do que você está perguntando aqui. O desempenho é principalmente uma questão de qualidade de implementação, não de linguagem. Além disso, o Node nem sequer é uma linguagem, é uma estrutura de E / S registrada para ECMAScript. Executando um script equivalente no IronPython e MRI, o IronPython provavelmente será mais rápido. Executando um script equivalente no CPython e JRuby + Truffle, é provável que o JRuby + Truffle seja mais rápido. Isso não tem nada a ver com Symbol
s, mas com a qualidade da implementação: o JRuby + Truffle possui um compilador de otimização agressiva, além de todo o mecanismo de otimização de uma JVM de alto desempenho, o CPython é um intérprete simples.
Como uma das intenções de Ruby é ser fácil de ler e escrever para humanos, seus criadores não poderiam facilitar o processo de codificação implementando essas melhorias no próprio intérprete (como pode ser em outros idiomas)?
No. Symbol
s não são uma otimização de compilador. Eles são um tipo de dados separado com semântica específica. Eles não são como os flonums do YARV , que são uma otimização interna privada para Float
s. A situação não é a mesma que para Integer
, Bignum
e Fixnum
, o que deve ser um detalhe otimização interna privada invisível, mas infelizmente não é. (Isto é, finalmente, vai ser fixado em Ruby 2.4, que remove Fixnum
e Bignum
e folhas apenas Integer
.)
Fazer isso da maneira que o Java faz, como um estado especial de String
s normal, significa que você sempre precisa ser cauteloso sobre se seus String
s estão ou não nesse estado especial e sob quais circunstâncias eles estão automaticamente nesse estado especial e quando não. Esse é um fardo muito maior do que simplesmente ter um tipo de dados separado.
Haveria uma definição independente de idioma dos símbolos e um motivo para tê-los em outros idiomas?
Symbol
é um tipo de dados que denota o conceito de nome ou rótulo . Symbol
s são objetos de valor , imutáveis, geralmente imediatos (se a linguagem distingue uma coisa dessas), apátridas e sem identidade. Dois Symbol
s iguais são também garantidos idênticos, ou seja, dois Symbol
s iguais são na verdade o mesmo Symbol
. Isso significa que igualdade de valor e igualdade de referência são a mesma coisa e, portanto, igualdade é eficiente e O (1).
Os motivos para tê-los em um idioma são realmente os mesmos, independentemente do idioma. Alguns idiomas dependem mais deles do que outros.
Na família Lisp, por exemplo, não há conceito de "variável". Em vez disso, você tem Symbol
s associados a valores.
Em linguagens com capacidades reflexivas ou introspectivos, Symbol
s muitas vezes são usados para indicar os nomes das entidades reflectidas nas APIs de reflexão, por exemplo, em Ruby, Object#methods
, Object#singleton_methods
, Object#public_methods
, Object#protected_methods
, e Object#public_methods
retornar um Array
de Symbol
s (embora eles poderiam muito bem retornar um Array
de Method
s). Object#public_send
usa um Symbol
denotando o nome da mensagem a ser enviada como argumento (embora também aceite um String
, Symbol
seja mais semanticamente correto).
No ECMAScript, Symbol
s são um alicerce fundamental para tornar o ECMAScript seguro para os recursos no futuro. Eles também desempenham um grande papel na reflexão.