← Ruby EnglishChapter 05 of 13

Methods, Blocks, and Procs

## Learning Objectives - Define and call methods - Understand method parameters and return values - Work with blocks and yield - Master procs and lambdas - Understand closures and scope ## Methods ### Basic Syntax ```ruby def greet "Hello!" end puts greet # "Hello!" ``` ### Method with Parameters ```ruby def greet(name) "Hello, #{name}!" end puts greet("Alice") # "Hello, Alice!" ``` ### Default Parameters ```ruby def greet(name = "World") "Hello, #{name}!" end puts greet # "Hello, World!" puts greet("Bob") # "Hello, Bob!" ``` ### Multiple Parameters ```ruby def add(a, b) a + b end puts add(2, 3) # 5 ``` ### Splat Operator ```ruby def sum(*numbers) numbers.reduce(0, :+) end puts sum(1, 2, 3, 4, 5) # 15 ``` ### Keyword Arguments (Ruby 2.0+) ```ruby def create_user(name:, email:, age: 18) { name: name, email: email, age: age } end create_user(name: "Alice", email: "alice@example.com") create_user(name: "Bob", email: "bob@example.com", age: 25) ``` ### Double Splat for Keyword Args ```ruby def config(**options) options end config(server: "localhost", port: 3000, debug: true) # => { server: "localhost", port: 3000, debug: true } ``` ## Return Values ```ruby # Explicit return def find_first_even(numbers) numbers.each { |n| return n if n.even? } nil end # Implicit return (last expression) def add(a, b) a + b end ``` ## Method Naming ```ruby # Question methods (?) - return boolean def empty?(str) str.length == 0 end # Bang methods (!) - potentially dangerous def sort!(array) array.sort! end def sort(array) array.sort end # Setter methods def name=(value) @name = value end # Predicates def between?(a, b) self >= a && self <= b end ``` ## Variable Arguments ```ruby def logger(level, *messages) messages.each { |msg| puts "[#{level.upcase}] #{msg}" } end logger("INFO", "Server started", "User logged in", "Request processed") ``` ## Blocks ### Block Syntax ```ruby # Do-end block [1, 2, 3].each do |n| puts n end # Brace block [1, 2, 3].each { |n| puts n } ``` ### Yield ```ruby def repeat(times) times.times { yield } end repeat(3) { puts "Hello" } # Output: Hello three times ``` ### Yield with Arguments ```ruby def calculate(a, b) yield(a, b) end result = calculate(5, 3) { |x, y| x + y } puts result # 8 result = calculate(5, 3) { |x, y| x * y } puts result # 15 ``` ### Block_given? ```ruby def maybe_repeat(times) if block_given? times.times { yield } else puts "No block provided" end end maybe_repeat(3) { puts "Hello" } maybe_repeat(3) ``` ## Procs ### Creating Procs ```ruby # Proc.new greet = Proc.new { |name| "Hello, #{name}!" } # proc method shout = proc { |text| text.upcase } # lambda keyword (stabby lambda) welcome = lambda { |name| "Welcome, #{name}!" } # Stabby lambda shorthand (Ruby 1.9+) farewell = ->(name) { "Goodbye, #{name}!" } ``` ### Calling Procs ```ruby greet = proc { |name| "Hello, #{name}!" } puts greet.call("Alice") puts greet["Bob"] # Alternative syntax puts greet.("Charlie") # Alternative syntax ``` ### Proc vs Lambda ```ruby # Proc - doesn't check argument count p = proc { |a, b| "#{a}, #{b}" } p.call(1, 2) # "1, 2" p.call(1) # "1, " (nil for missing) p.call(1, 2, 3) # "1, 2" (extra ignored) # Lambda - strict argument count l = lambda { |a, b| "#{a}, #{b}" } l.call(1, 2) # "1, 2" l.call(1) # ArgumentError! l.call(1, 2, 3) # ArgumentError! ``` ### Lambda_check ```ruby p = proc { |x| x } l = lambda { |x| x } puts p.lambda? # false puts l.lambda? # true ``` ## Lambdas ### Stabby Lambda Syntax ```ruby add = ->(a, b) { a + b } puts add.call(2, 3) # 5 square = ->(n) { n ** 2 } puts square.call(5) # 25 ``` ### Lambda as Method Argument ```ruby numbers = [1, 2, 3, 4, 5] # Instead of block doubled = numbers.map(&:to_i) # Symbol to proc doubled = numbers.map { |n| n * 2 } # With lambda numbers.each(&->(n) { puts "Number: #{n}" }) ``` ## Blocks to Procs ### Ampersand Operator ```ruby def method_that_yields yield if block_given? end proc = -> { puts "Hello" } method_that_yields(&proc) # Symbol to proc names = ["alice", "bob"] upcase_names = names.map(&:upcase) ``` ## Closures ```ruby # Blocks capture local variables def multiplier(factor) ->(number) { number * factor } end double = multiplier(2) triple = multiplier(3) puts double.call(5) # 10 puts triple.call(5) # 15 ``` ## Method Arguments Summary | Syntax | Description | |--------|-------------| | `def foo(a)` | Positional argument | | `def foo(a=1)` | Default argument | | `def foo(*a)` | Variable positional | | `def foo(a:)` | Keyword argument | | `def foo(a: 1)` | Keyword with default | | `def foo(**a)` | Keyword splat | | `def foo(&a)` | Block as proc | ## Summary - Methods: `def...end`, implicit/explicit return - Blocks: `do...end` or `{ }`, passed to methods - `yield`: executes the block - Procs: `Proc.new`, `proc`, stored as objects - Lambdas: `lambda { }` or `->()`, strict argument checking - `&` operator: converts block to proc or proc to block - Closures: blocks capture surrounding scope

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →