2016-12-09 2 views
3

J'ai une évaluation paresseuse, où je veux le premier résultat véridique résultant d'une opération de carte, et une fois de plus je me suis retrouvé à écrire .find { |e| e } à la fin de mon expression.Ruby: Y a-t-il une utilité pour select/find sans bloc?

Voici un exemple simple; le tableau et le bloc de carte sont, bien sûr, différent dans ma vraie vie:

[nil, 2, 3, 4].lazy.map{ |e| e }.find { |e| e } 

Je suis toujours un peu surpris/déçu quand je dois ajouter le bloc { |e| e } à un select ou find, surtout si elle est un évaluation paresseuse, parce que les deux - redondante - semblent être des fonctions d'identité par défaut:

> [nil, 2, 3, 4].find { |e| e } 
=> 2 
> [nil, 2, 3, 4].find 
=> #<Enumerator: [nil, 2, 3, 4]:find> 
> [nil, 2, 3, 4].find.map { |e| e } 
=> [nil, 2, 3, 4] 

est-ce recenseur diffèrent pratiquement tout de celui obtenu à partir .each?

> [nil, 2, 3, 4].each.map { |e| e } 
=> [nil, 2, 3, 4] 

De même avec select, à l'exception qui est encore plus inutile avec paresseux:

> [nil, 2, 3, 4].select 
=> #<Enumerator: [nil, 2, 3, 4]:select> 
> [nil, 2, 3, 4].select { |e| e } 
=> [2, 3, 4] 
> [nil, 2, 3, 4].select.lazy.force # doing it wrong looks functional! 
=> [nil, 2, 3, 4] 
> [nil, 2, 3, 4].lazy.select { |e| e }.force 
=> [2, 3, 4] 
> [nil, 2, 3, 4].lazy.select.force # same without .force 
ArgumentError: tried to call lazy select without a block 

-ce que ces identités apparentes utiles, ou tout simplement une opportunité pour un meilleur défaut dans une future version de (et ArgumentError!) Rubis?

+0

'cycle' sans bloc retourne un énumérateur qui boucle indéfiniment (à savoir' next' peut être appliqué indéfiniment), légèrement différent des autres. –

Répondre

2

Tout d'abord - une petite remarque. Si jamais vous tapez { |e| e }, vous pouvez utiliser &:itself. Avec cela, les méthodes énumérables sans bloc retournent souvent un énumérateur. Vous pouvez l'utiliser pour chaîner avec des méthodes d'énumération. Par exemple, tenez compte:

[1, 2, 3].map.with_index { |n, i| n + i } # => [1, 3, 5] 
[1, 2, 3].each.with_index { |n, i| n + i } # => [1, 2, 3] 

[1, 2, 3].select.with_index { |n, i| (n + 2 * i).even? } # => [2] 
+0

Bon, mais puisque l'OP a demandé spécifiquement select, vous pouvez montrer un exemple en utilisant select. – tokland

+0

@tokland, ajouté. – ndn

+0

Mm, merci pour la réponse rapide. 'select.with_index {| _, je | i> 2} 'a du sens, mais ça ne marche pas avec paresseux, ce qui semble être un peu un trou. Merci pour la référence '' (&: itself) '- intéressante et probablement plus efficace, mais pas aussi claire que' {| e | e} 'à mon cerveau. :) –