Les autres réponses sont assez complètes et Les fermetures en Ruby couvre largement les différences fonctionnelles. J'étais curieux de savoir quelle méthode serait la plus performante pour les méthodes qui éventuellement accepter un bloc, donc j'ai écrit quelques benchmarks (en partant de ce billet de Paul Mucur ). J'ai comparé trois méthodes :
- &block dans la signature de la méthode
- Utilisation de
&Proc.new
- Emballage
yield
dans un autre bloc
Voici le code :
require "benchmark"
def always_yield
yield
end
def sometimes_block(flag, &block)
if flag && block
always_yield &block
end
end
def sometimes_proc_new(flag)
if flag && block_given?
always_yield &Proc.new
end
end
def sometimes_yield(flag)
if flag && block_given?
always_yield { yield }
end
end
a = b = c = 0
n = 1_000_000
Benchmark.bmbm do |x|
x.report("no &block") do
n.times do
sometimes_block(false) { "won't get used" }
end
end
x.report("no Proc.new") do
n.times do
sometimes_proc_new(false) { "won't get used" }
end
end
x.report("no yield") do
n.times do
sometimes_yield(false) { "won't get used" }
end
end
x.report("&block") do
n.times do
sometimes_block(true) { a += 1 }
end
end
x.report("Proc.new") do
n.times do
sometimes_proc_new(true) { b += 1 }
end
end
x.report("yield") do
n.times do
sometimes_yield(true) { c += 1 }
end
end
end
Les performances étaient similaires entre Ruby 2.0.0p247 et 1.9.3p392. Voici les résultats pour la version 1.9.3 :
user system total real
no &block 0.580000 0.030000 0.610000 ( 0.609523)
no Proc.new 0.080000 0.000000 0.080000 ( 0.076817)
no yield 0.070000 0.000000 0.070000 ( 0.077191)
&block 0.660000 0.030000 0.690000 ( 0.689446)
Proc.new 0.820000 0.030000 0.850000 ( 0.849887)
yield 0.250000 0.000000 0.250000 ( 0.249116)
L'ajout d'un &block
param lorsqu'il n'est pas toujours utilisé ralentit vraiment la méthode. Si le bloc est optionnel, ne l'ajoutez pas à la signature de la méthode. Et, pour faire circuler les blocs, il faut envelopper yield
dans un autre bloc est le plus rapide.
Cela dit, il s'agit des résultats d'un million d'itérations, alors ne vous en faites pas trop. Si une méthode rend votre code plus clair au détriment d'un millionième de seconde, utilisez-la quand même.