Dynamic Defaults and Runtime Class Creation: Ruby's Eval-Time Surprises
Unlike most languages, Ruby evaluates default arguments at call time, not definition time. This means defaults can be "live" values. And because Ruby evaluates expressions everywhere, even in class definitions, you can do things that would requireeval in Perl. Some of this is practical. Some of it is just wonderfully weird.
Part 1: Dynamic Default Arguments
Perl equivalent: you'd handle this manually inside the sub with# Timestamp defaults to NOW when called, not when defined def log_message(message, timestamp = Time.now) puts "[#{timestamp}] #{message}" end log_message("First") # uses current time sleep(2) log_message("Second") # uses NEW current time, 2 seconds later
$timestamp //= time(). Ruby does it automatically in the method signature.
Part 2: Practical Default Arguments
Every time these methods are called without the optional argument, the default expression runs fresh. No stale values, no initialization bugs.# Default to current working directory def list_files(dir = Dir.pwd) Dir.glob("#{dir}/*") end # Default to environment variable def connect(host = ENV['DB_HOST'] || 'localhost') # host evaluated fresh each call end # Default to computed value def backup(filename, suffix = Time.now.strftime('%Y%m%d')) system("cp", filename, "#{filename}.#{suffix}") end
Part 3: Runtime Class Creation with Class.new
You can create classes dynamically without theclass keyword. This is rarely needed for scripting, but shows Ruby's flexibility.
Perl equivalent:# Create a class at runtime MyClass = Class.new(Array) do def custom_method "I have #{size} elements" end end obj = MyClass.new([1, 2, 3]) obj.custom_method # => "I have 3 elements"
eval "package MyClass; ..." with string code generation. Ruby's version is actual code, not string munging.
Part 4: The Weird Stuff (For Entertainment Purposes)
Because class bodies are evaluated at load time, you can do things like this:This is a curiosity, not something you'd use in production scripts. But it demonstrates that Ruby evaluates expressions everywhere, even in class definitions.class RandomSubclass < [Array, Hash, String].sample # Superclass chosen randomly at definition time end RandomSubclass.superclass # Could be any of the three!
The takeaway isn't "do this in production." The takeaway is that Ruby doesn't have a separate compile-time vs. runtime distinction the way other languages do. Everything is evaluated, everywhere, all the time. That's what makes dynamic defaults, define_method, and method_missing all work so naturally.
Created By: Wildcard Wizard. Copyright 2026