• Stars
    star
    145
  • Rank 254,087 (Top 6 %)
  • Language
    Clojure
  • License
    Eclipse Public Li...
  • Created about 9 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

NPM module for the the ClojureScript programming language

ClojureScript npm Package

Making the ClojureScript language usable from Node.js projects

var cljs = require("clojurescript")
cljs.compile("(fn [a] (str \"Hello \" a))")
// '(function (a){\nreturn [cljs.core.str("Hello "),cljs.core.str(a)].join(\'\');\n})'
var f = cljs.eval("(fn [a] (str \"Hello \" a))")
f("World")
// 'Hello World'

Status

Very early. Do not use for anything critical. Contributions welcome!

Installation

npm install -g clojurescript

Usage

Evaluating & Compiling

eval will return values that are directly usable from JavaScript. The whole standard library is available for use.

var f = cljs.eval("(fn [& args] (->> args (map inc) (remove odd?) into-array))")
f(1, 2, 3, 4, 5, 6, 7)
// [ 2, 4, 6, 8 ]

compile will return a string that can be evaluated using JavaScript's eval.

cljs.compile("(if (< 1 2 3 4 5) (.log js/console \"Less\"))")
'((((1 < 2)) && (((2 < 3)) && (((3 < 4)) && ((4 < 5)))))?console.log("Less"):null)'

Any code that makes use of namespaces of defs will need to run after lib/bootsrap.js has set up the ClojureScript environment. Contexts take care of this.

cljs.compile("(ns your.namespace) (defn f [x] (str \"your \" x))")
'goog.provide(\'your.namespace\');\ngoog.require(\'cljs.core\');\n(function (){\nyour.namespace.f = (function your$namespace$f(x){\nreturn [cljs.core.str("your "),cljs.core.str(x)].join(\'\');\n}); return (\nnew cljs.core.Var(function(){return your.namespace.f;},new cljs.core.Symbol("your.namespace","f","your.namespace/f",1343508863,null),cljs.core.PersistentHashMap.fromArrays([new cljs.core.Keyword(null,"ns","ns",441598760),new cljs.core.Keyword(null,"name","name",1843675177),new cljs.core.Keyword(null,"file","file",-1269645878),new cljs.core.Keyword(null,"end-column","end-column",1425389514),new cljs.core.Keyword(null,"column","column",2078222095),new cljs.core.Keyword(null,"line","line",212345235),new cljs.core.Keyword(null,"end-line","end-line",1837326455),new cljs.core.Keyword(null,"arglists","arglists",1661989754),new cljs.core.Keyword(null,"doc","doc",1913296891),new cljs.core.Keyword(null,"test","test",577538877)],[new cljs.core.Symbol(null,"your.namespace","your.namespace",-1885076140,null),new cljs.core.Symbol(null,"f","f",43394975,null),null,28,21,1,1,cljs.core.list(new cljs.core.PersistentVector(null, 1, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Symbol(null,"x","x",-555367584,null)], null)),null,(cljs.core.truth_(your.namespace.f)?your.namespace.f.cljs$lang$test:null)])));})()\n'

Contexts

ClojureScript has its own notion of namespaces implemented by the Google Closure JavaScript library. It sets up nested objects in the global environment to store your functions and data. This works well in the browser, but makes it difficult to work with Node which perfers to leave the global environment untouched.

To reconcile these two approaches, this package only ever evaluates ClojureScript code in an execution context. A context is an object that contains the global environment with the Google Closure-style namespaces that ClojureScript expects.

var ctx = cljs.newContext()
ctx.cljs.core.str
// { [Function]
//   ... }
ctx.cljs.core.map
// { [Function]
//   ... }

This way, ClojureScript gets the view of the world it wants and the global environment is not affected.

Code can be evaluated in any context. Namespaces and functions are all all accesible and usable from JavaScript.

cljs.eval("(ns foo)", ctx)
cljs.eval("(def name \"Ramsey\")", ctx)
ctx.foo.name
// 'Ramsey'
cljs.eval("(defn surround [a b] (str b a b))", ctx)
ctx.foo.surround("Hello", "~")
// '~Hello~'

Seperate contexts do not share anything. Even the standard library is reevaluated from scratch for each new context. Importantly, they maintain their own current namespace in *ns*.

