Skip to content

Instantly share code, notes, and snippets.

View mfikes's full-sized avatar

Mike Fikes mfikes

View GitHub Profile

Loading :advanced Code into an Unmodified WROVER running Espruino

You can load ClojureScript :advanced code directly into an ESP32 WROVER running Espruino for execution upon boot, by creating a binary and flashing it to the JavaScript "boot ROM" area. This has the same effect as when loading code via the Espruino Web IDE, in the "Direct to Flash (execute code at boot)" mode, but flashing is much quicker and more reliable.

Note: To do this, you'll need an ESP32 WROVER with SPI PSRAM, as opposed to just a WROOM, as the ClojureScript in this example uses more RAM than is available in the WROOM.

Create :advanced Code

Here is a small program that uses enough to pull in data structures, etc, leading to nearly 100 KiB:

function $cljs$core$Reduced$$($val$jscomp$52$$) {
this.$val$ = $val$jscomp$52$$;
this.$cljs$lang$protocol_mask$partition0$$ = 32768;
this.$cljs$lang$protocol_mask$partition1$$ = 0;
}
$cljs$core$Reduced$$.prototype.$cljs$core$IDeref$_deref$arity$1$ = function() {
return this.$val$;
};
@mfikes
mfikes / yes.md
Created November 23, 2019 21:46
Running ClojureScript on Espruino

With src/foo/core.cljs:

(ns foo.core)

(defn calculate []
 (let [xform (comp (map inc) (filter odd?) (take 123))]
   (transduce xform + (iterate inc 0))))

(js/print (calculate))
@mfikes
mfikes / optimize.md
Last active September 12, 2019 12:03

Note we are using :static-fns, and also note we are using master to get inferrence for implements? CLJS-3140.

At its core is an (arguably internal) optimization surrounding the notion of ^not-native, which is also effectively enabled if a value is tagged with a protocol type.

Note that compiler enables inference for implements? but not satisfies? because the later would break things.

And, if a user type hints with a protocol type, while the user code is arguably correct, it would provoke the same bug surrounding satisfies?.

$ clj -Sdeps '{:deps {org.clojure/clojurescript {:git/url "https://github.com/clojure/clojurescript" :sha "b38ded99dc0967a48824d55ea644bee86b4eae5b"}}}' -m cljs.main -co '{:static-fns true}' -re node -r
@mfikes
mfikes / gist:3a160a1504debd31e5771736256ca022
Last active September 8, 2019 21:33
Serializing CLJS Bean instances via transit preserving meta
$ clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.520"} com.cognitect/transit-cljs {:mvn/version "0.8.256"} com.cognitect/transit-js {:mvn/version "0.8.861"} cljs-bean {:mvn/version "1.4.0"}}}' -m cljs.main -re node -r
ClojureScript 1.10.520
(require '[cognitect.transit :as t]
         '[cljs-bean.core :refer [->clj]]
         '[cljs-bean.transit])
nil
cljs.user=> (defn roundtrip [x]
              (let [w (t/writer :json
                        {:handlers (cljs-bean.transit/writer-handlers)
cljs.user=> (set! *print-fn-bodies* true)
true
cljs.user=> (defrecord Foo [x])
cljs.user/Foo
cljs.user=> (defn bar [^cljs.user/Foo foo] #(:y foo))
#'cljs.user/bar
cljs.user=> (bar (assoc (->Foo 1) :y 3))
#object[Function "function (){
return new cljs.core.Keyword(null,"y","y",-1757859776).cljs$core$IFn$_invoke$arity$1(foo);
}"]
$ plk -Sdeps '{:deps {cljs-bean {:mvn/version "0.2.0"}}}'
ClojureScript 1.10.520
cljs.user=> (simple-benchmark [o #js {:a 1 :b 2 :c 3}]
#_=> (let [{:keys [a b c]} (js->clj o :keywordize-keys true)]
#_=> (+ a b c))
#_=> 1e6)
[o #object[cljs.tagged-literals.JSValue]], (let [{:keys [a b c]} (js->clj o :keywordize-keys true)] (+ a b c)), 1000000 runs, 3077 msecs
nil
cljs.user=> (require '[cljs-bean.core :refer [bean]])
nil
@mfikes
mfikes / perf.md
Last active April 16, 2019 20:46
$ cat src/foo/core.cljs
(ns foo.core)

(prn (time (reduce + (map inc (map inc (range (* 1024 1024)))))))
$ clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.516"}}}' -m cljs.main -O advanced -c foo.core
$ node out/main.js
(ns foo.bar
(:require foo.core)
#_(:require-macros foo.core))
(defn try-me []
(foo.core/m))
(ns foo.core)
(defmacro m []
`(foo.core/f))