Liguagem Ruby tá difícil

Nunca tinha visto Ruby na vida e resolvi tentar aprender atraves do livro do Rodrigo Urubatan que apesar de ter como foco Ruby on Rails, tem nos primeiros capítulos uma introdução a linguagem Ruby.
Não se se é problema meu que conheço só java, ams to tendo uma certa dificuldade de enter a linguagem.
Abaixo está os código que viajei.

arr = [1,2,3,4] arr.each { |var| print "#{var}\n" }

A saida é 1
2
3
4

E o outro

[code]def recebe_proc_e_passa_parametro
if block_given?
yield(23)
else
puts "você precisa passar um bloco de código para este método\n"
end
end

def recebe_proc_e_passa_parametro do |par|
puts "Recebi #{par} dentro deste bloco\n"
end[/code]

A saida é: Recebi 23 dentro deste bloco

Meu Deus! Daonde surgiu aquele |var| o que ele faz ? Achei que iria passar o um parâmetro para |var|

E o outro código ? Sem chance…

Será que é normal agente não entender nada no começo ?

Ok, vamos lá.

Vou te ensinar de um jeito bem simplista, na medida em que você se acostumar com a linguagem você pode procurar por mais materiais e entender mais a fundo o que se passa.

O ruby te deixa ‘passar’ blocos de código pros métodos. Você pode pensar nesses blocos como funções que vão ser executadas em ‘alguma coisa’ que o metodo que vc passou o bloco retorna… essa ‘alguma coisa’ o método ‘joga’ no parâmetro do seu bloco.

Pensa que existem dois tipo de parametros: o parametro do método e o parametro do bloco.
Exemplo:

  def met(arg) #arg é o parametro do método
    alguma_coisa = "vou aparecer no lugar do 'parametro' do bloco"
    if block_given? #verifica se algum bloco foi passado pro seu metodo
      yield alguma_coisa
    else
       puts arg
    end
  end

No caso do método ‘met’, quando você chama esse metodo sem passar um bloco, ele imprime o argumento que você passou.

met('testando') # => "testando"

Quando você passa um bloco pra ‘met’, o ‘if block_given?’ vê que você passou o bloco e o executa. Aí ele ‘joga’ a variável ‘alguma_coisa’ (usando yield) no parâmetro do bloco.

met('testando') do |parametro_que_veio_do_yield|
 puts parametro_que_veio_do_yield
end # => "vou aparecer no lugar do 'parametro' do bloco"

No primeiro exemplo que você colocou, o each faz um yield pra cada elemento do array, por isso que todos os elementos são impressos. O segundo método é parecido com o que eu dei de exemplo…

É isso ai!

Se quiser melhores detalhes procure um tutorial do CLIPPER vs 5.0 em diante, você vai encontrar vários exemplos com explicações bem detalhadas sobre o assunto.

flws

Olá dlt, beleza ?
Cara obrigado pela explicações, mas vamos ver se entendi.

Quando eu passo um bloco para o método met, ele verifica se é um bloco atraves do if block_given?, certo ?
Sendo assim ele executa o bloco atraves e atribui o valor para yield. Assim sendo, novamente chama-se o metodo met passando como parâmetro o resultado atribuido a yield .

Só não entendi o resultado abaixo. Vc não esta passando para o método yield o valor ‘testando’, o retorno não deveria ser ‘testando’, já que ‘testando’ não é um bloco de código.

met('testando') do |parametro_que_veio_do_yield| puts parametro_que_veio_do_yield end # => "vou aparecer no lugar do 'parametro' do bloco"

Não. O método ‘met’ não é chamdo duas vezes. Se você passar um bloco pra ele, ele executa o bloco, que espera um parâmetro.
Pensa que o bloco é uma função. O yield é um método que o ruby usa pra fazer o bind do que vc passar como parâmetro pra ele com o parâmetro que o bloco espera.

Considerando esse bloco:

Se eu tenho o bloco, e passo ele pro método ‘met’, o yield pega o valor da variável ‘alguma_coisa’ e coloca no lugar do ‘var’ do bloco. Depois o bloco é executado com o parâmetro que foi passado pra ele pelo yield.

puxa, com Ruby vc pode passar um bloco de codigo para um metodo.

