Skip to content

Commit

Permalink
Merge pull request jduey#8 from roman/clojurescript
Browse files Browse the repository at this point in the history
Add support for Clojurescript
  • Loading branch information
jduey committed Jan 31, 2013
2 parents 999d448 + 224a151 commit c9a28a3
Show file tree
Hide file tree
Showing 12 changed files with 1,129 additions and 709 deletions.
7 changes: 7 additions & 0 deletions .gitignore
@@ -0,0 +1,7 @@
.lein-*
node_modules/
resources/js/protocol_monads_dev.js
resources/js/protocol_monads_browser_test.js
resources/js/protocol_monads_browser_optimized_test.js
resources/js/protocol_monads_node_test.js
target/
22 changes: 22 additions & 0 deletions .travis.yml
@@ -0,0 +1,22 @@
language:
- node_js
- clojure
lein: lein2
jdk:
- oraclejdk7
node_js:
- "0.8"
before_script:
- "export DISPLAY=:99:0"
- "echo 'Compile to javascript'"
- "lein2 cljsbuild once"
- "echo 'Starting buster server'"
- "./node_modules/buster/bin/buster-server &"
- "sleep 3"
- "echo 'Done.'"
- "echo 'Starting phantomjs server'"
- "phantomjs ./node_modules/buster/script/phantom.js &"
- "sleep 3"
- "echo 'Done.'"
script:
- lein2 test && npm test
14 changes: 14 additions & 0 deletions buster.js
@@ -0,0 +1,14 @@
var config = exports;

config['Browser Tests'] = {
environment: 'browser',
sources: [],
tests: [ "resources/js/protocol_monads_browser_test.js"
, "resources/js/protocol_monads_browser_optimized_test.js" ]
};

config['Node Tests'] = {
environment: 'node',
sources: [],
tests: ["resources/js/protocol_monads_node_test.js"]
};
14 changes: 14 additions & 0 deletions dalap_rules.clj
@@ -0,0 +1,14 @@
{
["src/clj/monads/core.clj" "src/cljs/monads/core.cljs"]
['clojure.lang.PersistentList 'List
'clojure.lang.PersistentList$EmptyList 'EmptyList
'clojure.lang.PersistentVector 'PersistentVector
'clojure.lang.PersistentHashSet 'PersistentHashSet
'clojure.lang.LazySeq 'LazySeq
'clojure.lang.IFn 'IFn
'clojure.lang.IDeref 'IDeref
'deref '-deref
'invoke '-invoke]
["test/clj/monads/test/core_test.clj" "test/cljs/monads/test/core_test.cljs"]
[]
}
8 changes: 8 additions & 0 deletions package.json
@@ -0,0 +1,8 @@
{
"name": "protocol-monads",
"description": "",
"version": "1.0.0",
"author": "",
"dependencies" : { "buster" : "0.6.12" },
"scripts": { "test": "buster-test -e node && buster-test -e browser" }
}
44 changes: 42 additions & 2 deletions project.clj
@@ -1,3 +1,43 @@
(defproject net.clojure/monads "1.0.0"
(defproject net.clojure/monads "1.0.1-SNAPSHOT"
:description "A protocol based implementation of monads"
:dependencies [[org.clojure/clojure "1.4.0"]])
:dependencies [[org.clojure/clojure "1.4.0"]]
:source-paths ["src/clj"]
:test-paths ["test/clj"]
:profiles {:dev {:dependencies [[com.birdseye-sw/buster-cljs "0.1.0"]]
:plugins [[lein-cljsbuild "0.2.9"]
[com.birdseye-sw/lein-dalap "0.1.0"]]}}
:hooks [leiningen.dalap]

:cljsbuild
{:builds
[{:id :dev
:source-path "src/cljs"
:compiler
{:output-to "resources/js/protocol_monads_dev.js"
:optimizations :simple
:pretty-print true}}
{:id :browser-test
:source-path "test/cljs"
:compiler
{:output-to "resources/js/protocol_monads_browser_test.js"
:libraries ["resources/js/protocol_monads_dev.js"]
:externs ["externs/buster.js"]
:optimizations :simple
:pretty-print true}}
{:id :browser-test-optimized
:source-path "test/cljs"
:compiler
{:output-to "resources/js/protocol_monads_browser_optimized_test.js"
:libraries ["resources/js/protocol_monads_dev.js"]
:externs ["externs/buster.js"]
:optimizations :advanced}}
{:id :node-test
:source-path "test/cljs"
:compiler
{:output-to "resources/js/protocol_monads_node_test.js"
:libraries ["resources/js/protocol_monads_dev.js"]
:externs ["externs/buster.js"]
:optimizations :simple
:pretty-print true}}]}

)
73 changes: 35 additions & 38 deletions src/monads/core.clj → src/clj/monads/core.clj
Expand Up @@ -6,6 +6,7 @@
; the terms of this license.
; You must not remove this notice, or any other, from this software.


