Skip to content

Instantly share code, notes, and snippets.

@divs1210
Last active November 13, 2018 11:04
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 divs1210/cc02a388e1f2f59a86b60271f7e46750 to your computer and use it in GitHub Desktop.
Save divs1210/cc02a388e1f2f59a86b60271f7e46750 to your computer and use it in GitHub Desktop.
Lazy Seqs in Ruby
# Abstract Class
# ==============
class ISeq
def first
end
def rest
end
def [](idx)
seq = self
idx.times {
seq = seq.rest
}
seq.first
end
def to_s
ret = "["
seq = self
while seq != nil
ret += seq.first.to_s + ", "
seq = seq.rest
end
ret[-2..-1] = "]"
ret
end
end
# Linked List
# ===========
class Cell < ISeq
def initialize(head, tail)
@head = head
@tail = tail
end
def first
@head
end
def rest
@tail
end
end
c_list = Cell.new(1, Cell.new(2, Cell.new(3, nil)))
puts "Linked List: #{c_list}"
# Lazy List
# =========
class LazySeq < ISeq
def initialize(head, rest_fn)
@head = head
@rest_fn = rest_fn
end
def first
@head
end
def rest
@rest_fn.call
end
end
l_list = LazySeq.new 1, ->() { LazySeq.new 2, ->() { LazySeq.new 3, ->() { nil }} }
puts "Lazy List: #{l_list}"
# Lazy methods for ISeq
# =====================
ISeq.class_eval do
def take(n)
if n > 0
LazySeq.new first, ->() do
rest.take n-1
end
else
nil
end
end
def map(f)
LazySeq.new f.call(first), ->() do
tail = rest
if tail
tail.map f
else
->() { nil }
end
end
end
end
# Utils
# =====
def iterate(f, initial)
LazySeq.new initial, ->() {
iterate f, f.call(initial)
}
end
wholes = iterate ->(x) { x+1 }, 0 # whole numbers
evens = wholes.map ->(x) { 2*x } # even numbers
puts "Mapped Lazy List: #{evens.take 5}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment