Master Ruby's numbered parameters (_1, _2, etc.) for concise block syntax, reducing verbosity in simple transformations and iterations.
Numbered parameters, introduced in Ruby 2.7, provide a shorthand syntax for simple blocks.
Instead of explicitly naming block parameters, you can use _1, _2, etc.
to refer to the first, second, and subsequent block arguments. This feature reduces verbosity
for simple transformations and makes code more concise.
class NumberedParametersBasics
def self.demonstrate_single_parameter
puts "=== Single Parameter Examples ==="
numbers = [1, 2, 3, 4, 5]
# Traditional syntax vs numbered parameters
puts "Traditional map: #{numbers.map { |n| n * 2 }}"
puts "Numbered param: #{numbers.map { _1 * 2 }}"
puts "Traditional select: #{numbers.select { |n| n.even? }}"
puts "Numbered param: #{numbers.select { _1.even? }}"
puts "Traditional find: #{numbers.find { |n| n > 3 }}"
puts "Numbered param: #{numbers.find { _1 > 3 }}"
# String operations
words = ["hello", "world", "ruby", "programming"]
puts "\nString operations:"
puts "Traditional upcase: #{words.map { |word| word.upcase }}"
puts "Numbered param: #{words.map { _1.upcase }}"
puts "Traditional length: #{words.map { |word| word.length }}"
puts "Numbered param: #{words.map { _1.length }}"
puts "Traditional filter: #{words.select { |word| word.length > 4 }}"
puts "Numbered param: #{words.select { _1.length > 4 }}"
end
def self.demonstrate_method_chaining
puts "\n=== Method Chaining Examples ==="
data = [" apple ", " BANANA ", " Cherry "]
# Complex transformations with numbered parameters
result1 = data.map { |item| item.strip.downcase.capitalize }
result2 = data.map { _1.strip.downcase.capitalize }
puts "Traditional chaining: #{result1}"
puts "Numbered param: #{result2}"
# Hash operations
users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Carol", age: 35 }
]
names_traditional = users.map { |user| user[:name] }
names_numbered = users.map { _1[:name] }
puts "\nHash access:"
puts "Traditional: #{names_traditional}"
puts "Numbered: #{names_numbered}"
adults_traditional = users.select { |user| user[:age] >= 30 }
adults_numbered = users.select { _1[:age] >= 30 }
puts "\nFiltering adults:"
puts "Traditional: #{adults_traditional.map { |u| u[:name] }}"
puts "Numbered: #{adults_numbered.map { _1[:name] }}"
end
def self.demonstrate_mathematical_operations
puts "\n=== Mathematical Operations ==="
numbers = [1, 2, 3, 4, 5]
operations = [
["Square", { |n| n ** 2 }, { _1 ** 2 }],
["Cube", { |n| n ** 3 }, { _1 ** 3 }],
["Double + 1", { |n| n * 2 + 1 }, { _1 * 2 + 1 }],
["Factorial", { |n| (1..n).reduce(:*) }, { (1.._1).reduce(:*) }]
]
operations.each do |name, traditional, numbered|
result1 = numbers.map(&traditional)
result2 = numbers.map(&numbered)
puts "#{name}:"
puts " Traditional: #{result1}"
puts " Numbered: #{result2}"
puts " Same result: #{result1 == result2}"
end
end
end
NumberedParametersBasics.demonstrate_single_parameter
NumberedParametersBasics.demonstrate_method_chaining
NumberedParametersBasics.demonstrate_mathematical_operations
class MultipleParameterExamples
def self.demonstrate_two_parameters
puts "=== Two Parameter Examples ==="
# Hash iteration
scores = { "Alice" => 95, "Bob" => 87, "Carol" => 92 }
puts "Hash iteration:"
scores.each { |name, score| puts "Traditional: #{name}: #{score}" }
scores.each { puts "Numbered: #{_1}: #{_2}" }
# Transform hash to array
pairs_traditional = scores.map { |name, score| [name, score] }
pairs_numbered = scores.map { [_1, _2] }
puts "\nHash to array conversion:"
puts "Traditional: #{pairs_traditional}"
puts "Numbered: #{pairs_numbered}"
# Array operations with index
fruits = ["apple", "banana", "cherry"]
puts "\nArray with index:"
fruits.each_with_index { |fruit, index| puts "Traditional: #{index}: #{fruit}" }
fruits.each_with_index { puts "Numbered: #{_2}: #{_1}" }
# Filter with condition on both parameters
high_scorers_traditional = scores.select { |name, score| score > 90 }
high_scorers_numbered = scores.select { _2 > 90 }
puts "\nHigh scorers (score > 90):"
puts "Traditional: #{high_scorers_traditional}"
puts "Numbered: #{high_scorers_numbered}"
end
def self.demonstrate_array_operations
puts "\n=== Array Operations with Multiple Parameters ==="
# Array combination operations
arr1 = [1, 2, 3]
arr2 = [4, 5, 6]
zipped_traditional = arr1.zip(arr2).map { |a, b| a + b }
zipped_numbered = arr1.zip(arr2).map { _1 + _2 }
puts "Array addition:"
puts "Traditional: #{zipped_traditional}"
puts "Numbered: #{zipped_numbered}"
# More complex operations
multiplication_traditional = arr1.zip(arr2).map { |a, b| a * b }
multiplication_numbered = arr1.zip(arr2).map { _1 * _2 }
puts "\nArray multiplication:"
puts "Traditional: #{multiplication_traditional}"
puts "Numbered: #{multiplication_numbered}"
# Conditional operations
max_values_traditional = arr1.zip(arr2).map { |a, b| [a, b].max }
max_values_numbered = arr1.zip(arr2).map { [_1, _2].max }
puts "\nMax values:"
puts "Traditional: #{max_values_traditional}"
puts "Numbered: #{max_values_numbered}"
end
def self.demonstrate_reduce_operations
puts "\n=== Reduce Operations ==="
numbers = [1, 2, 3, 4, 5]
# Sum with reduce
sum_traditional = numbers.reduce { |acc, n| acc + n }
sum_numbered = numbers.reduce { _1 + _2 }
puts "Sum:"
puts "Traditional: #{sum_traditional}"
puts "Numbered: #{sum_numbered}"
# Product
product_traditional = numbers.reduce { |acc, n| acc * n }
product_numbered = numbers.reduce { _1 * _2 }
puts "\nProduct:"
puts "Traditional: #{product_traditional}"
puts "Numbered: #{product_numbered}"
# String concatenation
words = ["Ruby", "is", "awesome"]
sentence_traditional = words.reduce { |acc, word| acc + " " + word }
sentence_numbered = words.reduce { _1 + " " + _2 }
puts "\nString concatenation:"
puts "Traditional: #{sentence_traditional}"
puts "Numbered: #{sentence_numbered}"
# Complex reduce operation
data = [
{ name: "Alice", score: 95 },
{ name: "Bob", score: 87 },
{ name: "Carol", score: 92 }
]
# Find highest scorer
highest_traditional = data.reduce { |acc, person| acc[:score] > person[:score] ? acc : person }
highest_numbered = data.reduce { _1[:score] > _2[:score] ? _1 : _2 }
puts "\nHighest scorer:"
puts "Traditional: #{highest_traditional[:name]} (#{highest_traditional[:score]})"
puts "Numbered: #{highest_numbered[:name]} (#{highest_numbered[:score]})"
end
end
MultipleParameterExamples.demonstrate_two_parameters
MultipleParameterExamples.demonstrate_array_operations
MultipleParameterExamples.demonstrate_reduce_operations
class AdvancedNumberedParameters
def self.demonstrate_conditional_logic
puts "=== Conditional Logic with Numbered Parameters ==="
numbers = [-5, -2, 0, 3, 7, 12]
# Ternary operators
abs_values_traditional = numbers.map { |n| n < 0 ? -n : n }
abs_values_numbered = numbers.map { _1 < 0 ? -_1 : _1 }
puts "Absolute values:"
puts "Traditional: #{abs_values_traditional}"
puts "Numbered: #{abs_values_numbered}"
# Complex conditions
categories_traditional = numbers.map do |n|
if n < 0
"negative"
elsif n == 0
"zero"
elsif n < 10
"small positive"
else
"large positive"
end
end
categories_numbered = numbers.map do
if _1 < 0
"negative"
elsif _1 == 0
"zero"
elsif _1 < 10
"small positive"
else
"large positive"
end
end
puts "\nNumber categories:"
puts "Traditional: #{categories_traditional}"
puts "Numbered: #{categories_numbered}"
# Case statements
grades = [95, 87, 76, 65, 45]
letter_grades_traditional = grades.map do |grade|
case grade
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
when 60..69 then "D"
else "F"
end
end
letter_grades_numbered = grades.map do
case _1
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
when 60..69 then "D"
else "F"
end
end
puts "\nLetter grades:"
puts "Traditional: #{letter_grades_traditional}"
puts "Numbered: #{letter_grades_numbered}"
end
def self.demonstrate_string_processing
puts "\n=== String Processing ==="
texts = ["hello world", "RUBY programming", "Mixed Case Text"]
# String transformations
title_case_traditional = texts.map { |text| text.split.map(&:capitalize).join(" ") }
title_case_numbered = texts.map { _1.split.map(&:capitalize).join(" ") }
puts "Title case:"
puts "Traditional: #{title_case_traditional}"
puts "Numbered: #{title_case_numbered}"
# Regular expression operations
emails = ["user@domain.com", "invalid-email", "another@test.org", "not-valid"]
valid_emails_traditional = emails.select { |email| email.match?(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i) }
valid_emails_numbered = emails.select { _1.match?(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i) }
puts "\nValid emails:"
puts "Traditional: #{valid_emails_traditional}"
puts "Numbered: #{valid_emails_numbered}"
# String length filtering and transformation
words = ["a", "hello", "world", "x", "programming", "ruby"]
long_words_traditional = words.select { |word| word.length > 3 }.map { |word| word.upcase }
long_words_numbered = words.select { _1.length > 3 }.map { _1.upcase }
puts "\nLong words (uppercase):"
puts "Traditional: #{long_words_traditional}"
puts "Numbered: #{long_words_numbered}"
end
def self.demonstrate_data_structures
puts "\n=== Complex Data Structure Operations ==="
products = [
{ name: "Laptop", price: 999.99, category: "Electronics" },
{ name: "Book", price: 19.99, category: "Education" },
{ name: "Phone", price: 699.99, category: "Electronics" },
{ name: "Desk", price: 299.99, category: "Furniture" }
]
# Price calculations
prices_traditional = products.map { |product| product[:price] }
prices_numbered = products.map { _1[:price] }
puts "All prices:"
puts "Traditional: #{prices_traditional}"
puts "Numbered: #{prices_numbered}"
# Filtering and transformation
expensive_electronics_traditional = products
.select { |product| product[:category] == "Electronics" }
.select { |product| product[:price] > 500 }
.map { |product| product[:name] }
expensive_electronics_numbered = products
.select { _1[:category] == "Electronics" }
.select { _1[:price] > 500 }
.map { _1[:name] }
puts "\nExpensive electronics:"
puts "Traditional: #{expensive_electronics_traditional}"
puts "Numbered: #{expensive_electronics_numbered}"
# Grouping operations
by_category_traditional = products.group_by { |product| product[:category] }
by_category_numbered = products.group_by { _1[:category] }
puts "\nProducts by category:"
puts "Traditional keys: #{by_category_traditional.keys}"
puts "Numbered keys: #{by_category_numbered.keys}"
# Nested operations
category_stats_traditional = by_category_traditional.transform_values do |products|
{
count: products.length,
avg_price: products.map { |p| p[:price] }.sum / products.length
}
end
category_stats_numbered = by_category_numbered.transform_values do
{
count: _1.length,
avg_price: _1.map { _1[:price] }.sum / _1.length
}
end
puts "\nCategory statistics:"
category_stats_traditional.each { |cat, stats| puts "Traditional #{cat}: #{stats}" }
category_stats_numbered.each { puts "Numbered #{_1}: #{_2}" }
end
end
AdvancedNumberedParameters.demonstrate_conditional_logic
AdvancedNumberedParameters.demonstrate_string_processing
AdvancedNumberedParameters.demonstrate_data_structures
class FunctionalProgramming
def self.demonstrate_functional_patterns
puts "=== Functional Programming Patterns ==="
# Function composition
numbers = [1, 2, 3, 4, 5]
# Traditional function composition
result_traditional = numbers
.map { |n| n * 2 }
.select { |n| n > 5 }
.map { |n| n.to_s }
# Numbered parameters version
result_numbered = numbers
.map { _1 * 2 }
.select { _1 > 5 }
.map { _1.to_s }
puts "Function composition:"
puts "Traditional: #{result_traditional}"
puts "Numbered: #{result_numbered}"
# Currying-like behavior
add_ten = proc { |x| x + 10 }
multiply_by_two = proc { |x| x * 2 }
# Traditional composition
composed_traditional = numbers.map { |n| multiply_by_two.call(add_ten.call(n)) }
# Numbered parameters
composed_numbered = numbers.map { multiply_by_two.call(add_ten.call(_1)) }
puts "\nFunction composition with procs:"
puts "Traditional: #{composed_traditional}"
puts "Numbered: #{composed_numbered}"
end
def self.demonstrate_lazy_evaluation
puts "\n=== Lazy Evaluation ==="
# Large range for demonstration
large_range = (1..1_000_000)
# Find first 5 numbers that satisfy complex condition
start_time = Time.now
result_traditional = large_range
.lazy
.select { |n| n % 7 == 0 }
.map { |n| n ** 2 }
.select { |n| n.to_s.include?("9") }
.first(5)
traditional_time = Time.now - start_time
start_time = Time.now
result_numbered = large_range
.lazy
.select { _1 % 7 == 0 }
.map { _1 ** 2 }
.select { _1.to_s.include?("9") }
.first(5)
numbered_time = Time.now - start_time
puts "Lazy evaluation results:"
puts "Traditional: #{result_traditional}"
puts "Numbered: #{result_numbered}"
puts "Traditional time: #{traditional_time.round(4)}s"
puts "Numbered time: #{numbered_time.round(4)}s"
end
def self.benchmark_performance
puts "\n=== Performance Comparison ==="
require 'benchmark'
data = (1..100_000).to_a
Benchmark.bm(20) do |x|
x.report("Traditional syntax") do
data.map { |n| n * 2 }.select { |n| n > 50_000 }.first(100)
end
x.report("Numbered parameters") do
data.map { _1 * 2 }.select { _1 > 50_000 }.first(100)
end
x.report("Traditional complex") do
data.map { |n| n * 2 + 1 }.select { |n| n.even? }.map { |n| n.to_s }
end
x.report("Numbered complex") do
data.map { _1 * 2 + 1 }.select { _1.even? }.map { _1.to_s }
end
end
end
def self.demonstrate_higher_order_functions
puts "\n=== Higher-Order Functions ==="
# Functions that return functions
def self.create_multiplier(factor)
proc { _1 * factor }
end
def self.create_filter(condition)
proc { condition.call(_1) }
end
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Using higher-order functions with numbered parameters
double = create_multiplier(2)
triple = create_multiplier(3)
is_even = create_filter(proc { _1.even? })
is_greater_than_5 = create_filter(proc { _1 > 5 })
puts "Original: #{numbers}"
puts "Doubled: #{numbers.map(&double)}"
puts "Tripled: #{numbers.map(&triple)}"
puts "Even numbers: #{numbers.select(&is_even)}"
puts "Greater than 5: #{numbers.select(&is_greater_than_5)}"
# Combining higher-order functions
result = numbers
.map(&double)
.select(&is_greater_than_5)
.map { _1.to_s }
puts "Combined operations: #{result}"
end
end
FunctionalProgramming.demonstrate_functional_patterns
FunctionalProgramming.demonstrate_lazy_evaluation
# FunctionalProgramming.benchmark_performance # Uncomment to run benchmark
FunctionalProgramming.demonstrate_higher_order_functions
class RealWorldApplications
def self.demonstrate_log_analysis
puts "=== Log File Analysis ==="
# Simulated log entries
log_entries = [
"2023-01-01 10:00:00 INFO User login: alice@example.com",
"2023-01-01 10:01:15 ERROR Database connection failed",
"2023-01-01 10:02:30 INFO User login: bob@example.com",
"2023-01-01 10:03:45 WARN High memory usage: 85%",
"2023-01-01 10:05:00 ERROR Authentication failed for user: charlie@example.com",
"2023-01-01 10:06:15 INFO User logout: alice@example.com"
]
# Extract error messages
errors_traditional = log_entries
.select { |entry| entry.include?("ERROR") }
.map { |entry| entry.split(" ", 4)[3] }
errors_numbered = log_entries
.select { _1.include?("ERROR") }
.map { _1.split(" ", 4)[3] }
puts "Error messages:"
puts "Traditional: #{errors_traditional}"
puts "Numbered: #{errors_numbered}"
# Count log levels
log_levels_traditional = log_entries
.map { |entry| entry.split(" ")[2] }
.tally
log_levels_numbered = log_entries
.map { _1.split(" ")[2] }
.tally
puts "\nLog level counts:"
puts "Traditional: #{log_levels_traditional}"
puts "Numbered: #{log_levels_numbered}"
# Extract user activities
user_activities_traditional = log_entries
.select { |entry| entry.include?("User") }
.map { |entry| entry.match(/User (\w+): (.+)/)[1..2] }
.group_by { |activity, user| activity }
user_activities_numbered = log_entries
.select { _1.include?("User") }
.map { _1.match(/User (\w+): (.+)/)[1..2] }
.group_by { _1[0] }
puts "\nUser activities:"
user_activities_traditional.each { |activity, users| puts "Traditional #{activity}: #{users.map(&:last)}" }
end
def self.demonstrate_sales_data_processing
puts "\n=== Sales Data Processing ==="
sales_data = [
{ date: "2023-01-01", product: "Laptop", amount: 1200, quantity: 1, salesperson: "Alice" },
{ date: "2023-01-02", product: "Mouse", amount: 25, quantity: 5, salesperson: "Bob" },
{ date: "2023-01-02", product: "Laptop", amount: 1200, quantity: 1, salesperson: "Alice" },
{ date: "2023-01-03", product: "Keyboard", amount: 75, quantity: 3, salesperson: "Charlie" },
{ date: "2023-01-03", product: "Monitor", amount: 300, quantity: 2, salesperson: "Alice" }
]
# Calculate total sales by salesperson
sales_by_person_traditional = sales_data
.group_by { |sale| sale[:salesperson] }
.transform_values { |sales| sales.sum { |sale| sale[:amount] } }
sales_by_person_numbered = sales_data
.group_by { _1[:salesperson] }
.transform_values { _1.sum { _1[:amount] } }
puts "Sales by salesperson:"
puts "Traditional: #{sales_by_person_traditional}"
puts "Numbered: #{sales_by_person_numbered}"
# Find high-value sales (> $500)
high_value_sales_traditional = sales_data
.select { |sale| sale[:amount] > 500 }
.map { |sale| "#{sale[:product]} ($#{sale[:amount]}) by #{sale[:salesperson]}" }
high_value_sales_numbered = sales_data
.select { _1[:amount] > 500 }
.map { "#{_1[:product]} ($#{_1[:amount]}) by #{_1[:salesperson]}" }
puts "\nHigh-value sales:"
high_value_sales_traditional.each { |sale| puts "Traditional: #{sale}" }
high_value_sales_numbered.each { puts "Numbered: #{_1}" }
# Calculate average order value by product
avg_by_product_traditional = sales_data
.group_by { |sale| sale[:product] }
.transform_values { |sales| sales.sum { |sale| sale[:amount] } / sales.length }
avg_by_product_numbered = sales_data
.group_by { _1[:product] }
.transform_values { _1.sum { _1[:amount] } / _1.length }
puts "\nAverage order value by product:"
puts "Traditional: #{avg_by_product_traditional}"
puts "Numbered: #{avg_by_product_numbered}"
end
def self.demonstrate_api_response_processing
puts "\n=== API Response Processing ==="
# Simulated API responses
api_responses = [
{ status: 200, data: { user_id: 1, name: "Alice" }, timestamp: "2023-01-01T10:00:00Z" },
{ status: 404, error: "User not found", timestamp: "2023-01-01T10:01:00Z" },
{ status: 200, data: { user_id: 2, name: "Bob" }, timestamp: "2023-01-01T10:02:00Z" },
{ status: 500, error: "Internal server error", timestamp: "2023-01-01T10:03:00Z" },
{ status: 200, data: { user_id: 3, name: "Charlie" }, timestamp: "2023-01-01T10:04:00Z" }
]
# Extract successful responses
successful_responses_traditional = api_responses
.select { |response| response[:status] == 200 }
.map { |response| response[:data] }
successful_responses_numbered = api_responses
.select { _1[:status] == 200 }
.map { _1[:data] }
puts "Successful responses:"
puts "Traditional: #{successful_responses_traditional}"
puts "Numbered: #{successful_responses_numbered}"
# Error summary
errors_traditional = api_responses
.select { |response| response[:status] != 200 }
.map { |response| { status: response[:status], error: response[:error] } }
errors_numbered = api_responses
.select { _1[:status] != 200 }
.map { { status: _1[:status], error: _1[:error] } }
puts "\nError summary:"
puts "Traditional: #{errors_traditional}"
puts "Numbered: #{errors_numbered}"
# Response time analysis (simulated)
response_times = api_responses.map.with_index { |response, index| [response, rand(100..500)] }
slow_responses_traditional = response_times
.select { |response, time| time > 300 }
.map { |response, time| { status: response[:status], time: time } }
slow_responses_numbered = response_times
.select { _2 > 300 }
.map { { status: _1[:status], time: _2 } }
puts "\nSlow responses (> 300ms):"
puts "Traditional: #{slow_responses_traditional}"
puts "Numbered: #{slow_responses_numbered}"
end
def self.demonstrate_configuration_processing
puts "\n=== Configuration Processing ==="
# Environment configuration
raw_config = {
"DATABASE_URL" => "postgresql://localhost:5432/myapp",
"REDIS_URL" => "redis://localhost:6379",
"LOG_LEVEL" => "info",
"MAX_THREADS" => "5",
"FEATURE_FLAG_NEW_UI" => "true",
"FEATURE_FLAG_ANALYTICS" => "false"
}
# Extract feature flags
feature_flags_traditional = raw_config
.select { |key, value| key.start_with?("FEATURE_FLAG_") }
.transform_keys { |key| key.sub("FEATURE_FLAG_", "").downcase }
.transform_values { |value| value == "true" }
feature_flags_numbered = raw_config
.select { _1.start_with?("FEATURE_FLAG_") }
.transform_keys { _1.sub("FEATURE_FLAG_", "").downcase }
.transform_values { _1 == "true" }
puts "Feature flags:"
puts "Traditional: #{feature_flags_traditional}"
puts "Numbered: #{feature_flags_numbered}"
# Parse numeric configurations
numeric_configs_traditional = raw_config
.select { |key, value| value.match?(/^\d+$/) }
.transform_values { |value| value.to_i }
numeric_configs_numbered = raw_config
.select { _2.match?(/^\d+$/) }
.transform_values { _1.to_i }
puts "\nNumeric configurations:"
puts "Traditional: #{numeric_configs_traditional}"
puts "Numbered: #{numeric_configs_numbered}"
# URL configurations
url_configs_traditional = raw_config
.select { |key, value| value.start_with?("http://", "https://", "redis://", "postgresql://") }
.transform_values { |url| URI.parse(url) rescue nil }
.compact
url_configs_numbered = raw_config
.select { _2.start_with?("http://", "https://", "redis://", "postgresql://") }
.transform_values { URI.parse(_1) rescue nil }
.compact
puts "\nURL configurations:"
url_configs_traditional.each { |key, uri| puts "Traditional #{key}: #{uri.scheme}://#{uri.host}:#{uri.port}" }
url_configs_numbered.each { puts "Numbered #{_1}: #{_2.scheme}://#{_2.host}:#{_2.port}" }
end
end
RealWorldApplications.demonstrate_log_analysis
RealWorldApplications.demonstrate_sales_data_processing
RealWorldApplications.demonstrate_api_response_processing
RealWorldApplications.demonstrate_configuration_processing
class BestPracticesDemo
def self.good_uses
puts "=== Good Uses of Numbered Parameters ==="
data = [1, 2, 3, 4, 5]
# ✅ Simple mathematical operations
squares = data.map { _1 ** 2 }
puts "Squares: #{squares}"
# ✅ Property access
users = [{ name: "Alice" }, { name: "Bob" }]
names = users.map { _1[:name] }
puts "Names: #{names}"
# ✅ Simple filtering
evens = data.select { _1.even? }
puts "Evens: #{evens}"
# ✅ Chaining operations
result = data.map { _1 * 2 }.select { _1 > 5 }.map { _1.to_s }
puts "Chained: #{result}"
end
def self.problematic_uses
puts "\n=== Avoid These Patterns ==="
data = [1, 2, 3, 4, 5]
# ❌ Complex logic (better with named parameters)
def self.complex_bad_example
data.map do
if _1 < 3
result = _1 * 2
result += 1 if _1.odd?
result.to_s.ljust(5, "0")
else
(_1 ** 2 + _1).to_s.reverse
end
end
end
# ✅ Better version with named parameter
def self.complex_good_example
data.map do |num|
if num < 3
result = num * 2
result += 1 if num.odd?
result.to_s.ljust(5, "0")
else
(num ** 2 + num).to_s.reverse
end
end
end
puts "Complex logic results:"
puts "Bad (numbered): #{complex_bad_example}"
puts "Good (named): #{complex_good_example}"
# ❌ Multiple nested levels
nested_data = [[1, 2], [3, 4], [5, 6]]
# This becomes hard to read
flattened_bad = nested_data.map { _1.map { _1 * 2 } }.flatten
puts "\nNested numbered: #{flattened_bad}"
# Better with named parameters
flattened_good = nested_data.map { |pair| pair.map { |num| num * 2 } }.flatten
puts "Nested named: #{flattened_good}"
end
def self.migration_example
puts "\n=== Migration Strategy ==="
# Start with traditional syntax
data = ["hello", "world", "ruby"]
# Step 1: Identify simple transformations
traditional = data.map { |word| word.upcase }
# Step 2: Convert to numbered parameters
numbered = data.map { _1.upcase }
# Step 3: Verify behavior is identical
puts "Traditional: #{traditional}"
puts "Numbered: #{numbered}"
puts "Same result: #{traditional == numbered}"
# Step 4: Consider readability
# For teams new to numbered parameters, document the change
# and ensure everyone understands the syntax
end
def self.performance_considerations
puts "\n=== Performance Considerations ==="
require 'benchmark'
large_array = (1..100_000).to_a
# Performance is generally equivalent
Benchmark.bm(20) do |x|
x.report("Named parameter") do
large_array.map { |n| n * 2 }.first(1000)
end
x.report("Numbered parameter") do
large_array.map { _1 * 2 }.first(1000)
end
end
puts "\nPerformance is typically equivalent."
puts "Choose based on readability, not performance."
end
end
BestPracticesDemo.good_uses
BestPracticesDemo.problematic_uses
BestPracticesDemo.migration_example
# BestPracticesDemo.performance_considerations # Uncomment to run benchmark
Watch and learn numbered block parameters