Module: Lisp
- Included in:
- DottedPair
- Defined in:
- lib/mega/lisp.rb
Overview
:title: Lisp Mixin
This module provides Lisp-like functional notation. With this module it almost possibel 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 ;)
Author(s)
-
Florian Frank
Defined Under Namespace
Classes: DottedPair
Instance Method Summary collapse
- #accumulate(fun, x, list) ⇒ Object (also: #foldleft)
- #all?(pred, list) ⇒ Boolean
- #append(l, m) ⇒ Object
- #assoc(x, list) ⇒ Object
- #atom?(x) ⇒ Boolean
- #car(pair) ⇒ Object
- #cdr(pair) ⇒ Object
-
#cons(car, cdr) ⇒ Object
Functional API.
- #consonto(cdr, car) ⇒ Object
- #drop(l, n) ⇒ Object
- #equal?(l, m) ⇒ Boolean
- #exists?(pred, list) ⇒ Boolean
- #explode(string) ⇒ Object
- #filter(pred, list) ⇒ Object
- #implode(list) ⇒ Object
- #length(list) ⇒ Object
- #link(lists) ⇒ Object
- #list(*elms) ⇒ Object
- #map(fun, list) ⇒ Object
- #member?(x, list) ⇒ Boolean
- #null?(x) ⇒ Boolean
- #pair!(x) ⇒ Object
- #pair?(x) ⇒ Boolean
- #pairlis(l, m) ⇒ Object
- #prod(list) ⇒ Object
- #reduce(fun, x, list) ⇒ Object (also: #foldright)
- #reverse(lists) ⇒ Object
- #set(var, val, binding) ⇒ Object
- #set_car!(pair, val) ⇒ Object
- #set_cdr!(pair, val) ⇒ Object
- #sum(list) ⇒ Object
- #take(l, n) ⇒ Object
- #zip(fun, l, m) ⇒ Object
Instance Method Details
#accumulate(fun, x, list) ⇒ Object Also known as: foldleft
283 284 285 286 287 288 289 |
# File 'lib/mega/lisp.rb', line 283 def accumulate(fun, x, list) if null?(list) x else accumulate(fun, fun.call(x, car(list)), cdr(list)) end end |
#all?(pred, list) ⇒ Boolean
271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/mega/lisp.rb', line 271 def all?(pred, list) if null?(list) true else if pred.call(car(list)) all?(pred, cdr(list)) else false end end end |
#append(l, m) ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/mega/lisp.rb', line 188 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 |
#assoc(x, list) ⇒ Object
254 255 256 257 |
# File 'lib/mega/lisp.rb', line 254 def assoc(x, list) f = filter(lambda { |y| x == car(y)}, list) if null?(f) then nil else car(f) end end |
#atom?(x) ⇒ Boolean
172 173 174 |
# File 'lib/mega/lisp.rb', line 172 def atom?(x) not pair?(x) || null?(x) end |
#car(pair) ⇒ Object
137 138 139 140 |
# File 'lib/mega/lisp.rb', line 137 def car(pair) pair = pair!(pair) pair.first end |
#cdr(pair) ⇒ Object
142 143 144 145 |
# File 'lib/mega/lisp.rb', line 142 def cdr(pair) pair = pair!(pair) pair.second end |
#cons(car, cdr) ⇒ Object
Functional API
129 130 131 |
# File 'lib/mega/lisp.rb', line 129 def cons(car, cdr) DottedPair.new(car, cdr) end |
#consonto(cdr, car) ⇒ Object
133 134 135 |
# File 'lib/mega/lisp.rb', line 133 def consonto(cdr, car) DottedPair.new(car, cdr) end |
#drop(l, n) ⇒ Object
335 336 337 338 339 340 341 |
# File 'lib/mega/lisp.rb', line 335 def drop(l, n) if n > 0 and not null?(l) drop(cdr(l), n - 1) else l end end |
#equal?(l, m) ⇒ Boolean
176 177 178 |
# File 'lib/mega/lisp.rb', line 176 def equal?(l, m) l == m end |
#exists?(pred, list) ⇒ Boolean
259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/mega/lisp.rb', line 259 def exists?(pred, list) if null?(list) false else if pred.call(car(list)) true else exists?(pred, cdr(list)) end end end |
#explode(string) ⇒ Object
307 308 309 |
# File 'lib/mega/lisp.rb', line 307 def explode(string) list(*(string.split(//))) end |
#filter(pred, list) ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/mega/lisp.rb', line 242 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 |
#implode(list) ⇒ Object
311 312 313 |
# File 'lib/mega/lisp.rb', line 311 def implode(list) accumulate(lambda { |x, y| x + y }, '', list) end |
#length(list) ⇒ Object
200 201 202 203 204 205 206 |
# File 'lib/mega/lisp.rb', line 200 def length(list) if null?(list) 0 else 1 + length(cdr(list)) end end |
#link(lists) ⇒ Object
303 304 305 |
# File 'lib/mega/lisp.rb', line 303 def link(lists) accumulate(lambda { |x, y| append(x, y) }, nil, lists) end |
#list(*elms) ⇒ Object
180 181 182 183 184 185 186 |
# File 'lib/mega/lisp.rb', line 180 def list(*elms) if elms.empty? nil else cons(elms.shift, list(*elms)) end end |
#map(fun, list) ⇒ Object
208 209 210 211 212 213 214 |
# File 'lib/mega/lisp.rb', line 208 def map(fun, list) if null?(list) nil else cons(fun.call(car(list)), map(fun, cdr(list))) end end |
#member?(x, list) ⇒ Boolean
230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/mega/lisp.rb', line 230 def member?(x, list) if null?(list) false else if x == car(list) true else member?(x, cdr(list)) end end end |
#null?(x) ⇒ Boolean
159 160 161 |
# File 'lib/mega/lisp.rb', line 159 def null?(x) x == nil end |
#pair!(x) ⇒ Object
167 168 169 170 |
# File 'lib/mega/lisp.rb', line 167 def pair!(x) return x if pair?(x) return DottedPair[*x] end |
#pair?(x) ⇒ Boolean
163 164 165 |
# File 'lib/mega/lisp.rb', line 163 def pair?(x) x.is_a?(DottedPair) end |
#pairlis(l, m) ⇒ Object
226 227 228 |
# File 'lib/mega/lisp.rb', line 226 def pairlis(l, m) zip(lambda { |x, y| cons(x, y) }, l, m) end |
#prod(list) ⇒ Object
319 320 321 |
# File 'lib/mega/lisp.rb', line 319 def prod(list) accumulate(lambda { |x, y| x * y }, 1, list) end |
#reduce(fun, x, list) ⇒ Object Also known as: foldright
293 294 295 296 297 298 299 |
# File 'lib/mega/lisp.rb', line 293 def reduce(fun, x, list) if null?(list) x else fun.call(car(list), reduce(fun, x, cdr(list))) end end |
#reverse(lists) ⇒ Object
323 324 325 |
# File 'lib/mega/lisp.rb', line 323 def reverse(lists) accumulate(lambda { |x, y| consonto(x, y) }, nil, lists) end |
#set(var, val, binding) ⇒ Object
147 148 149 |
# File 'lib/mega/lisp.rb', line 147 def set(var, val, binding) eval "var = #{val}", binding end |
#set_car!(pair, val) ⇒ Object
151 152 153 |
# File 'lib/mega/lisp.rb', line 151 def set_car!(pair, val) pair.first = val end |
#set_cdr!(pair, val) ⇒ Object
155 156 157 |
# File 'lib/mega/lisp.rb', line 155 def set_cdr!(pair, val) pair.second = val end |
#sum(list) ⇒ Object
315 316 317 |
# File 'lib/mega/lisp.rb', line 315 def sum(list) accumulate(lambda { |x, y| x + y }, 0, list) end |
#take(l, n) ⇒ Object
327 328 329 330 331 332 333 |
# File 'lib/mega/lisp.rb', line 327 def take(l, n) if n > 0 and not null?(l) cons(car(l), take(cdr(l), n - 1)) else nil end end |
#zip(fun, l, m) ⇒ Object
216 217 218 219 220 221 222 223 224 |
# File 'lib/mega/lisp.rb', line 216 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 |