Skip to content

Instantly share code, notes, and snippets.

@dchelimsky
Last active December 24, 2015 13:49
Show Gist options
  • Save dchelimsky/6808471 to your computer and use it in GitHub Desktop.
Save dchelimsky/6808471 to your computer and use it in GitHub Desktop.
Prototype higher order function to compose lambdas in Ruby. Result of working with Matt Wynne on a means of wrapping filters in Cucumber (Ruby).
require 'wrong/adapters/rspec'
# (apply comp fns) in clojure
module Composer
def compose((*rest, last))
last ||= ->(x){x}
rest_reversed = rest.reverse_each
lambda do |*args|
rest_reversed.reduce(last[*args]) {|result, fn| fn[result]}
end
end
module_function :compose
end
describe Composer do
describe ".compose" do
it "returns identity with no fns" do
empty = Composer.compose([])
assert { empty.call(3) == 3 }
end
it "composes with 1 fns" do
double = ->(x) { x + x }
composed_double = Composer.compose([double])
assert { composed_double.call(3) == 6 }
end
it "composes with 2 fns" do
double = ->(x) { x + x }
square = ->(x) { x * x }
square_double = Composer.compose([square, double])
assert { square_double.call(3) == 36 }
end
it "composes with 3 fns" do
double = ->(x) { x * 2 }
triple = ->(x) { x * 3 }
square = ->(x) { x * x }
square_double_triple = Composer.compose([square, double, triple])
assert { square_double_triple.call(3) == 18*18 }
end
it "composes with no-arg fn at end" do
double = ->(x) { x * 2 }
triple = ->(x) { x * 3 }
square = ->(x) { x * x }
three = -> (){3}
square_double_triple = Composer.compose([square, double, triple, three])
assert { square_double_triple.call == 18*18 }
end
end
end
@tomstuart
Copy link

@dchelimsky Your changes don’t seem to incorporate @threedaymonk’s suggestion of using #reverse_each, which is preferable to #reverse since it doesn’t involve allocating a new array.

@dchelimsky
Copy link
Author

@tomstuart right you are - fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment