Skip to content

Instantly share code, notes, and snippets.

@jin
Created November 21, 2014 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jin/4f49662e1587fda22401 to your computer and use it in GitHub Desktop.
Save jin/4f49662e1587fda22401 to your computer and use it in GitHub Desktop.
Functional Ruby: implementing commonly used functions with lambda objects
# Regular Ruby methods, can't pass them around like function objects
def length(xs)
return 0 if xs.empty?
1 + length(xs[1..-1])
end
def map(xs, process = -> (x) { x })
return [] if xs.empty?
[process.call(xs.first)] + map(xs[1..-1], process)
end
# Lambda objects
length_func = -> (xs) { xs.empty? ? 0 : 1 + length_func.call(xs[1..-1])}
map_func = -> (xs, process) do
return [] if xs.empty?
[process.call(xs.first)] + map_func.call(xs[1..-1], process)
end
filter_func = -> (xs, filter) do
return [] if xs.empty?
x = xs.first
if filter.call(x)
[x] + filter_func.call(xs[1..-1], filter)
else
filter_func.call(xs[1..-1], filter)
end
end
take_func = -> (xs, num) do
return [] if xs.empty? || num.to_i <= 0
[xs.first] + take_func.call(xs[1..-1], num - 1)
end
# Testing
puts length [] # => 0
puts length [1, 2, 3] # => 3
puts length_func.call([]) # => 0
puts length_func.call([1, 2, 3]) # => 3
p map([]) # => []
p map([1, 2]) # => [1, 2]
p map([1, 2, 3], Proc.new { |x| x.to_i * x.to_i } ) # => [1, 4, 9]
p map([1, 2, "foo"], Proc.new { |x| x.to_i * x.to_i } ) # => [1, 4, 9]
p map_func.call([1, 2, 3], Proc.new { |x| x.to_i * x.to_i }) # => [1, 4, 9]
p map_func.call([1, 2, "foo"], Proc.new { |x| x.to_i * x.to_i }) # => [1, 4, 0]
p filter_func.call([], -> (x) { x } ) # => []
p filter_func.call([1, 2, 3], -> (x) { x.odd? }) # => [1, 3]
p take_func.call([], 1) # => []
p take_func.call([1, 2, 3], 0) # => []
p take_func.call([1, 2, 3], 2) # => [1, 2]
p take_func.call(map_func.call(filter_func.call((1..3000).to_a, -> (x) { x.odd? } ), -> (x) { x * x }), 42)
# => [1, 9, 25, 49, 81, 121, 169, 225, 289, 361, 441, 529, 625, 729, 841, 961, 1089, 1225, 1369, 1521, 1681, 1849, 2025, 2209, 2401, 2601, 2809, 3025, 3249, 3481, 3721, 3969, 4225, 4489, 4761, 5041, 5329, 5625, 5929, 6241, 6561, 6889]
# Stack too deep for 10000 elements array
# p take_func.call(map_func.call(filter_func.call((1..10000).to_a, -> (x) { x.odd? } ), -> (x) { x * x }), 42)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment