Git Product home page Git Product logo

c2's Introduction

  _____   ___  
 / ____| |__ \ 
| |         ) |
| |        / / 
| |____   / /_ 
 \_____| |____|

Declarative visualization in Clojure(Script)

C2 is a D3-inspired data visualization library for Clojure and ClojureScript. As with D3, the core idea is to build declarative mappings from your data to HTML or SVG markup. This lets you leverage CSS and the existing web ecosystem to construct bespoke data visualizations.

C2 encourages a "data-driven" approach to application design. Compose pure functions to map your data to native Clojure vectors and maps that represent the DOM, and then let the library handle rendering into actual elements (on the clientside) or a string of markup (on the serverside).

In a browser, C2 handles DOM updates as well, so it will add/remove nodes and set attributes/styles when your data changes so you don't have to deal with the incidental state and complexity of low-level, imperative manipulation. To see what this "data-driven" approach looks like in a simple application, see this C2-powered todo list.

See also:

Google group

Example visualizations

Annotated source

Deprecated

C2 was first released in Jan 2012 and in May 2012 its DOM-manipulation engine was factored into a separate library, Singult. Singult's core idea, providing an data-oriented abstraction for DOM-manipulation, has since been adopted by many other projects---most notably React.js (released May 2013). These libraries provide a superset of C2/Singult's capabilities: Everything you can make in C2/Singult you can also make using React.js. React.js is likely faster (using "virtual DOM diffs" rather than direct DOM walking) and provides API hooks into low-level details via lifecycle methods.

So, rather than use C2 I suggest you look into:

  • React.js: Similar ideas as C2, but supported by Facebook and the trendy JavaScript masses.
  • Rum: ClojureScript bindings to React.js. This is what I use now instead of C2.
  • Elm: A compile-to-JS language that includes a virtual DOM system, typed pattern matching, and the most humane compiler messages I've ever seen.

In terms of data visualization specifically, I suggest:

  • Show me the numbers: A great coverage of the fundamentals (hint: use a lot of bar and line charts).
  • Drawing points, rectangles, and lines using SVG or HTML flexbox.
  • Sticking to simple animations using CSS transitions or (even better) come up with a design that doesn't rely on animation/interaction.

Play around

See vrepl/README.markdown for instructions on using the built-in examples+interactive-development server (Clojure-only). For a full ClojureScript application example, check out the C2-powered todo list.

There's also a two minute screencast, and a longer overview/tutorial video on the library.

To use from Clojure/ClojureScript add this to your project.clj:

[com.keminglabs/c2 "0.2.3"]

Leiningen 2.0.0 is required. For ClojureScript development, check out lein-cljsbuild.

Differences from D3

Language

D3 is written in JavaScript and C2 is written in Clojure. Clojure is a richer language than JavaScript, with features like destructuring, lazy evaluation, namespaces, and macros, which JavaScript does not provide. Since Clojure runs on the Java Virtual Machine, it's possible to work with much larger data sets than JavaScript can handle, directly access datastores, and perform advanced computations (in parallel).

C2 also leverages ClojureScript, a Clojure-to-JavaScript compiler, so you can take advantage of the expressiveness of Clojure while maintaining the reach of JavaScript. The ClojureScript compiler is built on Google's Closure compiler, and in many cases your visualizations may compile to JavaScript with a smaller file size than the D3.js library itself!

(If you want a ClojureScript library that actually leverages D3, take a look at the awesomely polyfilled Strokes library.)

View is data

Rather than think of DOM nodes as foreign objects to be manipulated with methods like addChild or setClass, in C2 you build the DOM you want using standard Clojure data structures like vectors and maps. That is, you just specify what you want on the DOM by composing pure functions. Since all you're doing is data transformation, you don't actually need a DOM; that means you can

  • test your code without a browser
  • render all of your visualizations on the server and send down pure markup
  • render visualizations with computationally-heavy mappings (e.g., detailed map projections or Hilbert curves) on background web workers

