14 Callable and runnable objects
The chapter introduces Ruby’s broader idea of things you can call, run, or execute beyond ordinary method calls. It focuses first on procs and lambdas as anonymous functions, then on method objects, threads, and finally ways to launch external programs. Along the way, it emphasizes that Ruby gives you multiple layers of dynamism: code can be packaged as objects, captured from blocks, passed around, invoked later, and even used to reshape execution context.
A major theme is the distinction between block syntax and proc objects. Blocks are part of method-call syntax, not objects themselves, but they can be captured as procs with the special ampersand form and then invoked with call. The chapter explores how procs act as closures, preserving the local variables in scope when they were created, which makes patterns like counters and stateful callbacks possible. It also shows how lambdas are a stricter kind of proc, especially in argument handling and return behavior, and how Ruby’s proc-conversion hooks such as to_proc enable concise constructs like symbol-to-proc shorthand and hash lookups in map.
The later sections broaden the discussion to method objects, where methods can be detached from instances, rebound, and called like other callable objects, mainly as a reflective tool rather than a common everyday technique. The chapter then shifts to the eval family, explaining how Ruby can execute strings as code, change self with instance_eval and instance_exec, and define methods dynamically with class_eval and define_method, while warning about the security and design risks of these powers. It closes with concurrency and external execution: threads for lightweight concurrent work, thread-local data and keys, a networked server example, and system command interfaces such as system, backticks, open, and Open3 for interacting with operating-system programs.
A phantom Proc instantiation intervenes between a method call and a method.
Summary
- Objects in Ruby are products of runtime code execution but can, themselves, have the power to execute code.
- Proc objects are anonymous functions that can be executed.
- The lambda “flavor” of proc objects is stricter about arity than plain procs.
- Procs bound to variables can be used as code blocks.
- Any object can have a to_proc method, available through the & prefix operator.
- Symbol#to_proc creates a proc that sends the symbol itself to the object(s), e.g., array_of_strings.map(&:upcase).
- The Method class allows methods to be passed around as first-class objects.
- The eval “family” of methods includes eval, instance_eval, and class_eval (aka module_eval).
- Bindings represent the local variable bindings at a given point in program execution.
- Threads offer facilities for concurrent programming.
- Threads can store values as keys, e.g., my_thread[:message] = "Hello".
- External programs can be executed from Ruby code with the system method, exec, backticks, and the open and Open3.popen3 facilities.
The Well-Grounded Rubyist, Fourth Edition ebook for free