2010-06-15 19 views
5

Disons que j'ai une fonctionComprendre Ruby Enumerable carte # (avec des blocs plus complexes)

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

et moi avions simple tableau dénombrable

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

Et je l'ai couru à travers la carte, avec mon fonction, en utilisant un bloc do-end:

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

Comment pourrais-je faire sans, par exemple, la définition de la fonction en premier lieu? Par exemple,

# 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'est pas ruby ​​valide, et le compilateur se fâche contre moi même y penser. Mais comment pourrais-je mettre en place une sorte de chose équivalente, ça marche?

modifier

En réalité, la solution à mon problème important pour moi beaucoup moins que la motivation/raisonnement derrière elle, pour me aider à mieux comprendre comment les blocs ruby ​​travail :)

+2

Pour ce que ça vaut, vous peut faire 1.even? ou 1.odd? in ruby> = 1.8.7 – steenslag

Répondre

13

Vous » re si proche. Il suffit de retirer les return s et vous êtes en or. Ceci est dû au fait que le bloc passé à map est un proc (c'est-à-dire créé avec Proc.new), et non un lambda. Un return dans un proc ne saute pas simplement hors du processus saute hors de la méthode qui a été exécutée (c'est-à-dire appelé call) le proc. Un retour dans un lambda, en revanche, ne saute que sur le lambda.

La méthode proc renvoie un lambda dans Ruby 1.8 et un Proc dans Ruby 1.9. Il vaut probablement mieux ne pas utiliser cette méthode et être explicite avec la construction que vous voulez utiliser.

Je devine que vous étiez en IRB ou un script ruby ​​ordinaire quand vous essayiez cela. La leçon à tirer de ceci est d'utiliser des retours implicites sauf si vous ne pouvez pas, je suppose.

+0

Y a-t-il une raison * pourquoi * cela arrive? Est-ce que le bloc éteint simplement la commande last-execute, comme dans les retours implicites? Je pose cette question parce que j'aimerais pouvoir prédire ce qui se passe; avoir ces résultats semble juste un peu ... aléatoire. –

+0

La version courte est "c'est l'une des différences entre procs et lambdas." Travailler sur une meilleure explication. Et oui, les blocs retourneront simplement l'expression la plus récemment évaluée en eux. – x1a4

+0

merci pour l'explication; c'est très complet et utile =) juste une dernière question ... est-il possible de passer un lambda comme un bloc? à #map, peut-être? –

9

Je soupçonne que ce peut être une double question, mais de donner une valeur d'un bloc, utilisez next

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

hm, cela semble être exactement ce que je cherchais :) merci :) –

3

Shortest variante en utilisant la réponse d'Andrew:

simple.map { |n| next :even if n % 2 == 0; :odd } 
+1

Aller un peu plus loin:' simple.map {| n | prochaine n% 2 == 0? : pair:: impair} ';-) –