Skip to content
/ sanity Public

Fixes a number of problems with Clojure semantics and syntax and fills in some missing functionality

License

Notifications You must be signed in to change notification settings

abarbu/sanity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 

Repository files navigation

sanity

Available from clojars:

Clojars Project

Use with:

(use '[sanity core improvements reader])

Sanity fixes some issues with Clojure's semantics and syntax, fills in some missing parts of the standard API, fixes ` by adding a sane version named #`, and provides some functions which are more compatible with their better thought out Scheme counterparts.

It provides combine-namespaces which takes a name along with one or more namespaces, unions those namespaces and exposes them all under the given name. Particularly useful with incanter and loom:

(combine-namespaces i incanter.core incanter.io incanter.optimize incanter.stats)
(combine-namespaces l loom.graph loom.alg loom.gen loom.attr loom.label loom.io)

It adds syntax for #`. This is a quasiquote and works just like ` except that it does not qualify symbols with the current namespace. This default behaviour leads to a lot of strange and broken code. Try out `a vs #`a (you would need to do `~'a to get this (sane) behaviour otherwise). #` also handles #`(~@()) correctly and returns '() instead of '(nil).

Individual functions are mostly documented, but this project as a whole does not yet have documentation.

If you use Emacs and clojure-mode with this library this code will make syntax highlighting quite a bit better (the last bit about the percent sign is just personal taste and doesn't have anything to do with sanity):

(put-clojure-indent 'define 'defun)
(put-clojure-indent 'cases 1)
(put-clojure-indent 'conds 0)
(put-clojure-indent 'unless 1)
(put-clojure-indent 'lambda 'defun)
(put 'define 'clojure-doc-string-elt 2)
(font-lock-add-keywords 'clojure-mode
                        `((,(concat
                             "(\\(?:clojure.core/\\)?"
                             (regexp-opt
                              '("cases" "conds" "lambda") t)
                             "\\>")
                           1 font-lock-keyword-face)))
(font-lock-add-keywords 'clojure-mode
                        `((,(concat "\\<"
                                    (regexp-opt '("%") t)
                                    "\\>")
                           0 font-lock-builtin-face)))

Other broken behavior to hopefully be patched one day:

  • (seq '()) returns nil instead of failing. An example of where this misguided propensity to return nil everywhere leads to trouble, consider that (cdr (cdr (seq [1 2]))) and (seq []) are paradoxically not equal. seq should return the empty element of the collection, not nil. This ripples out and causes many other bugs, including some in the clojure compiler. An example is where
`(~@(map (fn [x] (+ x 1)) '(1 2 3)))

returns, as expected (2 3 4) but as the list becomes empty we would expect () whereas instead you get something pretty broken (nil) because of this sloppy seq behavior.

  • :keyword on a map without the given key returns nil instead of failing. This hides bugs and causes errors to appear far away from their real source.
  • (first '()) returns nil instead of failing.
  • The scoping of def and defn is broken yet for some reason they're still allowed outside the toplevel.
  • map mangles the type of object you pass in and always returns a lazy sequence. This leads to a lot of difficult to read code that has to rebuild the original object constantly, not to mention bugs where strict objects become lazy at unexpected times. map should do what it's meant to do, preserve the type of the object. map-lazy can have the current behavior.

License

Copyright © 2014 Andrei Barbu

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

Yourkit supports this open source project through their Java profiler.

About

Fixes a number of problems with Clojure semantics and syntax and fills in some missing functionality

Resources

License

Stars

Watchers

Forks

Packages

No packages published