Básico From Javascript To Ruby

Como prometido, irei mostrar as diferenças e semelhanças entre Javascript e Ruby. Nada melhor do que começar com o básico, estruturas, variáveis, objetos, tipos, etc. Quem conhece Javascript vai gostar, espero hehe. Para testar os códigos, é necessário que você tenha o Ruby instalado com o IRB ou vá até o Try Ruby e um console do Firebug com o Firefox de preferência. Ou se preferir aqui mesmo, neste mini console meia boca que acabei de fazer: Como eu odeio o WordPress

Introdução

Uma pequena introdução ao Ruby: Ruby é uma linguagem puramente orientada a objetos, tudo em Ruby é objeto, números, strings, arrays etc, Javascript é quase isso, alguns tipos ainda são primitivos. Em Ruby temos classes e módulos ao invés de protótipos. Você pode estender qualquer classe ou objeto a qualquer momento, a maioria dos operadores são na realidade métodos. Ruby tem tipagem forte e dinâmica, o que significa que não precisa ficar declarando tipos, mas não pode tentar somar um número com uma string que resultará em erro. Em Ruby "funções" são métodos de Kernel.

Variáveis

Assim como em Javascript, em Ruby não precisa ficar declarando o tipo das variáveis, mas não tente somar uma string com um número que nem em Js, resultará em erro:

>>> numero = 2
2
>>> string = "2"
"2"
>>> string + numero
"22"

Agora em Ruby:


