Skip to content

Instantly share code, notes, and snippets.

@ecmendenhall
Last active August 29, 2015 14:06
Show Gist options
  • Save ecmendenhall/d7393bbc965ce6862324 to your computer and use it in GitHub Desktop.
Save ecmendenhall/d7393bbc965ce6862324 to your computer and use it in GitHub Desktop.
# Some simple Ruby transducers
# Based on Rich Hickey's "Transducers" talk at Strangeloop 2014
# https://www.youtube.com/watch?v=6mTbuzafcII
# Clojure:
# (defn mapping [f]
# (fn [step]
# (fn [r x] (step r (f x)))))
def mapping(&procedure)
proc { |&step| proc { |r, x| step.call(r, (procedure.call x)) } }
end
# Clojure:
# (defn filtering [pred]
# (fn [step]
# (fn [r x] (if (pred x) (step r x) r))))
def filtering(&predicate)
proc do |&step|
proc do |r, x|
if predicate.call(x)
step.call(r, x)
else
r
end
end
end
end
# Clojure:
# (def cat
# (fn [step]
# (fn [r x] (reduce step r x))))
# (defn mapcatting [f]
# (comp (map f) cat))
def mapcatting(&procedure)
proc do |&step|
proc do |r, x|
results = (procedure.call x)
results.each do |y|
step.call(r, y)
end
r
end
end
end
# Clojure:
# (defn mapl [f coll]
# (reduce ((mapping f) conj)
# [] coll))
def mapl(collection, &procedure)
collection.inject([], &mapping(&procedure).call(&:<<))
end
# Clojure:
# (defn filterl [f coll]
# (reduce ((filtering f) conj)
# [] coll))
def filterl(collection, &procedure)
collection.inject([], &filtering(&procedure).call(&:<<))
end
# Clojure:
# (defn mapcatl [f coll]
# (reduce ((mapcatting f) conj)
# [] coll))
def mapcatl(collection, &procedure)
collection.inject([], &mapcatting(&procedure).call(&:<<))
end
mapl((1..5), &:succ)
# => [2, 3, 4, 5, 6]
filterl((1..10), &:even?)
# => [1, 3, 5, 7, 9]
mapcatl [1, 3, 5] { |n| [:wut, 'lol' * n] }
# => [:wut, "lol", :wut, "lollollol", :wut, "lollollollollol"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment