class Obfusk::List
Lazy List
Public Class Methods
– Monad
–
# File lib/obfusk/list.rb, line 236 def self.mreturn(x) Cons x, Nil() end
Public Instance Methods
element at index
# File lib/obfusk/list.rb, line 101 def [](i) raise ArgumentError, 'negative index' if i < 0 j = 0; each { |x| return x if i == j; j += 1 } raise ArgumentError, 'index too large' end
pretend to be lazy (so we don’t need Obfusk.eager
)
# File lib/obfusk/list.rb, line 72 def _ self end
# File lib/obfusk/list.rb, line 50 def _compare_data(rhs) match Nil: -> (_) { 0 }, Cons: -> (_) { [head,tail] <=> [rhs.head,rhs.tail] } end
# File lib/obfusk/list.rb, line 45 def _eq_data(rhs) match Nil: -> (_) { true }, Cons: -> (_) { [head,tail] == [rhs.head,rhs.tail] } end
append two lists
# File lib/obfusk/list.rb, line 127 def append(ys) match Nil: -> (_) { ys._ }, Cons: -> (_) { Cons(head) { tail.append ys } } end
pretend to be lazy (see _)
# File lib/obfusk/list.rb, line 77 def chain(m,*a,&b) ::Obfusk.lazy { public_send(m,*a,&b) } end
concatenate a list of lists
# File lib/obfusk/list.rb, line 164 def concat foldr(Nil()) { |x,ys| x.append ys } end
–
# File lib/obfusk/list.rb, line 57 def each(&b) return enum_for :each unless b xs = self; while xs != Nil() do b[xs.head]; xs = xs.tail end end
the list of those elements that satisfy the predicate
# File lib/obfusk/list.rb, line 84 def filter(p = nil, &b) g = p || b match Nil: -> (_) { Nil() }, Cons: -> (_) { g[head] ? Cons(head) { tail.filter(g) } : tail.filter(g) } end
foldr, applied to a binary operator, a starting value (typically the right-identity of the operator), and a list, reduces the list using the binary operator, from right to left:
“‘haskell foldr f z [x1, x2, …, xn] == x1 `f` (x2 `f` … (xn `f` z)…) “`
NB: because ruby is not lazy, the secons argument of the binary operator is lazy and must be treated as such.
# File lib/obfusk/list.rb, line 149 def foldr(z, f = nil, &b) g = f || b match Nil: -> (_) { z }, Cons: -> (_) { g[head, tail.chain(:foldr, z, g)] } end
length
# File lib/obfusk/list.rb, line 108 def length n = 0; each { n += 1 }; n end
the list obtained by applying a function (or block) to each element
# File lib/obfusk/list.rb, line 92 def map(f = nil, &b) g = f || b match Nil: -> (_) { Nil() }, Cons: -> (_) { Cons(g[head]) { tail.map g } } end
empty?
# File lib/obfusk/list.rb, line 113 def null match Nil: -> (_) { true }, Cons: -> (_) { false } end
the prefix of length n (or the list itself if n > length)
# File lib/obfusk/list.rb, line 192 def take(n) return Nil() if n <= 0 match Nil: -> (_) { Nil() }, Cons: -> (_) { Cons(head) { tail.take(n - 1) } } end
# File lib/obfusk/list.rb, line 67 def to_a each.to_a end
# File lib/obfusk/list.rb, line 62 def to_s *xs, x = self.class.name.split '::'; n = xs*'::' + '.' + x self == Nil() ? "<##{n}>" : "<##{n}(#{head},...)>" end
combine parallel elements of two lists using a binary operator
# File lib/obfusk/list.rb, line 217 def zipWith(ys, f = nil, &b) g = f || b self == Nil() || ys._ == Nil() ? Nil() : Cons(g[head, ys._.head]) { tail.zipWith(ys._.tail, g) } end