irb(main):001:0> numero = 2
=> 2
irb(main):002:0> string = "2"
=> "2"
irb(main):003:0> string + numero
TypeError: can't convert Fixnum into String
	from (irb):3:in `+'
	from (irb):3
	from :0

Os exemplos acima mostram que Ruby tem tipagem forte. Um detalhe: assim como em Js, em Ruby não precisa ficar usando ponto-e-vírgula no final das expressões, a não ser que seja feita mais de uma em linha.

Agora vamos falar sobre o escopo das variáveis (só local e global, mais tarde falaremos sobre variáveis de instância, de classe etc.). Em Javascript para que uma variável seja local ela precisa ser definida acompanhada da palavra chave var, se não for ela é interpretada como sendo global.

>>> function teste(){global = "teste"}
>>> global = "fora"
"fora"
>>> global
"fora"
>>> teste()
>>> global
"teste"

No código acima a função teste modificou o valor da variável global, para que não modificasse era só colocar um var antes de sua definição. Agora em Ruby, para declarar uma variável global é só seguir as convenções e colocar um $ na frente da variável, se a variavel começar com letras ou _ (não é permitido variáveis que iniciem com números) ela é considerada local.

irb(main):001:0> def teste; $global = "teste"; end
=> nil
irb(main):002:0> $global = "fora"
=> "fora"
irb(main):003:0> $global
=> "fora"
irb(main):004:0> teste
=> "teste"
irb(main):005:0> $global
=> "teste"

Funcionou do mesmo modo que o exemplo de Javascript porque definimos a variável com um $ na frente, se não tivessemos usado esse $ dentro do método a variável $global continuaria com o valor "fora". Algumas observações: Métodos são definidos usando a palavra chave def seguida do nome do método e seus argumentos. Não precisamos colocar parêntesis nem na chamada do método nem na definição dele, já em Js quando chamamos alguma função sem parêntesis, não estamos chamando e sim recebendo a função em si como uma closure, explicarei isso depois. Na 4 linha quando executamos o método teste recebemos uma string "teste", mas como se não retornamos nada? Simples, em Ruby não precisamos colocar explicitamente a palavra-chave return para retornar alguma coisa, o valor da última expressão avaliada é automaticamente retornada, e no caso a última expressão foi a atribuição de "teste".

Tipos

Mostrarei os tipos padrão da linguagem, assim como em outras linguagens Ruby tem diversos tipos.

String, Numeric e Array – Comum

Em Ruby também temos diversos tipos como String, Numeric (Fixnum ou Float) e Array. Eles podem ser definidos assim como em Javascript:


irb(main):001:0> string = "Uma String"
=> "Uma String"
irb(main):002:0> fixnum = 64
=> 64
irb(main):003:0> float = 3.141585
=> 3.141585
irb(main):004:0> array = [0, "Outra String", string, fixnum, float]
=> [0, "Outra String", "Uma String", 64, 3.141585]
irb(main):005:0> puts "string - #{string.class}\\nfixnum - #{fixnum.class}\\nfloat  - #{float.class}\\narray  - #{array.class}"
string - String
fixnum - Fixnum
float  - Float
array  - Array
=> nil

Definimos uma String, Fixnum, Float e um Array. Agora chamamos o método puts do Kernel com uma String de parâmetro, dentro dessa string usamos #{..} para executar código Ruby, o valor retornado será concatenado com a String. Strings podem ser definidas com " ou , lembrando que neste último não são permitidos caracteres de escape como \n e nem aquelas chaves lá em cima para colocar código Ruby. Olhe este exemplo aí embaixo, lembrando que << serve para concatenar uma string, assim como +=:

irb(main):001:0> string = "Bernardo"
=> "Bernardo"
irb(main):002:0> string2 = string
=> "Bernardo"
irb(main):003:0> string &lt;< " Rufino"
=> "Bernardo Rufino"
irb(main):004:0> "string = #{string}; string2 = #{string2}"
=> "string = Bernardo Rufino; string2 = Bernardo Rufino"

Ué! Mas como?! Quando definimos string2 na linha 2, estamos fazendo uma referência a string e não uma cópia, depois quando usamos o método << ele concatena na string, não cria um novo objeto string, e como string2 apontava para string, ela também muda. Usando += não teremos esse problema, porém é mais lento já que estamos criando um novo objeto. Uma dica: use o <<, mas com cuidado.

irb(main):001:0> string = "Bernardo"
=> "Bernardo"
irb(main):002:0> string2 = string
=> "Bernardo"
irb(main):003:0> string += " Rufino"
=> "Bernardo Rufino"
irb(main):004:0> "string = #{string}; string2 = #{string2}"
=> "string = Bernardo Rufino; string2 = Bernardo"

Funcionou como esperávamos, outro meio de evitar esse tipo de problema é na hora de atribuir string2 fazer uma cópia de string usando o método dup que copia o objeto, a linha 2 ficaria assim string2 = string.dup, e funcionária também.

Hash e Symbol – Arrays com chaves e mini Strings

Vou mostrar a vocês Hashes e Symbols, que nada mais são que Arrays com chaves e Strings imutáveis. Symbols são definidos usando : na frente, são como Strings mais pequenas, disse que eles são imutáveis pois sempre representam o mesmo objeto.


irb(main):001:0> symbol = :simbolo
=> :simbolo
irb(main):002:0> string = 'simbolo'
=> "simbolo"
irb(main):003:0> symbol == string
=> false
irb(main):004:0> symbol == :simbolo
=> true
irb(main):005:0> "symbol id = #{symbol.object_id}; :simbolo id = #{:simbolo.object_id}"
=> "symbol id = 1018338; :simbolo id = 1018338"
irb(main):006:0> "string id = #{string.object_id}; 'simbolo' id = #{'simbolo'.object_id}"
=> "string id = 37415690; 'simbolo' id = 37328150"

Primeiro definimos um Symbol e uma String, comparamos o Symbol com a String, usando == assim como em Js, e verificamos que não eram iguais, comparamos aquele Symbol a :simbolo e verificamos que são iguais. Mostramos o id, chamando o método object_id, de cada objeto String e vimos que cada String nova mesmo com o mesmo conteúdo representa um objeto novo, e depois fazemos o mesmo com Symbols porém cada Symbol novo com o mesmo conteúdo representa o mesmo objeto.

Agora veremos os Hashes, Arrays com chaves. São parecidissimos com os objetos literais em Javascript (JSON). Geralmente usamos os Symbols como chaves de um Hash.

>>> json = {"nome": "Bernardo Rufino", email: "bermonruf@gmail.com"}
Object nome=Bernardo Rufino email=bermonruf@gmail.com
>>> json["nome"]
"Bernardo Rufino"
>>> json.nome
"Bernardo Rufino"
>>> json["email"]
"bermonruf@gmail.com"
>>> json.email
"bermonruf@gmail.com"

JSON é geralmente usado para troca de dados e para criação de classes alterando o prototype. Como vimos pode-se ter uma chave definida com ou sem aspas, e para acessar se usa colchetes ou com um ponto. Em Ruby com hashes temos:

irb(main):001:0> hash = {:nome => "Bernardo Rufino", "email" => "bermonruf@gmail.com"}
=> {:nome=>"Bernardo Rufino", "email"=>"bermonruf@gmail.com"}
irb(main):002:0> hash[:nome]
=> "Bernardo Rufino"
irb(main):003:0> hash["nome"]
=> nil
irb(main):004:0> hash["email"]
=> "bermonruf@gmail.com"
irb(main):005:0> hash[:email]
=> nil
irb(main):006:0> hash.nome
NoMethodError: undefined method `nome' for {:nome=>"Bernardo Rufino", "email"=>"bermonruf@gmail.com"}:Hash
	from (irb):6
	from :0

Repare que tentamos acessar uma propriedade com uma chave Symbol usando String e não deu certo (retornou nil, que é como se fosse null em Js, é um objeto também), ocorre o mesmo ao contrário e depois tentamos acessar como se estivéssemos chamando um método, como o método não existe um erro é gerado (Obs: dá pra fazer o hash ser acessado por métodos com method_missing, falaremos disso depois). O conselho é usar Symbols, já que são imutáveis, ocuparão menos espaço na memória.

true, false e nil – Booleanos e Nulo

