ruby.onl / sorcery

Dynamic Defaults and Runtime Class Creation: Ruby's Eval-Time Surprises

2026-03-29

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 require eval in Perl. Some of this is practical. Some of it is just wonderfully weird.

Part 1: Dynamic Default Arguments

# 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
Perl equivalent: you'd handle this manually inside the sub with $timestamp //= time(). Ruby does it automatically in the method signature.

Part 2: Practical Default Arguments

# 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
Every time these methods are called without the optional argument, the default expression runs fresh. No stale values, no initialization bugs.

Part 3: Runtime Class Creation with Class.new

You can create classes dynamically without the class keyword. This is rarely needed for scripting, but shows Ruby's flexibility.
# 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"
Perl equivalent: 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:
class RandomSubclass < [Array, Hash, String].sample # Superclass chosen randomly at definition time end RandomSubclass.superclass # Could be any of the three!
This is a curiosity, not something you'd use in production scripts. But it demonstrates that Ruby evaluates expressions everywhere, even in class definitions.

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