Boolean & Nil
Boolean
A Boolean is either true or false. Booleans are produced by comparisons, logical operators, and predicate methods (.empty?, .nil?, is_integer(), etc.).
flag = true
missing = false
puts 5 > 3 # true
puts 5 < 3 # false
puts 5 == 5 # true
puts 5 != 3 # true
Logical Operators
puts true and false # false — both must be true
puts true or false # true — at least one must be true
puts not true # false — negation
# Short-circuit evaluation
# 'and' stops at the first false
# 'or' stops at the first true
puts false and risky() # false — risky() never called
puts true or risky() # true — risky() never called
Truthiness
Only false and nil are falsy. Every other value — including 0, "", and [] — is truthy. This matches Ruby's model.
if 0 then puts "truthy" end # prints
if "" then puts "truthy" end # prints
if [] then puts "truthy" end # prints
if false then puts "truthy" end # does NOT print
if nil then puts "truthy" end # does NOT print
Boolean Comparison
puts true == true # true
puts true == false # false
puts true != false # true
# Booleans are not numbers — no arithmetic
# puts true + 1 # Runtime error
Type Checking
puts is_bool(true) # true
puts is_bool(false) # true
puts is_bool(0) # false
puts is_bool("true") # false
Common Patterns
# Guard clause with boolean
def process(data)
return nil if data == nil
return nil if data.empty?
data.map do |x| x * 2 end
end
# Store result of a condition
valid = age >= 18 and not banned
puts "Access: #{if valid then "granted" else "denied" end}"
# Predicate methods return booleans
puts "".empty? # true
puts [1, 2].empty? # false
puts "hello".include?("ell") # true
puts is_integer(42) # true
Nil
nil represents the absence of a value. It is Frankie's equivalent of null, None, or undefined in other languages. There is exactly one nil — every nil is the same value.
missing = nil
puts missing # nil
puts missing == nil # true
When Nil Appears
# Unset hash keys
h = {name: "Alice"}
puts h["age"] # nil — key doesn't exist
# Out-of-range vector access
v = [1, 2, 3]
puts v[10] # nil
# Missing function results
def find_user(id)
return nil if id == 0
{id: id, name: "User#{id}"}
end
puts find_user(0) # nil
# Short-circuit of &. chain
puts nil&.upcase # nil
Checking for Nil
x = nil
# Three equivalent ways
puts x == nil # true
puts x != nil # false
puts x.nil? # true — method form
puts is_nil(x) # true — function form
Avoid testing if not x to check for nil — it also catches false:
x = false
if not x # catches both nil AND false
puts "this runs"
end
if x == nil # only catches nil
puts "this does not run"
end
Nil Safety with&.``
The safe navigation operator &. short-circuits on nil, returning nil instead of crashing:
name = nil
puts name.upcase # Runtime error
puts name&.upcase # nil — safe
# Chain — stops at the first nil
user = nil
puts user&.name&.upcase&.length # nil
# Useful when a value might or might not be present
config = {db: {host: "localhost"}}
puts config.dig("db", "host")&.upcase # LOCALHOST
puts config.dig("db", "port")&.to_s # nil
Nil in Collections
v = [1, nil, 2, nil, 3]
puts v.compact # [1, 2, 3] — removes all nils
# nil propagates in arithmetic — raises an error
# puts nil + 1 # TypeError
# Nil-safe default pattern
value = get_value() || 0 # note: || is not in Frankie
# Instead use:
raw = get_value()
value = if raw == nil then 0 else raw end
Conversion
puts nil.to_s # "" — nil becomes empty string
puts nil.to_a # [] — nil becomes empty vector (via stdlib)
Type Checking
puts is_nil(nil) # true
puts is_nil(false) # false — false is not nil
puts is_nil(0) # false
puts is_nil("") # false