With standard data structures, you're also not limited (as in D3) to mapping each datum to a single DOM node. For instance, you could build a bar chart's title, bars, and their labels all at the same time:

(bind! "#barchart"
       [:div#barchart
        [:h2 "Rad barchart!"]
        [:div.bars
         (unify {"A" 1, "B" 2, "C" 4, "D" 3}
                (fn [[label val]]
                  [:div.bar
                   [:div.bar-fill {:style {:width (x-scale val)}}]
                   [:span.label label]]))]])

whereas in D3 (because of the chained syntax) you'd have to build the bars and labels in separate passes (or manually, using each).

Sensible state

All of Clojure's data structures are immutable; if you want to model mutable state, explicit semantics are required. Both Clojure and ClojureScript have the atom reference type, which just "points" to an immutable value. If you want to "change" an atom, you point it to another immutable value. To get at the value, you have to explicitly dereference it using the @ syntax (e.g., @a ;;=> "stuff pointed at by a")

C2 takes advantage of this to automatically setup bindings. In the previous example, if the bar chart's data were dereferenced from an atom rather than being inlined ({"A" 1, "B" 2, "C" 4, "D" 3}), then the bind! macro would automatically watch that atom and re-render the view when the atom pointed to a new value. (Watchers are added to every atom that is dereferenced within bind!.)

No animation

Unlike D3, C2 does not have an animation system, although you can use CSS transitions to perform animations.

Development

The C2 library itself is a grab bag of data visualization helpers (scales, map projections, &c.) and some wrappers around the Google Closure library's DOM-manipulation and event handling facilities. The core DOM-manipulation and binding functionality is provided by two other libraries:

  • Singult renders hiccup vectors into DOM-elements and merges into existing DOM trees. Singult is written in CoffeeScript (for speed) and does not depend on ClojureScript at all, so you can use it from plain JavaScript if you like.
  • Reflex provides a macro that "captures" dereferenced atoms, which is what powers C2's bind! macro. Reflex also provides some macros to help coordinate (e.g., automatically add/remove watchers on multiple atoms).

Most of C2 is written in platform-agnostic Clojure using cljx, a Clojure/ClojureScript code generator. If you edit a .cljx file, run

lein cljx

to regenerate the corresponding .clj and .cljs files.

Unit tests are written in Midje; run with:

lein midje

For ClojureScript-specific integration testing, you can run the highly advanced, PhantomJS-powered "list-of-assertions" testing framework:

lein cljsbuild test

or, if you're too cool to go headless:

lein cljsbuild once

c2's People

Contributors

aperiodic avatar chapmanb avatar jblomo avatar lgastako avatar lynaghk avatar nblumoe avatar timcharper avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

c2's Issues

Protocol for clj->js conversions.

Currently this proxies to the clj->js in Singult, but that needs to be optimized for speed.
Bring back a separate clj->js fn to C2, and implement using Protocols so that users can define lossy conversions from Clojure datastructures to JavaScript objects themselves.

C2 projects cannot compile with ClojureScript 2138

Hey Kevin.

I was integrating C2 into a work project and discovered that things don't seem to work with more recent versions of ClojureScript.

For example, if you upgrade the hello-bars demo then clean target/ and public/out/ you will find the project can no longer cljsbuild.

