ruby.onl / secret-operators

Conditional Assignment: ||= and the Boolean Operator Tricks

2026-03-26

Ruby's ||= is the Perl refugee's //=. Assign a default value only if the variable is nil or false. Combined with &&= and the fact that || and && return actual values (not just true/false), you get a powerful set of tools for defensive coding. But there's a gotcha with false that'll bite you if you're not careful.

Part 1: ||= (Assign if nil/false)

count ||= 0 # assign only if count is nil or false name ||= "anonymous" # set default hash[:key] ||= [] # autovivify! create array if missing
Perl equivalent: $count //= 0; (defined-or-assign, Perl 5.10+)

Important difference: Perl's //= checks for defined. Ruby's ||= checks for truthiness (nil OR false). In Ruby, 0 and "" are truthy, so ||= won't overwrite them. In Perl, //= won't overwrite 0 or "" either (they're defined). So in practice, they behave similarly for most cases.

Part 2: &&= (Assign if truthy)

string &&= string + " suffix" # Only modifies string if it's not nil/false # Equivalent to: # if string # string = string + " suffix" # end name &&= name.strip # strip only if name exists
Perl: $string &&= $string . " suffix"; (works the same).

Part 3: Boolean Operators Return Values

This is identical to Perl. && and || return the actual value, not just true/false.

|| returns first truthy value

name = params[:name] || ENV['USER'] || "anonymous" # Checks each, returns the first one that isn't nil/false port = config[:port] || 8080 # Use config port, fall back to 8080
Perl: my $name = $params{name} || $ENV{USER} || "anonymous";

&& returns first falsy, or last truthy

result = valid? && process_data && save_result # Short-circuits on first false/nil # Returns the actual false/nil value, or the last truthy value # Practical: conditional chaining line && line.strip && line.strip.length > 0

Part 4: Default Value Patterns

# Simple default timeout = options[:timeout] || 30 # Nested default with ||= config[:database] ||= {} config[:database][:host] ||= "localhost" config[:database][:port] ||= 5432 # From environment with fallback db_host = ENV['DB_HOST'] || "localhost" db_port = (ENV['DB_PORT'] || 5432).to_i

Part 5: The false Gotcha

# DANGER: ||= treats false as "not set" flag = false flag ||= true # flag is now true! Probably not what you wanted. # If you need to handle false vs nil: flag = true if flag.nil? # only overwrites nil, not false
This is the one place where Ruby's ||= and Perl's //= diverge in practice. Perl's //= won't overwrite false because false is defined. Ruby's ||= will, because false is falsy.

Part 6: Comparison with Perl

Pattern Perl Ruby
Default value $x || "default" x || "default"
Defined-or $x // "default" No exact equivalent; use x.nil? ? "default" : x
Assign if undef $x //= "default" x ||= "default" (but catches false too)
Short-circuit AND valid() && process() valid? && process
Short-circuit OR try_a() || try_b() try_a || try_b

Created By: Wildcard Wizard. Copyright 2026