cljs.eval("(str *ns*)", ctx)
// 'foo'
var ctx2 = cljs.newContext()
cljs.eval("(str *ns*)", ctx2)
// 'cljs.user'
cljs.eval("(ns foo)", ctx2)
cljs.eval("(def name \"Not Ramsey\")", ctx2)
ctx2.foo.name
// 'Not Ramsey'

When eval and compile are used without a second argument, a default context is used. It is exposed as context on the module object.

cljs.eval("(ns foo) (def a 1)")
cljs.context.foo.a
// 1

ClojureScript Require

:require and :use work in ns forms as expected. The search path aims to mirror the Node package resolution algorithm, i.e. .cljs files will be looked up in the node_modules folder if it exists, and then in the node_modules folder of the parent directory and so on to the top of the file system.

;; node_modules/helpers.cljs
(ns helpers)

(defn wrap [a min max]
  (cond (< a min) min
        (> a max) max
        :else    a))
var cljs = require("clojurescript")
cljs.eval("(ns main (:require helpers))")
cljs.eval("(helpers/wrap 90 0 10)")
// 10
cljs.eval("(helpers/wrap -90 0 10)")
// 0

Node Require

requireing "clojurescript/register" will register the .cljs extension with Node's require function and allow you to require cljs files in node. The module will export the contents of the last namespace in the file.

require("clojurescript/register")
var helpers = require("helpers")
helpers
// { wrap: [Function: helpers$wrap] }
helpers.wrap(90, 0, 100)
// 90
helpers.wrap(-90, 0, 100)
// 0

Command Line

Installing with -g will create put a cljs executable on your path.

Calling without arguments starts a REPL.

$ cljs
> (+ 1 2)
3
> (ns mappers)
nil
> (defn inc-all [col] (map inc col))
#'mappers/inc-all
> (ns cljs.user)
nil
> (mappers/inc-all (range 20))
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
> (ns cljs.user (:require helpers))
nil
> (helpers/wrap 0 0 0)
0
> (ns cljs.user (:require [helpers :refer [wrap]]))
nil
> (wrap 90 0 10)
10
> (wrap -90 0 10)
0

Passing a file as an argument will execute that file.

