Last active
December 24, 2015 13:49
-
-
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oh, and @threedaymonk wisely suggests achieving an rfold with reverse_each.inject
instead of reverse.inject
, which is better all round.
I didn't know about Facets. Facets contains a compose
method on Proc
, but nothing that works on a collection of procs like the clojure one does. I've refactored this code us use the Facets Proce#compose
. It's simpler but it would still be nice to see it on an Array
I think.
@tomstuart: updated with suggestions from you and @threedaymonk.
@mattwynne WDYT?
@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.
@tomstuart right you are - fixed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
(Although it would be better to precompute
rest.reverse
before returning thelambda
.)