Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add implement-map-in-lisp-in-ruby

  • Loading branch information...
commit e55da8ddbfddf468bf2376132fa103e3e9185805 1 parent 7d5787f
@JoshCheek JoshCheek authored
View
1  Readme.mdown
@@ -13,6 +13,7 @@ Playgrounds
* [craigslist-watcher](http://github.com/JoshCheek/Play/tree/master/craigslist-watcher/) Script to check my local craigslist free page for the given item (in my case, free computers).
* [fsm](http://github.com/JoshCheek/Play/tree/master/fsm/) Finite state machine in C through macros.
* [html-consolidated](http://github.com/JoshCheek/Play/tree/master/html-consolidated/) Use gcc's preparser to consolidate content into an html page (such as css and javascript libraries) so you can give someone a single html page with no external dependencies.
+* [implement-map-in-lisp-in-ruby](http://github.com/JoshCheek/Play/tree/master/implement-map-in-lisp-in-ruby/) Implementing Lisp's map function (technically done in Ruby)
* [irb](http://github.com/JoshCheek/Play/tree/master/irb/) Proof of concept for an interactive Ruby repl like irb.
* [lisp-games](http://github.com/JoshCheek/Play/tree/master/lisp-games/) Some simple command line games created with Lisp, so that I would have some hands-on experience writing my own, since [Land of Lisp][landoflisp] is mostly about reading Barski's Lisp.
* [lisp-tree](http://github.com/JoshCheek/Play/tree/master/lisp-tree/) Create, traverse, and generate images for a tree structure in lisp.
View
35 implement-map-in-lisp-in-ruby/Readme.md
@@ -0,0 +1,35 @@
+Description
+===========
+
+Was talking to one of the craftsmen at [8th Light](http://www.8thlight.com/), who was saying
+that it was talking about implementing map in his own lisp. Figured I'd give it a shot.
+Cheated a bit in that I built it mostly out of Ruby, but the map function is all within the paradigm.
+
+
+---------------------------------------
+
+**This code is unmaintained.**
+
+_If you do something interesting with it, let me know so I can be happy._
+
+---------------------------------------
+
+Copyright (c) 2011 Joshua Cheek
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
View
99 implement-map-in-lisp-in-ruby/implement-map-in-lisp-in-ruby.rb
@@ -0,0 +1,99 @@
+# === booleans ===
+t = ->(first, second) { first } # true
+f = ->(first, second) { second } # false
+n = ->() { n } # nil
+_if = ->(bool, consequent, alternative) { bool[consequent, alternative][] }
+do_if = ->(bool, consequent) { _if[bool, consequent, n] }
+do_unless = ->(bool, consequent) { _if[bool, n, consequent] }
+are_equal = ->(lhs, rhs) { lhs == rhs ? t : f } # <-- cheating here
+
+
+define_singleton_method :assert do |bool|
+ do_unless[bool, -> { raise }]
+end
+
+define_singleton_method :refute do |bool|
+ do_if[bool, -> { raise }]
+end
+
+define_singleton_method :assert_equal do |lhs, rhs|
+ assert are_equal[lhs, rhs]
+end
+
+ # tests
+ assert t
+ refute f
+
+ assert _if[t, ->{t}, ->{f}]
+ refute _if[f, ->{t}, ->{f}]
+
+ assert are_equal[f, f]
+ assert are_equal[t, t]
+ assert are_equal[1, 1]
+ refute are_equal[0, 1]
+ refute are_equal[t, f]
+ refute are_equal[n, f]
+ refute are_equal[f, n]
+
+ assert_equal t, do_if[t, ->{t}]
+ assert_equal n, do_if[f, ->{t}]
+ assert_equal n, do_unless[t, ->{t}]
+ assert_equal t, do_unless[f, ->{t}]
+
+
+# === numeric ===
+is_zero = ->(num) { are_equal[num, 0] }
+subtract = ->(minuend, subtrahend) { minuend - subtrahend }
+
+ # tests
+ assert is_zero[0]
+ assert is_zero[0.0]
+ refute is_zero[1]
+
+ assert_equal 3, subtract[4, 1]
+
+
+# === lists ===
+cons = ->(first, second=n) {
+ # returns a lambda that will return first element if given t, rest if given f
+ ->(bool) {
+ _if[ bool,
+ -> { first },
+ -> { second }]}}
+
+car = ->(list) { list[t] }
+
+cdr = ->(list) { list[f] }
+
+is_empty = ->(list) { are_equal[list, n] }
+
+map = ->(list, function ) {
+ _if[ is_empty[list],
+ -> { n },
+ -> { cons[ function[car[list]],
+ map[cdr[list],
+ function]]}]}
+
+ # tests
+ assert_equal 1, car[cons[1, 2]]
+ assert_equal 2, cdr[cons[1, 2]]
+ assert_equal 1, car[cons[1]]
+ assert_equal n, cdr[cons[1]]
+
+ assert is_empty[n]
+ refute is_empty[cons[1, n]]
+
+ double = ->(num) { num + num }
+ identity = ->(element) { element }
+ one_to_five = cons[1, cons[2, cons[3, cons[4, cons[5]]]]]
+
+ assert_equal n, map[n, identity]
+ assert_equal 2, car[map[cons[1], double]]
+
+ assert_equal 2, car[ map[one_to_five, double] ]
+ assert_equal 4, car[cdr[ map[one_to_five, double] ]]
+ assert_equal 6, car[cdr[cdr[ map[one_to_five, double] ]]]
+ assert_equal 8, car[cdr[cdr[cdr[ map[one_to_five, double] ]]]]
+ assert_equal 10, car[cdr[cdr[cdr[cdr[ map[one_to_five, double] ]]]]]
+ assert_equal n, cdr[cdr[cdr[cdr[cdr[ map[one_to_five, double] ]]]]]
+
Please sign in to comment.
Something went wrong with that request. Please try again.