Skip to content

Instantly share code, notes, and snippets.

@domgetter
Last active March 24, 2021 02:32
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save domgetter/e6edc10303347a1084e1 to your computer and use it in GitHub Desktop.
Save domgetter/e6edc10303347a1084e1 to your computer and use it in GitHub Desktop.
map = -> f {
-> rf {
-> acc, elem {
rf[acc, f[elem]]
}
}
}
square = -> n { n**2 }
add = -> acc, n { acc + n }
[1,2,3].reduce(0, &map[square][add])
#=> 14
notify = -> n {puts "Working on: #{n}"; n}
[1,2,3].reduce(0, &map[notify][add])
# Working on: 1
# Working on: 2
# Working on: 3
#=> 6
# We can compose these nicely
notify_then_square = -> n { square[notify[n]] }
[1, 2, 3].reduce(0, &map[notify_then_square][add])
# Working on: 1
# Working on: 2
# Working on: 3
#=> 14
square_then_notify = -> n { notify[square[n]] }
[1, 2, 3].reduce(0, &map[square_then_notify][add])
# Working on: 1
# Working on: 4
# Working on: 9
#=> 14
# Given the same implementation of map, we can reduce into other things
require 'set'
append_to_set = -> set, elem {set << elem}
[1, 2, 2, 3].reduce(Set.new, &map[notify][append_to_set])
# Working on: 1
# Working on: 2
# Working on: 2
# Working on: 3
#=> #<Set: {1, 2, 3}>
enqueue = -> queue, elem {queue.enq(elem)}
q = [1, 2, 3].reduce(Queue.new, &map[notify][enqueue])
# Working on: 1
# Working on: 2
# Working on: 3
#=> #<Thread::Queue:0x00000002a557d8>
3.times {puts q.deq}
# 1
# 2
# 3
#=> 3
# It's also faster than the transducers gem
require 'transducers'
t = Time.now; 100000.times {(1..3).reduce(0, &map[:succ.to_proc][:+.to_proc])}; puts Time.now - t
# 0.200011
#=> nil
t = Time.now; 100000.times {Transducers.transduce(Transducers.map(:succ), :+, 0, 1..3)}; puts Time.now - t
# 0.586033
#=> nil
# But still slower than the Ruby way, though this may be due to writing the transducer in Ruby, instead of as a C extension
t = Time.now; 100000.times {(1..3).reduce(0, &map[:succ.to_proc][:+.to_proc])}; puts Time.now - t
# 0.200011
#=> nil
t = Time.now; 100000.times {(1..3).map(&:succ).reduce(0, &:+)}; puts Time.now - t
# 0.126008
#=> nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment