0
0
Rubyprogramming~15 mins

Parameters with default values in Ruby - Deep Dive

Choose your learning style9 modes available
Overview - Parameters with default values
What is it?
Parameters with default values let you give a starting value to a function's input. If you don't provide that input when calling the function, it uses the default. This makes functions easier to use and more flexible. You can skip some inputs without causing errors.
Why it matters
Without default values, every time you call a function, you must provide all inputs, even if some are usually the same. This makes code longer and harder to read. Default values save time and reduce mistakes by handling common cases automatically.
Where it fits
Before learning this, you should understand how to define and call functions with parameters. After this, you can learn about keyword arguments and variable-length arguments to make functions even more flexible.
Mental Model
Core Idea
A parameter with a default value acts like a backup plan that the function uses when no input is given for that parameter.
Think of it like...
It's like ordering a coffee where the barista asks if you want milk. If you don't say anything, they add regular milk by default. But if you say 'no milk,' they follow your choice instead.
Function call with parameters
┌───────────────────────────────┐
│ function example(param1, param2=default) │
└───────────────┬───────────────┘
                │
       ┌────────┴────────┐
       │                 │
  Caller provides    Caller skips
  param2 value       param2 value
       │                 │
       ▼                 ▼
  param2 = given     param2 = default
Build-Up - 7 Steps
1
FoundationBasic function parameters
🤔
Concept: Functions can take inputs called parameters to work with different data.
def greet(name) puts "Hello, #{name}!" end greet("Alice")
Result
Hello, Alice!
Understanding that functions can receive inputs is the base for customizing behavior.
2
FoundationCalling functions without defaults
🤔
Concept: When a function has parameters without defaults, you must provide all arguments when calling it.
def greet(name, greeting) puts "#{greeting}, #{name}!" end greet("Alice", "Hi")
Result
Hi, Alice!
Knowing that missing arguments cause errors helps appreciate the need for defaults.
3
IntermediateAdding default values to parameters
🤔Before reading on: do you think you can call a function without providing all arguments if some have defaults? Commit to yes or no.
Concept: You can assign default values to parameters so callers can omit them.
def greet(name, greeting = "Hello") puts "#{greeting}, #{name}!" end greet("Alice") greet("Bob", "Hi")
Result
Hello, Alice! Hi, Bob!
Understanding default values lets you write simpler calls for common cases.
4
IntermediateOrder of parameters with defaults
🤔Before reading on: do you think parameters with defaults can come before those without? Commit to yes or no.
Concept: Parameters with defaults should come after those without to avoid confusion.
def example(a, b = 2) puts "a=#{a}, b=#{b}" end example(1) example(1, 3) # Wrong order example (will cause error): # def wrong(b = 2, a) # end
Result
a=1, b=2 a=1, b=3
Knowing parameter order rules prevents syntax errors and unexpected behavior.
5
IntermediateUsing expressions as default values
🤔
Concept: Default values can be any expression, including method calls or calculations.
def greet(name, greeting = "Hello".upcase) puts "#{greeting}, #{name}!" end greet("Alice")
Result
HELLO, Alice!
Recognizing that defaults can be dynamic expressions increases function flexibility.
6
AdvancedMutable default values gotcha
🤔Before reading on: do you think using a mutable object like an array as a default creates a new object each call? Commit to yes or no.
Concept: Default values are evaluated once when the function is defined, not each time it is called.
def add_item(item, list = []) list << item list end puts add_item(1).inspect puts add_item(2).inspect
Result
[1] [1, 2]
Understanding this prevents bugs where default mutable objects keep state across calls.
7
ExpertAvoiding mutable default traps
🤔Before reading on: do you think using nil and initializing inside the function avoids shared state? Commit to yes or no.
Concept: A common pattern is to use nil as default and create a new object inside the function.
def add_item(item, list = nil) list ||= [] list << item list end puts add_item(1).inspect puts add_item(2).inspect
Result
[1] [2]
Knowing this pattern helps avoid subtle bugs with shared mutable defaults in production code.
Under the Hood
When Ruby reads a function definition with default parameters, it stores the default expressions. When the function is called, Ruby checks if an argument was given. If not, it uses the stored default value. For mutable defaults, the same object is reused across calls because the default is evaluated once at definition time.
Why designed this way?
Evaluating defaults once improves performance by avoiding repeated computation. However, this design requires care with mutable objects to prevent unintended shared state. Alternatives like evaluating defaults on each call would be slower and less efficient.
Function definition
┌───────────────────────────────┐
│ def func(param=default_value) │
└───────────────┬───────────────┘
                │
        Store default_value once