diff --git a/hello-bars/project.clj b/hello-bars/project.clj
index 90c8b76..a982bc5 100644
--- a/hello-bars/project.clj
+++ b/hello-bars/project.clj
@@ -1,9 +1,8 @@
 (defproject hello-bars "0.0.1-SNAPSHOT"
   :description "hello-bars: c2 at its simplest"
-  :dependencies [[org.clojure/clojure "1.4.0"]
+  :dependencies [[org.clojure/clojure "1.5.1"]
+                 [org.clojure/clojurescript "0.0-2138"]

Result:

Compiling "public/out/hello-bars.js" from "src/cljs"...
Compiling "public/out/hello-bars.js" failed:
clojure.lang.ExceptionInfo: failed compiling file:src/cljs/hello_bars/core.cljs
                 core.clj:4327 clojure.core/ex-info
             compiler.clj:1005 cljs.compiler/compile-file
             compiler.clj:1057 cljs.compiler/compile-root
# ...
Caused by: clojure.lang.ExceptionInfo: clojure.lang.Cons cannot be cast to clojure.lang.Named at line 109 file:/Users/ryan/.m2/repository/com/keminglabs/c2/0.2.1/c2-0.2.1.jar!/c2/dom.cljs
                 core.clj:4327 clojure.core/ex-info
              analyzer.clj:265 cljs.analyzer/error
             analyzer.clj:1414 cljs.analyzer/analyze-seq
             analyzer.clj:1505 cljs.analyzer/analyze[fn]
...

(Since there doesn't seem to be a 0.2.1 tag, I bumped to 0.2.2 and the line in question is dom.cljs#112)

It seems to be something to do with core.match. Can you make anything of this?

Unexpected null in singult when trying to bind!

When I try to bind! anything at all to a div in my page, the page trips over an unexpectedly null element in singult.coffee.merge. The specific thing I'm trying is (bind! "#content" [:p "Meaningful content."]). If you want, you can also look at the repo for the (currently toy) project.

This looks like a bug in singult, but I'm opening an issue c2 because that's the dependency I'm pulling in.

core.matrix support?

The following project is providing an API for multi-dimensional data / arrays / matrices in Clojure in a way that will hopefully be able to unify different matrix implementations in Clojure with a common abstraction:

It would be great if c2 could at some point gain the ability to visualise core.matrix data. In particular, this would make it easy for c2 to visualise data regardless of the underlying matrix / data format.

Note that there are also plans to port Incanter to use core.matrix, so there may also be some synergies there.

Event.on for multiple elements

Just started working with this library and seems pretty awesome thus far!

One question right now:

I have a list of albums on a page. Each album has a button beside it to add it:

ul.albums
    li
      button.add
    li
      button.add

However. When I do a function like:

(event/on-raw ".add" :click
  (fn [e]
    (swap! !playlist conj {:title "aotueh"})))

It only gets called for when I click add for the first album in the list. How can I make it work for all of them?

DOM namespace inference

Server-side hiccup doesn't care about namespaces (e.g., [:svg:g]) but in ClojureScript you need 'em for the correct DOM nodes to be generated.

This should be resolved so that pure Clojure SVG visualizations can be used in either place verbatim.

Hiccup-style vectors only support 2 classes

The hiccup style vectors only support two classes.

Doing the following in clojurescript

(bind! "#my-id"
  [:div.a.b.c "hello"])

will create

<div class="a b.c">hello</div>

This is using the 0.2.0 version from clojars.

seqable NodeLists

(copied from email)

Seems like C2's (-seq) hack for NodeLists no longer works with
advanced compilation, is that consistent with your observations?

Cheers,

Stephen

cljs compilation errors

Hi,

I ran into errors using c2 with recent clojurescript versions. For example if I make the following patch to the c2-demos/hello-bars project.clj:

 (defproject hello-bars "0.0.1-SNAPSHOT"
   :description "hello-bars: c2 at its simplest"
-  :dependencies [[org.clojure/clojure "1.4.0"]
-                 [com.keminglabs/c2 "0.2.1"]]
+  :dependencies [[org.clojure/clojure "1.5.1"]
+                 [org.clojure/clojurescript "0.0-2227"]
+                 [com.keminglabs/c2 "0.2.3"]]
   :min-lein-version "2.0.0"
   :source-paths ["src/clj"]

-  :plugins [[lein-cljsbuild "0.2.7"]]
+  :plugins [[lein-cljsbuild "1.0.3"]]

Then I get the following from lein cljsbuild:

Compiling "public/out/hello-bars.js" from ["src/cljs"]...
WARNING: Referred macro reflex.macros/capture-derefed does not exist at line 1 file:/home/felix/.m2/repository/com/keminglabs/reflex/0.1.1/reflex-0.1.1.jar!/reflex/core.cljs
WARNING: No such namespace: singult.coffee at line 1 file:/home/felix/.m2/repository/com/keminglabs/singult/0.1.6/singult-0.1.6.jar!/singult/core.cljs
WARNING: No such namespace: singult.coffee at line 1 /home/felix/devel/c2-demos/hello-bars/target/cljsbuild-compiler-0/singult/core.cljs
WARNING: Referred macro reflex.macros/capture-derefed does not exist at line 1 /home/felix/devel/c2-demos/hello-bars/target/cljsbuild-compiler-0/reflex/core.cljs

And fatal runtime errors:

Uncaught Error: goog.require could not find: singult.coffee 

I'm not sure how to go about investigating this.

Best
Felix

Clamp scales

Scales should have an option to clamp inputs from outside of their domain.

Compilation error in C2 "0.2.3-SNAPSHOT"

Hi Kevin,

I tried run lein cljsbuild with c2 version "0.2.3-SNAPSHOT". It gives the following error:

WARNING: Use of undeclared Var c2.dom/e__3480__auto__ at line 112 file:/***/.m2/repository/com/keminglabs/c2/0.2.3-SNAPSHOT/c2-0.2.3-SNAPSHOT.jar!/c2/dom.cljs
Compiling "resources/public/js/binding_issue.js" failed.
clojure.lang.ExceptionInfo: Assert failed: Can't qualify symbol in catch
(not (namespace name)) at line 112 file:/***/.m2/repository/com/keminglabs/c2/0.2.3-SNAPSHOT/c2-0.2.3-SNAPSHOT.jar!/c2/dom.cljs 

It seems that the error is caused by the dependency

[org.clojure/core.match "0.2.0-alpha12" :exclusions [org.clojure/core.logic]]

in project.clj. Reverting to

[org.clojure/core.match "0.2.0-alpha11" :exclusions [org.clojure/clojure org.clojure/core.logic]]

seems to fix the error.

Bye,
Federico

hello-bars demo has doctype issues?

Reported via an email:

I would like to point out that I've just run the 'c2-demos/hello-bars' you published on your github page and the bar visualization (sizing) fails if you add a doctype declaration

<!DOCTYPE html> 

or

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

to the html file 'hello-bars/public/index.html'.

CLJS unify should merge seqs into body

In CLJ hiccup seqs are "exploded" into the containing body:

(html [:ul (map (fn [d] [:li d])] (range 3))])

is treated the same as

(html [:ul
       [:li 1]
       [:li 2]
       [:li 3]])

C2 clientside should do likewise, so people don't have to expand manually using (into).

Test commands in README.markdown don't work

[tw-mbp13-nmahendran Desktop]$ lein version
Leiningen 1.7.1 on Java 1.6.0_31 Java HotSpot(TM) 64-Bit Server VM

This is the latest version provided by Homebrew.

[tw-mbp13-nmahendran Desktop]$ git clone [email protected]:nybbles/c2.git
Cloning into c2...
remote: Counting objects: 951, done.
remote: Compressing objects: 100% (500/500), done.
remote: Total 951 (delta 429), reused 835 (delta 314)
Receiving objects: 100% (951/951), 130.36 KiB, done.
Resolving deltas: 100% (429/429), done.

[tw-mbp13-nmahendran Desktop]$ cd c2/
[tw-mbp13-nmahendran c2 (master)]$ lein deps
Copying 8 files to /Users/nimalan/Desktop/c2/.lein-plugins
Copying 4 files to /Users/nimalan/Desktop/c2/lib

lein midje --autotest

lein midje --autotest
[tw-mbp13-nmahendran c2 (master)]$ lein midje --autotest
That's not a task. Use "lein help" to list all tasks.

lein cljsbuild test

[tw-mbp13-nmahendran c2 (master)]$ lein cljsbuild test
Compiling ClojureScript.
(Compiling out/test/integration.js from test/integration/cljs...)
( Failed!)
java.io.FileNotFoundException: Could not locate c2/util__init.class or c2/util.clj on classpath: 
                  RT.java:430 clojure.lang.RT.load
                  RT.java:398 clojure.lang.RT.load
                core.clj:5386 clojure.core/load[fn]
                core.clj:5385 clojure.core/load
              RestFn.java:408 clojure.lang.RestFn.invoke
                core.clj:5200 clojure.core/load-one
                core.clj:5237 clojure.core/load-lib
              RestFn.java:142 clojure.lang.RestFn.applyTo
                 core.clj:602 clojure.core/apply
                core.clj:5271 clojure.core/load-libs
              RestFn.java:137 clojure.lang.RestFn.applyTo
                 core.clj:602 clojure.core/apply
                core.clj:5352 clojure.core/require
              RestFn.java:408 clojure.lang.RestFn.invoke
             compiler.clj:874 cljs.compiler/eval1145[fn]
             MultiFn.java:177 clojure.lang.MultiFn.invoke
            compiler.clj:1076 cljs.compiler/analyze-seq
            compiler.clj:1129 cljs.compiler/analyze
            compiler.clj:1122 cljs.compiler/analyze
            compiler.clj:1189 cljs.compiler/compile-file*
            compiler.clj:1227 cljs.compiler/compile-file
            compiler.clj:1288 cljs.compiler/compile-root
              closure.clj:367 cljs.closure/compile-dir
              closure.clj:399 cljs.closure/eval1742[fn]
              closure.clj:266 cljs.closure/eval1670[fn]
              closure.clj:413 cljs.closure/eval1729[fn]
              closure.clj:266 cljs.closure/eval1670[fn]
              closure.clj:872 cljs.closure/build
              compiler.clj:52 cljsbuild.compiler/compile-cljs[fn]
              compiler.clj:51 cljsbuild.compiler/compile-cljs
              compiler.clj:70 cljsbuild.compiler/run-compiler
             NO_SOURCE_FILE:1 user/eval2146[fn]
                  util.clj:31 cljsbuild.util/in-threads[fn]
                core.clj:1817 clojure.core/binding-conveyor-fn[fn]
                  AFn.java:18 clojure.lang.AFn.call
          FutureTask.java:303 java.util.concurrent.FutureTask$Sync.innerRun
          FutureTask.java:138 java.util.concurrent.FutureTask.run
  ThreadPoolExecutor.java:886 java.util.concurrent.ThreadPoolExecutor$Worker.runTask
  ThreadPoolExecutor.java:908 java.util.concurrent.ThreadPoolExecutor$Worker.run
              Thread.java:680 java.lang.Thread.run
Running all ClojureScript tests.
Exception in thread "main" java.lang.RuntimeException: java.io.IOException: Cannot run program "phantomjs": error=2, No such file or directory
    at clojure.lang.Util.runtimeException(Util.java:165)
    at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:35)
    at cljsbuild.util$process_start.invoke(util.clj:70)
    at cljsbuild.util$sh.invoke(util.clj:80)
    at cljsbuild.test$run_tests$iter__180__184$fn__185.invoke(test.clj:11)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.RT.seq(RT.java:466)
    at clojure.core$seq.invoke(core.clj:133)
    at clojure.core$dorun.invoke(core.clj:2723)
    at clojure.core$doall.invoke(core.clj:2739)
    at cljsbuild.test$run_tests.invoke(test.clj:10)
    at user$eval221.invoke(NO_SOURCE_FILE:1)
    at clojure.lang.Compiler.eval(Compiler.java:6465)
    at clojure.lang.Compiler.eval(Compiler.java:6455)
    at clojure.lang.Compiler.eval(Compiler.java:6431)
    at clojure.core$eval.invoke(core.clj:2795)
    at clojure.main$eval_opt.invoke(main.clj:296)
    at clojure.main$initialize.invoke(main.clj:315)
    at clojure.main$null_opt.invoke(main.clj:348)
    at clojure.main$main.doInvoke(main.clj:426)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:405)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.Var.applyTo(Var.java:518)
    at clojure.main.main(main.java:37)
Caused by: java.io.IOException: Cannot run program "phantomjs": error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:460)
    at java.lang.Runtime.exec(Runtime.java:593)
    at java.lang.Runtime.exec(Runtime.java:466)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:92)
    at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:30)
    ... 24 more
