Blog · 2026-06-19Blog · 2026-06-19

Blocks & yield en Ruby, enfin clairs Blocks & yield in Ruby, finally clear

Le bloc est partout en Ruby : each, map, times. Mais qu'est-ce qu'un bloc, au juste, et que fait yield ? Une explication sans détour, avec du code.Blocks are everywhere in Ruby: each, map, times. But what is a block, exactly, and what does yield do? A no-nonsense explanation, with code.

RubyBlocksyieldItérateurs

Tu écris [1, 2, 3].each { |n| puts n } sans y penser. Mais ce { |n| ... }, c’est quoi ? Un bloc : un morceau de code que tu passes à une méthode, et que la méthode peut décider d’exécuter — quand elle veut, autant de fois qu’elle veut. C’est le mécanisme qui rend Ruby si expressif.

yield : « exécute le bloc qu’on m’a donné »

Toute méthode peut recevoir un bloc, même sans le déclarer. Le mot-clé yield l’appelle :

def deux_fois
  yield
  yield
end

deux_fois { puts "bonjour" }
# bonjour
# bonjour

La méthode ne sait pas ce que fait le bloc. Elle sait juste quand le déclencher. C’est une inversion : c’est la méthode qui rend la main au bloc, pas l’inverse.

On peut passer des valeurs au bloc

yield accepte des arguments, qui deviennent les paramètres du bloc (entre | |) :

def chaque_paire(liste)
  i = 0
  while i < liste.size
    yield(liste[i], liste[i + 1])
    i += 2
  end
end

chaque_paire([1, 2, 3, 4]) { |a, b| puts "#{a} et #{b}" }
# 1 et 2
# 3 et 4

C’est exactement ainsi que each fonctionne : la méthode pilote l’itération, le bloc décide quoi faire de chaque élément. Tu délègues le contrôle du quoi, tout en gardant le comment.

Et si aucun bloc n’est donné ?

block_given? te le dit, pour ne pas planter sur un yield dans le vide :

def saluer
  if block_given?
    yield "Ada"
  else
    "Bonjour Ada"
  end
end

saluer                          # => "Bonjour Ada"
saluer { |nom| "Salut #{nom}!" } # => "Salut Ada!"

Le bloc reste anonyme et attaché à un seul appel. Le jour où tu veux le stocker dans une variable ou le passer plus loin, il te faut un Proc ou une lambda — et là, les règles changent (sur le return, sur le nombre d’arguments).

C’est la suite logique : comprends le bloc et yield, et tu comprendras pourquoi Ruby a aussi besoin des procs et des lambdas.

You write [1, 2, 3].each { |n| puts n } without thinking. But that { |n| ... }, what is it? A block: a chunk of code you pass to a method, which the method can decide to run — whenever it wants, as many times as it wants. It’s the mechanism that makes Ruby so expressive.

yield: “run the block I was given”

Any method can receive a block, even without declaring it. The yield keyword calls it:

def twice
  yield
  yield
end

twice { puts "hello" }
# hello
# hello

The method doesn’t know what the block does. It only knows when to trigger it. It’s an inversion: the method hands control to the block, not the other way around.

You can pass values to the block

yield takes arguments, which become the block’s parameters (between | |):

def each_pair(list)
  i = 0
  while i < list.size
    yield(list[i], list[i + 1])
    i += 2
  end
end

each_pair([1, 2, 3, 4]) { |a, b| puts "#{a} and #{b}" }
# 1 and 2
# 3 and 4

This is exactly how each works: the method drives the iteration, the block decides what to do with each element. You delegate control of the what, while keeping the how.

What if no block is given?

block_given? tells you, so you don’t blow up on a yield into the void:

def greet
  if block_given?
    yield "Ada"
  else
    "Hello Ada"
  end
end

greet                          # => "Hello Ada"
greet { |name| "Hi #{name}!" } # => "Hi Ada!"

The block stays anonymous and tied to a single call. The day you want to store it in a variable or pass it further along, you need a Proc or a lambda — and there, the rules change (about return, about argument count).

It’s the logical next step: understand the block and yield, and you’ll understand why Ruby also needs procs and lambdas.

Tous les articlesAll articles