David Nolen
ClojureScript is a new compiler for Clojure that targets JavaScriptimmutability@youtube
Rich Hickey
Clojure rocks, JavaScript reachessimple made easy@infoq
(defcomponent app [{:keys [title connected qr question answers]} _]
(render [_]
(html
[:div.wrapper
[:h1 title]
(om/build question-widget question)
(if slide?
[:div
[:p (str "Connected: " connected)]
(om/build-all stat-widget answers)
(om/build qr-widget qr)]
(om/build-all answer-widget answers))]
)))
'1' == 1 // true
'true' == true // false
cljs.user=> (= 1 "1") ;; false
cljs.user=> (+ 1 "1")
WARNING: cljs.core/+, all arguments must be numbers, got [number string] instead. at line 1 cljs repl
"11"
[] + []
> ""
[] + {}
> "[object Object]"
{} + {}
> NaN
JS forces you to be async
even on server
keystonejs/keystone (4.5K stars, 770 forks) on Mar 23, 2015
exports.signin = function(lookup, req, res, onSuccess, onFail) {
if (!lookup) {
return onFail(new Error('session.signin requires a User ID or Object as the first argument'));
}
var User = keystone.list(keystone.get('user model'));
if ('string' === typeof lookup.email && 'string' === typeof lookup.password) {
// match email address and password
User.model.findOne({ email: lookup.email }).exec(function(err, user) {
if (user) {
user._.password.compare(lookup.password, function(err, isMatch) {
if (!err && isMatch) {
exports.signinWithUser(user, req, res, onSuccess);
}
else {
onFail(err);
}
});
} else {
onFail(err);
}
});
} else {
lookup = '' + lookup;
// match the userId, with optional password check
var userId = (lookup.indexOf(':') > 0) ? lookup.substr(0, lookup.indexOf(':')) : lookup,
passwordCheck = (lookup.indexOf(':') > 0) ? lookup.substr(lookup.indexOf(':') + 1) : false;
User.model.findById(userId).exec(function(err, user) {
if (user && (!passwordCheck || scmp(passwordCheck, hash(user.password)))) {
exports.signinWithUser(user, req, res, onSuccess);
} else {
onFail(err);
}
});
}
};
ES6 | ClojureScript |
---|---|
modules | namespaces |
var [one, ...rest] = foo;
var {foo, bar: baz} = qux;
var {foo, bar: baz} = qux;
[1, 2].map(x => x * 2)
|
[[one & rest] foo]
[{:keys [foo] baz :bar} qux]
[{:keys [foo] baz :bar} qux]
(map #(* % 2) [1, 2])
|
var, let, const | let |
iterator | map (lazy), transducers (@youtube) |
generator | lazy-seq |
type annotations | core.typed |
Map, Object | {}, defrecord |
JS | ClojureScript |
---|---|
this
var that = this |
explicit args passing, partial
(this-as that) |
uglifyjs, yui-compressor | Google Closure Compiler |
JSHint, JSLint | cljs.analyzer (works out-of-the-box)
undeclared Var .. at line, file
google closure compiler |
macros? ;( | (defmacro) |
stdlib? | :keyword , #{} , UUID
transit format Google Closure Library |
... |
:advanced dead code elimination
|
grunt/gulp/broccoli | lein-cljsbuild |
(newbie-friendly)
ficus.io clone
https://github.com/razum2um/jsmeetupbrnlein new app
[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.170"]
[figwheel-sidecar "0.5.0-SNAPSHOT"]
[org.omcljs/om "0.8.8"]
[prismatic/om-tools "0.4.0"]
[sablono "0.3.6"]
git checkout step1
git checkout step2
add-watch
git checkout step3
(p jsconf.state/state)
git checkout step4
git checkout step5