(ns monads.core
(:refer-clojure :exclude [do seq map])
(:require [clojure.set :as set]))
Expand All @@ -21,33 +22,6 @@
(defn plus [[mv & mvs]]
(plus-step mv mvs))

(defmacro do
"Monad comprehension. Takes the name of a monad (like vector, hash-set),
a vector of steps given as binding-form/monadic-expression pairs, and
a result value specified by expr. The monadic-expression terms can use
the binding variables of the previous steps.
If the monad contains a definition of m-zero, the step list can also
contain conditions of the form :when p, where the predicate p can
contain the binding variables from all previous steps.
A clause of the form :let [binding-form expr ...], where the bindings
are given as a vector as for the use in let, establishes additional
bindings that can be used in the following steps."
[result bindings expr]
(let [steps (partition 2 bindings)]
`(monads.core/bind (~result nil)
(fn [_#]
~(reduce (fn [expr [sym mv]]
(cond
(= :when sym) `(if ~mv
~expr
(monads.core/zero (~result nil)))
(= :let sym) `(let ~mv
~expr)
:else `(monads.core/bind ~mv (fn [~sym]
~expr))))
`(monads.core/do-result (~result nil) ~expr)
(reverse steps))))))

(defn- comprehend [f mvs]
(let [mv (first mvs)
rest-steps (reduce (fn [steps mv]
Expand Down Expand Up @@ -138,7 +112,8 @@
(writer-m-combine [c1 c2] (concat c1 c2)))

;; Monads describing multi-valued computations, i.e. computations
;; that can yield multiple values.
;; that can yield multiple values.

(extend-type clojure.lang.PersistentList$EmptyList
Monad
(do-result [_ v]
Expand Down Expand Up @@ -185,6 +160,27 @@
(clojure.core/seq ls) (lazy-concat (first l) (rest ls))
:else (list)))))


#_(:cljs
(extend-type Range
Monad
(do-result [_ v]
(list v))
(bind [mv f]
(mapcat f mv))

MonadZero
(zero [_]
[])
(plus-step [mv mvs]
(lazy-concat mv mvs))

MonadWriter
(writer-m-empty [_] (list))
(writer-m-add [c v] (conj c v))
(writer-m-combine [c1 c2] (concat c1 c2))))


(extend-type clojure.lang.LazySeq
Monad
(do-result [_ v]
Expand Down Expand Up @@ -281,20 +277,21 @@
[v]
(state-monad. v nil nil))

(deftype StateMonadFn [f]
clojure.lang.IFn
(invoke [_ s]
[s (f s)])
Monad
(do-result [_ v]
(state-monad. v nil nil))
(bind [mv f1]
(state-monad. nil mv f1)))

(defn update-state
"Return a state-monad value that replaces the current state by the
result of f applied to the current state and that returns the old state."
[f]
(reify
clojure.lang.IFn
(invoke [_ s]
[s (f s)])

Monad
(do-result [_ v]
(state-monad. v nil nil))
(bind [mv f]
(state-monad. nil mv f))))
(StateMonadFn. f))

(defn set-state
"Return a state-monad value that replaces the current state by s and
Expand Down
35 changes: 35 additions & 0 deletions src/clj/monads/macros.clj
@@ -0,0 +1,35 @@
; Copyright (c) Jim Duey. All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
; which can be found in the file epl-v10.html at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns monads.macros)

(defmacro do
"Monad comprehension. Takes the name of a monad (like vector, hash-set),
a vector of steps given as binding-form/monadic-expression pairs, and
a result value specified by expr. The monadic-expression terms can use
the binding variables of the previous steps.
If the monad contains a definition of m-zero, the step list can also
contain conditions of the form :when p, where the predicate p can
contain the binding variables from all previous steps.
A clause of the form :let [binding-form expr ...], where the bindings
are given as a vector as for the use in let, establishes additional
bindings that can be used in the following steps."
[result bindings expr]
(let [steps (partition 2 bindings)]
`(monads.core/bind (~result nil)
(fn [_#]
~(reduce (fn [expr [sym mv]]
(cond
(= :when sym) `(if ~mv
~expr
(monads.core/zero (~result nil)))
(= :let sym) `(let ~mv
~expr)
:else `(monads.core/bind ~mv (fn [~sym]
~expr))))
`(monads.core/do-result (~result nil) ~expr)
(reverse steps))))))

0 comments on commit c9a28a3

Please sign in to comment.