Símbolos em Ruby
Publicado em Developer
Recebi um email ontem comentando sobre a (curta) explicação de Símbolos que eu dou no meu tutorial de Ruby. Realmente é bem curta, e eu acho que esqueci o quanto o conceito de símbolos demorou para entrar na minha cabeça, talvez justamente por falta de alguma explicação mais clara para os newcomers de Ruby.
Vou tentar retificar meu erro aqui. Como digo na apostila, símbolos são como "strings levinhas". O que seria isso? Se vocês leram a apostila, sabem que Strings em Ruby alocam espaço na memória, ao contrário dos immediate values, (Fixnum's, booleanos, nulos e símbolos), que não alocam memória para os objetos.
Levando isso em conta, vamos imaginar assim: imagine seu programa cheio de Strings, todo programa usa um monte de Strings, mas que tal trocar essas Strings por símbolos onde você puder? Ia economizar um monte de memória, e o garbage collector agradece. Vou mostrar isso na prática, com um programinha besta que faz uma coisa besta mas que serve perfeitamente para o exemplo:
def azul?(s) return s=="azul" end puts "Há #{ObjectSpace.each_object(String){}} Strings na memória." 1000.times { azul?("verde") } puts "Agora há #{ObjectSpace.each_object(String){}} Strings na memória."
O que esse programa faz? Não muita coisa. Ele tem um método azul? (lembrem-se que métodos que tem ? no final são chamados de métodos predicados em Ruby), que verifica se o valor que passamos para ele é uma String "azul" ou não.
Executando esse programa, tenho:
[taq@~]ruby symbols.rb Há 168 Strings na memória. Agora há 2170 Strings na memória.
Ouch. Criamos 2002 Strings (as 2000 do loop mais as 2 mensagens impressas). Se levarmos em conta que "verde" tem 5 bytes e "azul" tem 4 bytes, alocamos pouco mais de 8k na memória. Pouca coisa? É, mas quantas vezes esse código vai rodar e durante quanto tempo? É uma boa prática se preocupar com otimização desde códigos mais pequenos, simples e de curta duração, pois isso se reflete depois em código mais extensos, complexos e de longa duração. Questão de costume.
E como fazer otimização nesse código? Olhem os símbolos aí! Vamos alterar nosso programa para:
def azul?(s) return s==:azul end puts "Há #{ObjectSpace.each_object(String){}} Strings na memória." 1000.times { azul?(:verde) } puts "Agora há #{ObjectSpace.each_object(String){}} Strings na memória."
Executando esse programa, tenho:
[taq@~]ruby symbols.rb Há 166 Strings na memória. Agora há 168 Strings na memória.
UAU! Economizei 2000 Strings! No programa só utilizei 2 símbolos, :verde (não é o Aurélio!) e :azul, que foram criados apenas uma vez durante todo o tempo de vida do programa. Isso mostra como o uso de símbolos é uma coisa a se pensar naqueles programas que usam várias Strings "identificáveis", vamos dizer assim, como no caso das cores, no exemplo.
Comentários
Comentários fechados.
Sem nenhum comentário.
Artigos anteriores
- Pull requests em modo raiz - sex, 22 de dezembro de 2023, 09:57:09 -0300
- Qual a idade do seu repositório? - ter, 27 de dezembro de 2022, 12:50:35 -0300
- Utilizando ctags em projetos Rails mais recentes - qui, 24 de junho de 2021, 08:23:43 -0300
- Fazendo o seu projeto brotar - seg, 15 de julho de 2019, 08:57:05 -0300
- Learn Functional Programming with Elixir - sex, 02 de março de 2018, 18:47:13 -0300
- Ambiente mínimo - Driver Driven Development - qua, 23 de agosto de 2017, 15:15:03 -0300
- Ambiente mínimo - repositórios de código - dom, 16 de abril de 2017, 13:02:14 -0300
- Ambiente mínimo - terminal e navegador - dom, 02 de abril de 2017, 21:43:29 -0300
- Utilizando muitas gems no seu projeto? - sáb, 29 de outubro de 2016, 11:57:55 -0200
- Desenvolvedores e inteligência artificial - seg, 11 de julho de 2016, 09:09:38 -0300