[Ruby] How to Truly Understand unless and until

작성자

카테고리:

← 피드로
DEV Community · TinyNight(JP) · 2026-07-27 개발(SW)

TinyNight(JP)

I frequently see comments that ‘unless’ and ‘until’ are difficult to understand.
I’ve also heard that it’s prohibited in tools like rubocop.
This is a fundamentally flawed way of thinking.

As a basic principle, abandon the idea of ​​”if it becomes false“.
The basic principle is to remember what happens when it becomes true, and you won’t get confused.

unless

Think of unless as an expression that will not be executed if the condition is met.

result = 1 if a && b     # If a && b is satisfied, execute the left side.
result = 2 unless a && b # If a && b is satisfied, do not execute the left side.

Enter fullscreen mode Exit fullscreen mode

When combined with return (guard clause), it should be considered a condition for proceeding with the process.

return if a && b     # Terminate processing if the (a && b) is satisfied.
return unless a && b # Proceed with processing if the (a && b) is satisfied.

Enter fullscreen mode Exit fullscreen mode

When using them as guard clauses, remember the following: The two have distinctly different roles.

Keywords Role Action return if expression blacklist Terminate processing if the expression is satisfied return unless expression whitelist Proceed with processing if the expression is satisfied

To differentiate their use, any judgment formulas that involve both should be separated.
An example is shown below.

def gagazet_gate(yevonite) # case 1
  return if yevonite == Kimahri
  # Blocks only Kimahri. This allows unauthorized people to pass through.
end

def gagazet_gate(yevonite) # case 2
  return unless yevonite == Summoner || yevonite == Guardian
  # Summoners and guards are allowed through. This means Kimahri can also get through.
end

def gagazet_gate(yevonite) # Bad case
  return if yevonite == Kimahri || yevonite != Summoner && yevonite != Guardian
    # "No passing if you're Kimahri, and also if you're not a summoner, and also if..."
    # Not Biran!
end

def gagazet_gate(yevonite) # Best case
  return unless yevonite == Summoner || yevonite == Guardian
  return if yevonite == Kimahri
  # Summoner may pass. Guardians may pass. Kimahri not pass!
  # Since these two guard clauses serve diametrically opposite purposes, they should be used separately.
end

Enter fullscreen mode Exit fullscreen mode

until

The until statement can be thought of as a condition that exits the loop when it becomes true.

i = 0
p i while (i += 1) < 10 # Loops while i is less than 10
p i until (i -= 1) <= 0 # Exit the loop when i becomes 0 or less

Enter fullscreen mode Exit fullscreen mode

For example, the following example is easy to understand. The formula is also elegant.

a = (1..100).to_a
a.shift until a.empty? # Exit the loop when a becomes empty

Enter fullscreen mode Exit fullscreen mode

Summary

While it’s often suggested that unless be replaced with if not, that suggestion is based on a flawed premise.
unless and until are not constructs that reverse the evaluation of if and while conditional expressions. Rather, they are constructs that “reverse the behavior” of a conditional expression.

Furthermore, until is actually more suitable for loops than while because it clarifies the goal.
The true ace of loop statements is until. It is definitely not a variation of while.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다