$ cat foo.cljs
(->> (range 20)
     (map inc)
     (filter even?)
     (map #(println (str "Hello " % " World")))
     dorun)
$ cljs foo.cljs
Hello 2 World
Hello 4 World
Hello 6 World
Hello 8 World
Hello 10 World
Hello 12 World
Hello 14 World
Hello 16 World
Hello 18 World
Hello 20 World

API

  • cljs.newContext([globals]) Creates a new ClojureScript execution context.
  • cljs.context The default execution context. Used by compile and eval by default.
  • cljs.compile(str[, ctx]) — Takes a string of ClojureScript code and returns a string of JavaScript code. Optionally takes a context to compile the code in.
  • cljs.eval(str[, ctx]) — Takes a string of ClojureScript code, evaluates it, and returns the resulting value. Optionally takes a context to evaluate the code in.

Building

lein cljsbuild once

to rebuild lib/bootstrap.js, where the ClojureScript compiler and standard library live. Requires Leiningen, Clojure, and Java to be installed and properly configured.

Legal

npm package © 2015-2016 Ramsey Nasser, provided under the Eclipse Public License 1.0

Uses code from elbow © 2015–2016 Mike Fikes and Contributors. Used under the Eclipse Public License version 1.0.

ClojureScript © Rich Hickey, provided under the Eclipse Public License 1.0

More Repositories

1

---

قلب: لغة برمجة
JavaScript
707
star
2

magic

Morgan And Grand Iron Clojure
Clojure
366
star
3

zajal

Experimental creative coding framework
JavaScript
160
star
4

arduino.tmbundle

The TextMate Arduino Bundle
Makefile
116
star
5

nostrand

Clojure on Mono
C#
69
star
6

ajeeb

Patterns for Playful Systems
JavaScript
69
star
7

mage

Symbolic MSIL bytecode generation for ClojureCLR
Clojure
63
star
8

symba

The Symbolic Assembler
Clojure
55
star
9

pltjs

A programming language design prototyping tool
JavaScript
44
star
10

god.js

New Gods Through Computer Science for Art Hack Day 2013
JavaScript
41
star
11

thixels

PICO8 inspired live coded thick pixel visual instrument
JavaScript
37
star
12

boards

Infinite whiteboards
JavaScript
28
star
13

rejoyce

A concatenative programming language inspired by Manfred von Thun's Joy
JavaScript
24
star
14

stopwork

Minimal HTML 5 Presentation Platform
CSS
23
star
15

rekindle

Hackable E-ink Tablets For Everyone
C
22
star
16

ajeeb-coroutines

Coroutines for the Ajeeb Game Engine
TypeScript
20
star
17

Socket

Sublime Socket REPLs
Python
18
star
18

Magic.Unity

Unity integration for the MAGIC compiler
C#
17
star
19

governingdynamics

The Governing Dynamics of Software - ITP Class on Language Design
13
star
20

sfpc-talk

Source code to the various slideshows used during my September 16, 2013 talk at the SFPC opening
JavaScript
11
star
21

malaf

Markdown + CSS = PDF
CSS
11
star
22

illness

HTML Mono MSIL Visualizer
C#
9
star
23

line

إعادة تخيل النص الرقمي
JavaScript
9
star
24

stop-emailing-me

just stop
JavaScript
9
star
25

ajeeb-ecs

Entity Component System for the Ajeeb Game EngineCoroutines
TypeScript
8
star
26

graffitidrone

Exactly what it sounds like
Ruby
7
star
27

twelve

Experimental Game Engine/Entity Component System
JavaScript
7
star
28

oddball

In-memory Content Addressable Store
JavaScript
6
star
29

Magic.Unity-Example

An example Magic.Unity project
Clojure
6
star
30

blenderhyrepl

Blender Hy REPL
Python
6
star
31

bctp

The Bytecode Transfer Protocol
JavaScript
5
star
32

teaching

Repository for my slides
HTML
5
star
33

dtplayfulsystems

Creative Coding class at Parsons Design + Tech
C
5
star
34

shapeserver

Harfbuzz shaping server
JavaScript
5
star
35

arz

a parser generator that makes nice trees
JavaScript
5
star
36

tools.analyzer.clr

CLR Specific Analysis Passes for clojure.tools.analyzer
Clojure
4
star
37

harfbuzz-js-demo

Correctly shaped 3D text in Three.js via HarfBuzz and OpenType
JavaScript
4
star
38

everyunicode

Twittering every graphical character in the Unicode 6.2 Standard. Task will complete in 2076.
Ruby
3
star
39

rdclcmps

Radical Computer Science at SFPC, Abbreviated
3
star
40

Magic.Runtime

C#
3
star
41

occupied.land

JavaScript
2
star
42

sponge

The Slowest Computer On Earth
HTML
2
star
43

hiccup-magic

A port of the hiccup library to Clojure on the CLR (the MAGIC compiler)
Clojure
2
star
44

gozer

Social media stream aggregation
JavaScript
2
star
45

cathoristic-logic

F#/Clojure implementation of Cathoristic Logic
F#
2
star
46

nopenotarabic

An Archive of Things That Are Not Arabic
HTML
2
star
47

-

بونج: اللعبة الكلاسيكية مبرمجة بلغة البرمجة "قلب" لمتصفح الويب
JavaScript
2
star
48

zajal-book

The Zajal Programming Book
2
star
49

coding-in-depth

Playable Fashion Coding in Depth Lesson Plan
HTML
2
star
50

tetroid

Arduino Tetris clone
Java
2
star
51

sfpc-fall14

Radical Computer Science at the School For Poetic Computation Fall 2014
1
star
52

playablefashion

C++
1
star
53

electron-p5

P5 in an Electron App
JavaScript
1
star
54

syntax-canvas

Language design experimentation tool
JavaScript
1
star
55

guillotine

Painless code execution framework
1
star
56

buzzkill

Flies are so annoying
JavaScript
1
star
57

terminalstate

maybe got carried away with this
HTML
1
star
58

npwd

Command-line password management for your various accounts.
JavaScript
1
star
59

resume

1
star
60

fsbook

an f# program that is also a book?
JavaScript
1
star
61

roll-a-ball

Adaptation of mlakewood's Roll_a_Ball
Clojure
1
star
62

hiramsey

Kaho's C64 Code
Visual Basic
1
star
63

magic-project

Top level build orchestration repository for MAGIC and all related technologies
1
star