Vc teria que fazer isso, em javascript, para ter o mesmo efeito:

[code]
Array.prototype.each = function(fun) {
if (typeof fun != “function”) return;
for (var i=0; i<this.length; i++) {
if(i in this) fun(this[i]);
}
return this;
}

var x = [“cat”, “dog”, “mouse”, “bird”];
x.each(function(i) {
alert(i);
});[/code]

perceba que o que muda é que vc passa, em ruby, um {|i| faz_algo_com(i) } pois vc esta passando um bloco que recebe um parametro.

Pratique mais que uma hora cai a ficha, comigo foi assim.

Boa idéia :smiley:
vou tentar colocar exemplos em outras linguagens na próxima vez que eu for explicar isto :smiley:

PS.: Mauricio, a explicação que te mandei por email ajudou?

[quote=urubatan]Boa idéia :smiley:
vou tentar colocar exemplos em outras linguagens na próxima vez que eu for explicar isto :smiley:

PS.: Mauricio, a explicação que te mandei por email ajudou?[/quote]

Urubatan poderia expor a explicação aqui para que todos pudesse acompanhar o raciocínio nesse post ?

Sei não… acho que a versão em javascript do jeito que foi colocada confunde mais ainda quem tá começando.

Acho um ‘map’ mais simples:

    function map(fn, a)
    {
        for (i = 0; i < a.length; i++)
        {
            a[i] = fn(a[i]);
        }
    }

Tirei o código do map daqui.

[quote=Marcio Duran]
Urubatan poderia expor a explicação aqui para que todos pudesse acompanhar o raciocínio nesse post ?[/quote]

Segue o que mandei por email:

cria uma closure que recebe um parâmetro
esta closure é passada como parametro para o método each do array

eu posso por exemplo fazer:

met = lambda {|val| puts val } met.call "teste"

PS.: mais adiante ainda no primeiro capitulo do livro isto é explicado, derepente o erro foi falar de arrays antes de falar de métodos.

[quote=dlt]Sei não… acho que a versão em javascript do jeito que foi colocada confunde mais ainda quem tá começando.

Acho um ‘map’ mais simples:

    function map(fn, a)
    {
        for (i = 0; i < a.length; i++)
        {
            a[i] = fn(a[i]);
        }
    }

Tirei o código do map daqui.[/quote]
OK, mas a idéia não era um código simples e javascript, era um código com a mesma lógica daquele em Ruby para exemplificar o que estava acontecendo.

Eu estava respondendo a esse post seu:

[quote=urubatan]Boa idéia
vou tentar colocar exemplos em outras linguagens na próxima vez que eu for explicar isto [/quote]

Por isso falei do js.

A quem pertence este método block_given? … ?
De onde ele vem?

[quote=Filipe Chagas]A quem pertence este método block_given? … ?
De onde ele vem?[/quote]
pertence ao core do ruby, se não estou enganado, foi declarado no modulo System

[off]
Depois desse tópico, comprei o seu livro, urubatan, e devo parabenizá-lo, o conteúdo está excelente!
Gostaria, apenas, de deixar uma sugestão: Que tal criar uma seção no portal que você criou para o livro (http://livro.urubatan.com.br/), para as erratas. Eu sei que você tem as colocado no seu blog, mas se estivessem em uma seção, como falei, ficariam mais fáceis de acessar.
Fica aí a dica.
Novamente meus parabéns. Sucesso!
[/off]

[quote=Filipe Chagas][off]
Depois desse tópico, comprei o seu livro, urubatan, e devo parabenizá-lo, o conteúdo está excelente!
Gostaria, apenas, de deixar uma sugestão: Que tal criar uma seção no portal que você criou para o livro (http://livro.urubatan.com.br/), para as erratas. Eu sei que você tem as colocado no seu blog, mas se estivessem em uma seção, como falei, ficariam mais fáceis de acessar.
Fica aí a dica.
Novamente meus parabéns. Sucesso!
[/off][/quote]
Estou atualizando o site do livro entre hoje e amanha com a página de erratas :smiley:

[quote]A quem pertence este método block_given? … ?
De onde ele vem? [/quote]

O método block_given? vem do módulo Kernel.

irb(main):003:0> Kernel.methods(false).grep /^block/
=> ["block_given?"]