Em Ruby até os booleans são objetos, até nulo (nil)é objeto! Diferentemente de Javascript e outras linguagens, Arrays vazios, Strings vazias, zeros etc. são considerados verdadeiros, somente false e nil são realmente falsos.

irb(main):001:0> true.class
=> TrueClass
irb(main):002:0> true.nil?
=> false
irb(main):003:0> false.class
=> FalseClass
irb(main):004:0> false.nil?
=> false
irb(main):005:0> nil.class
=> NilClass
irb(main):006:0> nil.nil?
=> true
irb(main):007:0> nil.methods.join(" ")
=> "inspect send display &amp; clone public_methods __send__ to_yaml equal? freeze object_id require_gem require to_f instance_eval methods pretty_print_inspect dup gem instance_variables instance_of? extend eql? | to_yaml_style id hash singleton_methods taint instance_variable_get frozen? kind_of? ^ to_a to_yaml_properties pretty_print_instance_variables type pretty_print_cycle protected_methods == === instance_variable_set is_a? respond_to? taguri to_s pretty_inspect class method pretty_print private_methods =~ tainted? taguri= __id__ untaint nil? to_i"

Pedimos a classe de cada valor e foi devolvida, testamos se cada valor é nulo com o método nil? e só o nil é nil (nossa! hehe), depois invocamos o método methods que devolve um Array com o nome dos métodos e juntamos os valores com um espaço. Observação: Os métodos que terminam em ? são métodos predicados, ou seja, retornam true ou false, o resto para indicar valor nenhum, ou alguma falha é recomendado retornar nil.

Regexp e Match Data – Expressões Regulares

Ruby também tem ótimo suporte às ERs. Expressões regulares são Regexps, são parecidíssimas com Javascript, se não iguais, podem ser criadas usando / ou o construtor padrão. Strings tem o método match, assim como as Regexp, mas eu acho muito mas lógico usar a partir da String. Temos também os operadores =~ e !~ para testar as ERs.

irb(main):001:0> regexp = /I Love (.+)/
=> /I Love (.+)/
irb(main):002:0> string = "I Love Ruby"
=> "I Love Ruby"
irb(main):003:0> string =~ regexp
=> 0
irb(main):004:0> match = string.match(regexp)
=> #<MatchData:0x477ea08>
irb(main):005:0> "match[1] = #{match[1]}; $1 = #{$1}"
=> "match[1] = Ruby; $1 = Ruby"
irb(main):006:0> regexp2 = Regexp.new("(.+) (.+) Ruby")
=> /(.+) (.+) Ruby/
irb(main):007:0> string =~ regexp2
=> 0
irb(main):008:0> "$1 = #{$1}; $2 = #{$2}"
=> "$1 = I; $2 = Love"
irb(main):009:0> string =~ /um padrao louco/
=> nil
irb(main):010:0> string.match(/um outro padrao louco/)
=> nil

O exemplo acima ilustra bem o que quis dizer, quando executamos o operador =~ se a string casar nós ganhamos a variável global $1 que representa o valor do 1º grupo da ER casado, com 2 grupos se casasse iríamos ter $1 e $2 assim em diante. Quando usamos o método match recebemos um objeto tipo MatchData se casar ou nil se não casar, os grupos casados podem ser acessados pelo objeto usando match[n] onde n é o número do grupo partindo de 1 e match é um MatchData.

Para procurar e substituir temos os métodos sub e gsub de Strings, que procuram por um padrão em uma String uma vez e mais de uma vez respectivamente. Eles recebem uma Regexp, também podem receber uma String nesse caso a string será substituída, e depois uma String que substituirá o valor casado, pode conter os valores dos grupos casdos usando \\n onde n é o número do grupo. Veja o exemplo

irb(main):001:0> string = "Um exemplo de <b>String</b> com formatacao <b>HTML</b> em <b>negrito</b>."
=> "Um exemplo de <b>String</b> com formatacao <b>HTML</b> em <b>negrito</b>."
irb(main):002:0> regexp = /<b>([^<]+)<\/b>/
=> /<b>([^<]+)<\/b>/
irb(main):003:0> string.sub(regexp, "*\\1*")
=> "Um exemplo de *String* com formatacao <b>HTML</b> em <b>negrito</b>."
irb(main):004:0> string.gsub(regexp, "*\\1*")
=> "Um exemplo de *String* com formatacao *HTML* em *negrito*."

Como podemos ver é parecidíssimo com Javascript. Qualquer erro no código comente, pode elogiar, criticar etc. mas comente hehe…

Anúncios

2 Responses to Básico From Javascript To Ruby

  1. JulioGreff disse:

    Muito bom, já tinha lido sobre isso, mas como meu inglês não é lá essas coisas ficaram alguns buracos, resolvido agora. Valeu!

  2. Lucas Almeida disse:

    Muito bom, exelente tuto, abraços

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: