Skip to content

Commit

Permalink
extended readme
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentToups committed Aug 27, 2009
1 parent 00b427a commit 4e2abfb
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 2 deletions.
107 changes: 107 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -1,3 +1,110 @@
Clojure-like Emacs
------------------

This is a group of loosely organized utilities to add clojure like
abilities to emacs-lisp.

It consists of defn and fn forms for declaring functions and anonymous
functions. These forms support the usual clojure-style destructuring
bind and arity based dispatch on function arguments. Another macro,
dlet, implements destructuring bind for "let". All of them are
lexically scoped, rather than the emacs default dynamic scope.
Despite this, a defn function is an emacs function, and can be
declared interactive.

defn, fn, dlet examples
-----------------------

These work in a manner similar to the clojure equivalents.

(defn f
([x] x)
([x y] (* x y)))
(f 10) ; -> 10
(f 10 20) ; -> 200

This defines a function of one or two arguments. When the function is
called, the correct body is invoked based on arity.

While emacs lacks a special syntax for tables, to does have hash
arrays. This library supports destructuring bind on hash-tables also
via the following syntax:

(defn f [a
[:: z :z :or (tbl! :z 100)]]
(list a z))

(f 10 (tbl! :z 11)) -> (10 11)
(f 10 (tbl!)) -> (10 100)


Note that `(tbl! :z 10)` is short hand which creates a hash table. It
can take multiple arguments: `(tbl! :x 10 :y 11 :z 14). Quick access
to the values in the table is accomplished via `tbl`: `(tbl a-table
:x)` gives the value stored by `:x`. These functions are included int
he library.

Destructuring bind is fully recursive, so you can nest desctructuring
syntax deeply and the macros will do the right thing. The macro
`dlet` works as you expect:

(dlet [x 10 y 11] (+ x y)) ;-> 21

All of them create lexical scopes.

Monads!
-------

I've implemented primitive monad support using this library. These
monads are patterned after the clojure contrib monad implementation
(although they are substantially less complete). Monads use the same
syntax for binding as clojure, so you can do neat things with them.

A simple example is identity monad.

(require 'monads)

(domonad monad-id [x 1 y 2] (+ x y)) ;-> 3

Slightly more interesting is the Maybe monad.

(domonad monad-maybe
[x (Just 20)
k (maybe/ x 4)
y (maybe+ k 1)]
k) ;-> (Just 5)

But:

(domonad monad-maybe
[x (Just 20)
k (maybe/ x 0) ; Divide by zero ruins the calculation
y (maybe+ k 1)]
k) ;-> (None)

Even more interesting is the sequence monad:

(domonad monad-seq
[x (list 1 2 3)
y (list 4 5 6)]
(list x y)) ;-> ((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6))

Note that destructuring bind works with the monads:

(domonad monad-seq
[[a b] (list '(1 2) '(3 4) '(5 6))]
(+ a b)) ;-> (3 7 11)

This is built on top of the fn implementation, so all the
desctructuring supported there works here.

The implementation is wacky right now, but will be cleaned up when I
can find moments of respite from writing my dissertation.





Update 26 Ayg 2009

* fixed a regression in defn code which disabled the ability to make defn's interactive.
Expand Down
4 changes: 2 additions & 2 deletions monads.el
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@
(defn maybe/ [x y]
(if (= 0 y) (None)
(Just (/ x y))))

(comment
(domonad monad-id [x 10 y 11] (+ x y))
(domonad monad-maybe [x (Just 20) k (maybe/ x 4) y (maybe+ k 1)] k)
(domonad monad-maybe [x (Just 20) k (maybe/ x 0) y (maybe+ k 1)] k)
(domonad monad-seq [x (list 1 2 3) y (list 4 5 6)] (list x y))
(domonad monad-seq [x (list 1 2 3) y (list 4 5 6)] (list x y)))

(provide 'monads)

Expand Down

0 comments on commit 4e2abfb

Please sign in to comment.