Liguagem Ruby tá difícil

16 respostas
MauNunes

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

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

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 ?

16 Respostas

dlt

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!

fantomas

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

MauNunes

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"

dlt

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.

peczenyj

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:

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);
});

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.

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?

Marcio_Duran

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?

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

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.

urubatan

Marcio Duran:

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

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.

urubatan

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.


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.

dlt

Eu estava respondendo a esse post seu:

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

Por isso falei do js.

Filipe_Chagas

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

urubatan

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

pertence ao core do ruby, se não estou enganado, foi declarado no modulo System

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]

urubatan

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]

Estou atualizando o site do livro entre hoje e amanha com a página de erratas :smiley:

dlt

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

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

irb(main):003:0> Kernel.methods(false).grep /^block/
=> ["block_given?"]
Criado 16 de abril de 2009
Ultima resposta 18 de mai. de 2009
Respostas 16
Participantes 7