metaprogramming/advanced/custom_iterators.rb

tests/_examples/metaprogramming/advanced/custom_iterators.rb in the metorex repository.

# Custom Iterators: Build iterator patterns using blocks
# Demonstrates: yield-like patterns, higher-order functions, closures

# Custom each_with_index using a counter
def each_with_index(array, &block)
  i = 0
  array.each do |item|
    block.call(item, i)
    i += 1
  end
end

puts "=== each_with_index ==="
each_with_index(["apple", "banana", "cherry"]) do |item, idx|
  puts "#{idx}: #{item}"
end

# Custom times iterator
def times(n, &block)
  i = 0
  while i < n
    block.call(i)
    i += 1
  end
end

puts ""
puts "=== times ==="
times(5) do |i|
  puts "Iteration #{i}"
end

# Custom reduce/fold
def reduce(array, initial, &block)
  acc = initial
  array.each do |item|
    acc = block.call(acc, item)
  end
  acc
end

puts ""
puts "=== reduce ==="
sum = reduce([1, 2, 3, 4, 5], 0) do |acc, n|
  acc + n
end
puts "Sum: #{sum}"

product = reduce([1, 2, 3, 4, 5], 1) do |acc, n|
  acc * n
end
puts "Product: #{product}"

# Custom flat_map
def flat_map(array, &block)
  result = []
  array.each do |item|
    mapped = block.call(item)
    mapped.each do |sub|
      result.push(sub)
    end
  end
  result
end

puts ""
puts "=== flat_map ==="
nested = [[1, 2], [3, 4], [5, 6]]
flattened = flat_map(nested) do |arr|
  arr
end
puts flattened

# Custom take_while
def take_while(array, &block)
  result = []
  done = false
  array.each do |item|
    if !done && block.call(item)
      result.push(item)
    else
      done = true
    end
  end
  result
end

puts ""
puts "=== take_while ==="
numbers = [2, 4, 6, 7, 8, 10]
evens = take_while(numbers) do |n|
  n % 2 == 0
end
puts evens

Output:

=== each_with_index ===
0: apple
1: banana
2: cherry

=== times ===
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4

=== reduce ===
Sum: 15
Product: 120

=== flat_map ===
1
2
3
4
5
6

=== take_while ===
2
4
6