Pergunta

Digamos que eu tenho uma função

def odd_or_even n
  if n%2 == 0
    return :even
  else
    return :odd
  end
end

E eu tinha uma variedade enumerável simples

simple = [1,2,3,4,5]

E eu o corri pelo mapa, com minha função, usando um bloco de ponta:

simple.map do
  |n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]

Como eu poderia fazer isso sem, digamos, definir a função em primeiro lugar? Por exemplo,

# does not work
simple.map do |n|
  if n%2 == 0
    return :even
  else
    return :odd
  end
end

# Desired result:
# => [:odd,:even,:odd,:even,:odd]

não é rubi válido, e o compilador fica bravo comigo por pensar nisso. Mas como eu implementaria um tipo de coisa equivalente, que funciona?

editar

Na realidade, a solução para o meu problema importa para mim muito menos do que a motivação/raciocínio por trás disso, para me ajudar a entender mais como os blocos de rubi funcionam :)

Foi útil?

Solução

Você está tão perto. Basta remover o returnS e você é dourado.

Isso ocorre porque o bloco passou para map é um Proc (ou seja, criado com Proc.new), e não um lambda. UMA return Dentro de um Proc, não sai apenas do proc- ele sai do método que executou (ou seja, chamou call ) o Proc. Um retorno dentro de um lambda, por outro lado, salta apenas do lambda.

o proc O método retorna um Lambda no Ruby 1.8 e um Proc em Ruby 1.9. Provavelmente é melhor não usar esse método e ser explícito com qual construção você deseja usar.

Acho que você estava no IRB ou em um script rubi simples quando estava tentando isso.

a = Proc.new { return }
a.call # fails. Nothing to return from.

def foobar
  a = Proc.new { return }
  a.call
  puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method.
end
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method.

b = lambda { return }
b.call # succeeds. The return only returns from the lambda itself.

def bazquux
  b = lambda { return }
  b.call
  puts 'hello' # this is reached. The lambda only returned from itself.
end
bazquux # succeeds, and prints 'hello'

A lição para aprender com isso é usar retornos implícitos, a menos que você não possa, eu acho.

Outras dicas

Eu suspeito que essa pode ser uma pergunta duplicada, mas para dar um valor de um bloco, use next

simple.map do |n|
  if n%2 == 0
    next :even
  else
    next :odd
  end
end

Variante mais curta usando a resposta de Andrew:

simple.map { |n| next :even if n % 2 == 0; :odd }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top