Caused by: java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)
    at java.lang.ProcessImpl.start(ProcessImpl.java:91)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:453)
    ... 32 more
[tw-mbp13-nmahendran c2 (master)]$ 

lein cljsbuild once

[tw-mbp13-nmahendran c2 (master)]$ lein cljsbuild once
Compiling ClojureScript.
(Compiling out/test/integration.js from test/integration/cljs...)
( Failed!)
java.io.FileNotFoundException: Could not locate c2/util__init.class or c2/util.clj on classpath: 
                  RT.java:430 clojure.lang.RT.load
                  RT.java:398 clojure.lang.RT.load
                core.clj:5386 clojure.core/load[fn]
                core.clj:5385 clojure.core/load
              RestFn.java:408 clojure.lang.RestFn.invoke
                core.clj:5200 clojure.core/load-one
                core.clj:5237 clojure.core/load-lib
              RestFn.java:142 clojure.lang.RestFn.applyTo
                 core.clj:602 clojure.core/apply
                core.clj:5271 clojure.core/load-libs
              RestFn.java:137 clojure.lang.RestFn.applyTo
                 core.clj:602 clojure.core/apply
                core.clj:5352 clojure.core/require
              RestFn.java:408 clojure.lang.RestFn.invoke
             compiler.clj:874 cljs.compiler/eval1145[fn]
             MultiFn.java:177 clojure.lang.MultiFn.invoke
            compiler.clj:1076 cljs.compiler/analyze-seq
            compiler.clj:1129 cljs.compiler/analyze
            compiler.clj:1122 cljs.compiler/analyze
            compiler.clj:1189 cljs.compiler/compile-file*
            compiler.clj:1227 cljs.compiler/compile-file
            compiler.clj:1288 cljs.compiler/compile-root
              closure.clj:367 cljs.closure/compile-dir
              closure.clj:399 cljs.closure/eval1742[fn]
              closure.clj:266 cljs.closure/eval1670[fn]
              closure.clj:413 cljs.closure/eval1729[fn]
              closure.clj:266 cljs.closure/eval1670[fn]
              closure.clj:872 cljs.closure/build
              compiler.clj:52 cljsbuild.compiler/compile-cljs[fn]
              compiler.clj:51 cljsbuild.compiler/compile-cljs
              compiler.clj:70 cljsbuild.compiler/run-compiler
             NO_SOURCE_FILE:1 user/eval2146[fn]
                  util.clj:31 cljsbuild.util/in-threads[fn]
                core.clj:1817 clojure.core/binding-conveyor-fn[fn]
                  AFn.java:18 clojure.lang.AFn.call
          FutureTask.java:303 java.util.concurrent.FutureTask$Sync.innerRun
          FutureTask.java:138 java.util.concurrent.FutureTask.run
  ThreadPoolExecutor.java:886 java.util.concurrent.ThreadPoolExecutor$Worker.runTask
  ThreadPoolExecutor.java:908 java.util.concurrent.ThreadPoolExecutor$Worker.run
              Thread.java:680 java.lang.Thread.run
[tw-mbp13-nmahendran c2 (master)]$

No license to use

Could you state a license by which the code can be used?

Thanks,

Hen

CLJX = Clojure / ClojureScript code sharing

The majority of C2 source is being ported to .cljx files that can be statically transformed into the appropriate .clj and .cljs files.
Consumers using the library as a JAR don't need to know about any of this, but it's central for development.
See emezeske/lein-cljsbuild#49 for more background, and leave a comment here if you think this is a great/terrible idea.

endless loop calling (c2.ticks/search [same-number same-number])

The following call results in an endless loop (clojurescript):
(c2.ticks/search [same-number same-number]) e.g. (c2.ticks/search [0 0])

So testing for (= d-min d-max) and returning an empty default seems to be a reasonable thing to do.

Version: [com.keminglabs/c2 "0.2.2"]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.