Lisp Mixin
This module provides Lisp-like functional notation. With this module it almost possible to write real Lisp code in Ruby.
Usage
It’s hardly believable, but the following IS valid ruby code:
(def accumulate (fun, x, list) (if (null? list) x else (accumulate fun, (fun.call x, (car list)), (cdr list)) end) end)
A real programmer can write LISP in any language ;)
- accumulate
- all?
- append
- assoc
- atom?
- car
- cdr
- cons
- consonto
- drop
- equal?
- exists?
- explode
- filter
- foldleft
- foldright
- format
- format
- implode
- length
- link
- list
- map
- member?
- null?
- pair!
- pair?
- pairlis
- prod
- reduce
- reverse
- set
- set_car!
- set_cdr!
- sum
- take
- zip
Class Lisp::DottedPair
Apply lisp format.
[ show source ]
# File lib/facets/more/lisp_format.rb, line 46 def self.format(format, *args) begin state = Format::State.new(args, Format::Output.new) formatter = Format::Formatter.new(format, state) formatter.run rescue => e puts 'Format error: ' + e.message puts format puts ' ' * (e.pos - 1) + '^' if e.respond_to? :pos raise end end
[ show source ]
# File lib/facets/more/lisp.rb, line 280 def accumulate(fun, x, list) if null?(list) x else accumulate(fun, fun.call(x, car(list)), cdr(list)) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 268 def all?(pred, list) if null?(list) true else if pred.call(car(list)) all?(pred, cdr(list)) else false end end end
[ show source ]
# File lib/facets/more/lisp.rb, line 185 def append(l, m) if null?(l) if null?(m) nil else cons(car(m), append(l, cdr(m))) end else cons(car(l), append(cdr(l), m)) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 251 def assoc(x, list) f = filter(lambda { |y| x == car(y)}, list) if null?(f) then nil else car(f) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 169 def atom?(x) not pair?(x) || null?(x) end
[ show source ]
# File lib/facets/more/lisp.rb, line 134 def car(pair) pair = pair!(pair) pair.first end
[ show source ]
# File lib/facets/more/lisp.rb, line 139 def cdr(pair) pair = pair!(pair) pair.second end
Functional API
[ show source ]
# File lib/facets/more/lisp.rb, line 126 def cons(car, cdr) DottedPair.new(car, cdr) end
[ show source ]
# File lib/facets/more/lisp.rb, line 130 def consonto(cdr, car) DottedPair.new(car, cdr) end
[ show source ]
# File lib/facets/more/lisp.rb, line 332 def drop(l, n) if n > 0 and not null?(l) drop(cdr(l), n - 1) else l end end
[ show source ]
# File lib/facets/more/lisp.rb, line 173 def equal?(l, m) l == m end
[ show source ]
# File lib/facets/more/lisp.rb, line 256 def exists?(pred, list) if null?(list) false else if pred.call(car(list)) true else exists?(pred, cdr(list)) end end end
[ show source ]
# File lib/facets/more/lisp.rb, line 304 def explode(string) list(*(string.split(//))) end
[ show source ]
# File lib/facets/more/lisp.rb, line 239 def filter(pred, list) if null?(list) nil else if pred.call(car(list)) cons(car(list), filter(pred, cdr(list))) else filter(pred, cdr(list)) end end end
Alias for accumulate
Alias for reduce
See Lisp::format.
[ show source ]
# File lib/facets/more/lisp_format.rb, line 61 def format(format, *args) Lisp.format(format, *args) end
[ show source ]
# File lib/facets/more/lisp.rb, line 308 def implode(list) accumulate(lambda { |x, y| x + y }, '', list) end
[ show source ]
# File lib/facets/more/lisp.rb, line 197 def length(list) if null?(list) 0 else 1 + length(cdr(list)) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 300 def link(lists) accumulate(lambda { |x, y| append(x, y) }, nil, lists) end
[ show source ]
# File lib/facets/more/lisp.rb, line 177 def list(*elms) if elms.empty? nil else cons(elms.shift, list(*elms)) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 205 def map(fun, list) if null?(list) nil else cons(fun.call(car(list)), map(fun, cdr(list))) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 227 def member?(x, list) if null?(list) false else if x == car(list) true else member?(x, cdr(list)) end end end
[ show source ]
# File lib/facets/more/lisp.rb, line 156 def null?(x) x == nil end
[ show source ]
# File lib/facets/more/lisp.rb, line 164 def pair!(x) return x if pair?(x) return DottedPair[*x] end
[ show source ]
# File lib/facets/more/lisp.rb, line 160 def pair?(x) x.is_a?(DottedPair) end
[ show source ]
# File lib/facets/more/lisp.rb, line 223 def pairlis(l, m) zip(lambda { |x, y| cons(x, y) }, l, m) end
[ show source ]
# File lib/facets/more/lisp.rb, line 316 def prod(list) accumulate(lambda { |x, y| x * y }, 1, list) end
[ show source ]
# File lib/facets/more/lisp.rb, line 290 def reduce(fun, x, list) if null?(list) x else fun.call(car(list), reduce(fun, x, cdr(list))) end end
[ show source ]
# File lib/facets/more/lisp.rb, line 320 def reverse(lists) accumulate(lambda { |x, y| consonto(x, y) }, nil, lists) end
[ show source ]
# File lib/facets/more/lisp.rb, line 144 def set(var, val, binding) eval "var = #{val}", binding end
[ show source ]
# File lib/facets/more/lisp.rb, line 148 def set_car!(pair, val) pair.first = val end
[ show source ]
# File lib/facets/more/lisp.rb, line 152 def set_cdr!(pair, val) pair.second = val end
[ show source ]
# File lib/facets/more/lisp.rb, line 312 def sum(list) accumulate(lambda { |x, y| x + y }, 0, list) end
[ show source ]
# File lib/facets/more/lisp.rb, line 324 def take(l, n) if n > 0 and not null?(l) cons(car(l), take(cdr(l), n - 1)) else nil end end
[ show source ]
# File lib/facets/more/lisp.rb, line 213 def zip(fun, l, m) if null?(l) and null?(m) nil elsif null?(l) or null?(m) raise ArgumentError.new("zip with unequal length lists") else cons(fun.call(car(l), car(m)), zip(fun, cdr(l), cdr(m))) end end