Function call
┌───────────────────────────────┐
│ func() or func(arg)            │
└───────────────┬───────────────┘
                │
       ┌────────┴────────┐
       │                 │
  Argument given     No argument
       │                 │
       ▼                 ▼
 Use given argument  Use stored default_value
Myth Busters - 4 Common Misconceptions
Quick: do you think default parameter values are re-evaluated every time the function is called? Commit to yes or no.
Common Belief:Default values are calculated fresh each time the function runs.
Tap to reveal reality
Reality:Default values are evaluated once when the function is defined, not on every call.
Why it matters:This causes bugs when using mutable objects as defaults, because changes persist across calls unexpectedly.
Quick: can parameters with defaults appear before parameters without defaults? Commit to yes or no.
Common Belief:You can put parameters with defaults anywhere in the parameter list.
Tap to reveal reality
Reality:Parameters with defaults must come after all parameters without defaults in Ruby.
Why it matters:Placing them incorrectly causes syntax errors and confusion about which arguments match which parameters.
Quick: do you think using nil as a default is the same as using an empty array? Commit to yes or no.
Common Belief:Using nil as a default is just like using an empty array directly as a default.
Tap to reveal reality
Reality:Using nil lets you create a new object inside the function each call, avoiding shared state bugs.
Why it matters:This pattern prevents unexpected data sharing between function calls, which can cause hard-to-find bugs.
Quick: do you think default parameters can be changed inside the function without affecting future calls? Commit to yes or no.
Common Belief:Changing a default parameter inside a function only affects that call.
Tap to reveal reality
Reality:If the default is a mutable object, changes persist and affect future calls that use the default.
Why it matters:This can lead to confusing behavior where function calls interfere with each other.
Expert Zone
1
Default parameter expressions are evaluated in the method's defining scope, so they can access local variables and constants available there.
2
Using keyword arguments with defaults can provide clearer code and avoid some pitfalls of positional defaults.
3
Ruby 3 introduced numbered parameters and other argument forwarding features that interact subtly with default parameters.
When NOT to use
Avoid default parameters when the default value is expensive to compute or when you need a fresh object each call; instead, use nil defaults and initialize inside the function. Also, prefer keyword arguments for clarity when many defaults exist.
Production Patterns
In real-world Ruby code, default parameters are often combined with keyword arguments for readability. The nil-and-initialize pattern is standard to avoid mutable default traps. Defaults are also used to provide backward compatibility when adding new parameters.
Connections
Keyword arguments
Builds-on
Understanding default values helps grasp keyword arguments, which allow naming parameters and setting defaults more explicitly.
Immutable vs mutable objects
Related concept
Knowing how mutable defaults behave connects to understanding object mutability and side effects in programming.
Default function arguments in mathematics
Similar pattern
Mathematical functions sometimes have default parameters, showing how programming borrows from math to simplify function calls.
Common Pitfalls
#1Using a mutable object like an array as a default parameter directly.
Wrong approach:def add_item(item, list = []) list << item list end add_item(1) add_item(2)
Correct approach:def add_item(item, list = nil) list ||= [] list << item list end add_item(1) add_item(2)
Root cause:Misunderstanding that default parameters are evaluated once, causing shared mutable state across calls.
#2Placing parameters with defaults before parameters without defaults.
Wrong approach:def example(b = 2, a) puts "a=#{a}, b=#{b}" end
Correct approach:def example(a, b = 2) puts "a=#{a}, b=#{b}" end
Root cause:Not knowing Ruby's syntax rules require parameters without defaults first.
#3Assuming default values are recalculated on every call.
Wrong approach:def greet(greeting = Time.now.to_s) puts greeting end greet sleep(1) greet
Correct approach:def greet(greeting = nil) greeting ||= Time.now.to_s puts greeting end greet sleep(1) greet
Root cause:Not realizing default expressions are evaluated once at definition, not at call time.
Key Takeaways
Parameters with default values let functions be called with fewer arguments by providing fallback inputs.
Default values are evaluated once when the function is defined, which can cause shared state if mutable objects are used.
Parameters with defaults must come after parameters without defaults in Ruby to avoid syntax errors.
Using nil as a default and initializing inside the function avoids bugs with shared mutable defaults.
Mastering default parameters is a stepping stone to understanding more advanced argument handling like keyword arguments.