This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-03-02
Channels
- # admin-announcements (9)
- # alda (21)
- # announcements (1)
- # beginners (68)
- # boot (241)
- # braid-chat (18)
- # cider (32)
- # cljs-dev (4)
- # cljsrn (11)
- # clojure (60)
- # clojure-dusseldorf (1)
- # clojure-germany (1)
- # clojure-poland (212)
- # clojure-russia (64)
- # clojure-sg (10)
- # clojurescript (212)
- # core-async (1)
- # css (14)
- # datomic (1)
- # emacs (9)
- # funcool (2)
- # hoplon (18)
- # jobs (1)
- # ldnclj (1)
- # lein-figwheel (5)
- # leiningen (3)
- # om (190)
- # onyx (46)
- # parinfer (13)
- # proton (3)
- # re-frame (7)
- # reagent (10)
- # ring-swagger (2)
- # slack-help (3)
- # specter (1)
- # yada (31)
I see. Very useful background @smw. I'm going to see if i can copy this and make it work. https://github.com/Lambda-X/replumb/tree/master/repl-demo/browser/cljs/replumb_repl
@smw @escherize you can use the cljs.js
namespace that ships with ClojureScript to evaluate stuff. It is not compatible with :advanced
and results in a decent amount of extra code if you go that route. Using the reader, on the other hand, doesn't have those aspects.
@escherize: give http://ClojureScript.io a spin to see its loading perf.
right, @mfikes, for my referenece, the reader is unable to evaluate, right? and is there some function in cljs.js where
(cljs.js/magic "(def a 1) a")
;;=> 1
yeah, I'm currently copying the implementation of http://clojurescript.io (replumb has an example section)
@escherize: if you wrap that in a do
you can use cljs.js/eval-str
On a slightly related question, is there a figwheel-style workflow working with planck somewhere?
@escherize: right. Replumb is on top of cljs.js
and adds REPL functionality.
Here's what I'm working on btw: http://take.ms/D3VkQ
@smw No. Planck supports (require 'some.ns :reload)
. It does not have code to watch the filesystem and load code when saved. (But it theoretically could.)
@escherize: I suppose a fiddle is sufficiently different from a REPL where Replumb might not be as useful as just using cljs.js
directly
I agree with @mfikes
we all agree with @mfikes 😄
when you @ your own name do you receive a notification?
but @escherize feel free to copy and paste and let me know if I can help if you are stuck ok? A lot of what you see in replumb is based from planck which was I guess based on that David project above
and just ran upon this article: http://yogthos.net/posts/2015-11-12-ClojureScript-Eval.html
@escherize: yeah, if you get stuck, just ask. One common mistake is to fail to initialize a namespace so that def
forms can do their side effects. Pure expressions work without that though.
btw we will soon open source a Code Mirror re-frame
component (it will be added to http://clojurescript.io as well)
it is actually Jared work that we are embellishing
so it will probably have Parinfer yes, or it will be very easy peasy to add
@escherize: Yogthos has a lot of good stuff in that article. Wonder why he skipped using eval-str
. Maybe just an oversight.
okay, @mfikes I think I ran into that problem, where there's no ns to def into (is that the proper way to say it?)
(defn eval-str [s]
(eval (empty-state)
(read-string s)
{:eval js-eval
:source-map true
:context :expr}
(fn [result] result)))
(defn run []
(reagent/render-component
(fn [] (eval-str @cljs-string))
(.getElementById js/document "baby-dom-target")))
he meant you have to initialize global
/`window` first: https://github.com/Lambda-X/replumb/blob/master/src/cljs/replumb/browser.cljs#L3
@escherize: Right… no need to define an eval-str
that calls read-string
. That’s built into cljs.js/eval-str
.
yes that too 😉
@escherize: With respect to the namespace: If you don’t indicate which namespace to eval in, cljs.js
defaults to cljs.user
. But there remains the fundamental issue that there is a cljs
global object with a user
object, etc.
So, how do you create a namespace in bootstrap? In Planck, I have it evaluate an ns
form if the user does in-ns
and the namespace doesn’t yet exist. There are probably different ways to skin that cat.
@richiardiandrea: so those are the options for eval-str, right?
basically replumb options are a mix of compiler options and its own, :target :default
is from the compiler but you don't need it if you are targeting the browser
@escherize: but that code was taken from the clojurescript repl, it is basically needed to init cljs.user
you might not need it, that is only needed if you want to have a cljs.user
ns
(eval-str (empty-state) "(ns cljs.user)" (fn [x] (js/console.log (clj->js x))))
;; prints: Error: No *eval-fn* set at cljs$js$_STAR_eval_fn_STAR_....
@mfikes: did you ever get to the bottom of this? https://github.com/mfikes/replete/issues/11
@escherize: are the symbol required correctly? (no :refer [eval-str]
on the top)
Here's the ns + calling form:
(ns cljsfiddle.app
(:require [reagent.core :as r]
[cljs.js :refer [eval-str empty-state]]))
(let [*eval-fn* identity]
(eval-str (empty-state) "(ns cljs.user)" (fn [x]
(def *error x)
(js/console.log (clj->js x)))))
{:error #error {:message "ERROR", :data {:tag :cljs/analysis-error}, :cause #object[Error Error: No *eval-fn* set]}}
at some point like above you need to set :eval js/eval
in the option map that you pass to cljs.js/eval-str
same for :load-fn
they are required
so load and no load-fn
@venantius: it might be same as https://github.com/clojure/clojurescript/commit/16666f37cc13ead5a66330046db82a2976b6f1f0
Is all that stuff required, @richiardiandrea ?
@escherize: no, I would say at the beginning you can just use :ns
:load
:eval
:context
too to :expr
and :def-emits-var true
they are all explained in the compiler option wiki
@venantius: Planck master builds against ClojureScript master (even if you brew install --HEAD planck
)
@richiardiandrea: so, here's what I've got:
{:load :source ;; <- misread this:
:ns 'cljs.user
:eval js/eval
:dev-emits-var true}
:load
needs to be a function, read here: https://github.com/Lambda-X/replumb#read-eval-call-options
@venantius: right. That fix is not in Planck 1.9, but it is in Planck 1.10 (master)
@venantius: meaning you'd have to follow the steps under Install Master here http://planck-repl.org/setup.html
wow, huge thanks to @richiardiandrea !!!
ahahah
happy to help!
Any tips on unit testing ClojureScript code.? I see speclj (https://github.com/slagyr/speclj) is built with both Clojure and ClojureScript in mind.
speclj seems outdated, and clojurescript now ships with a port of clojure.test - https://github.com/clojure/clojurescript/wiki/Testing
Thank you @delaguardo . How does speclj seem outdated I wonder, not being actively developed lately?
latest commit in speclj was about 8 months ago. It makes me think that the project is abandoned
know nothing about midje, sorry)
in my projects i use https://github.com/bensu/doo and it works like a charm
@stephenway: sadly React doesn't support (or Om doesn't support) the use
element in SVG https://facebook.github.io/react/docs/tags-and-attributes.html
@danielgrosse: isn't it just (defn get-menu [url] (parse-content (<!! (GET url))))
?
@danielgrosse: note that go
blocks are asynchronous and you can't block for a channel's result
So, I'm getting a :cljs/analysis-error when invoking the bootstrapped cljs compiler. But the interesting thing is if I run in development it actually works because I'm allowed to re-evaluate(?) the namespace. I'm invoking the compiler with the a namespace that's been evaluated (def'd?) Sorry my terminology is not good here.
I want to be able to import a library for the cljs bootstrapped compiler, and use it to evaluate some string and return a result.
(ns cljsfiddle.app
(:require [reagent.core :as r]
[cljsfiddle.samples-pane :refer [samples-pane]]
[cljsfiddle.db :refer [db]]
[cljs.js :refer [eval-str empty-state js-eval]]))
;;----snip-----
(defn my-eval [cljs-string]
(eval-str (empty-state)
(str
"(ns cljsfiddle.app)
(require '[reagent.core :as r :refer [atom]])"
cljs-string)
'dummy-symbol
{:ns 'cljsfiddle.app
:eval js-eval
:dev-emits-var true
:load (fn [& _] {:lang :clj :source "."})
:context :statement}
(fn [{:keys [error value] :as x}]
(if error
(do
(def *er x)
(js/console.log (str error)))
value))))
Uh, hey guys. So I've gotten an early version of http://cljsfiddle.com up and running.
@escherize: Looks cool… if you haven’t you may want to compile it with :static-fns true
, otherwise I think it is going to crap out on Safari.
(ns cljsfiddle.app
(:require [reagent.core :as r]
[cljsfiddle.samples-pane :refer [samples-pane]]
[cljsfiddle.db :refer [db]]
[cljs.js :refer [eval-str empty-state js-eval]]))
(defn my-eval [cljs-string]
(eval-str (empty-state)
(str "(ns cljs-user)
(def atom reagent.core/atom)"
cljs-string)
'dummy-symbol
{:ns 'cljs.user
:eval js-eval
:def-emits-var true
:load (fn [& _] {:lang :clj :source "."})
:context :statement}
(fn [{:keys [error value] :as x}]
(if error
(do
(def *er x)
(js/console.log (str error)))
value))))
@escherize: I’d first try with just :static-fns
true in the project itself, so that the base codebase is built that way. You may not need it for user code. It is at least worth trying.
@escherize: cool stuff
does it currently only work with Reagent?
@escherize: that's excellent! impressed
Man, that is so handy. For when I've got an idea I want to test out without access to my normal cljs dev environment
@escherize: that is absolutely fantastic, congrats
the lack of built-in support for require
in cljs.js stuff means you can't be very flexible in regard to deps, but this is a fantastic tool for introducing people to cljs nonetheless
I actually did (def atom reagent.core/atom)
to simulate the :require at the top of the clojurescript column
@escherize: I added some issues to the GitLab repo
But a "preset" ns
form could be added for some other libs too, maybe like Om obviously, or the toxi stuff which also deserves more attention
thanks @chrisoakman. I'm going to take you up re: parinfer btw
the Parinfer demo page I linked to in the issue is new; seems like there are some obvious synergies between those two projects (can't believe I just used the word "synergy" not in a corporate setting 😉 )
said another way: Ya'll should synergize.
@escherize: @mfikes: would pre-compiling a minified lib that just provides cljs.js/eval-str
as an exported function improve the startup time of cljsfiddle maybe?
I think it is a worthwhile experiment. You’d still need things like core.js
available for the compiled code to call upon. But the compiler itself might work under :advanced
.
like, the app could load instantly and set up a listener for the cljs.js/eval onload
, disabling the run button til it gets that
I would be of course interested too 😄 I always wondered if you could Make It Faster™
FWIW, there was a little experimentation on that front here https://github.com/mfikes/planck/issues/58
Might be worth discussing here: https://gitlab.com/escherize/cljsfiddle/issues/
But, yeah, you can get a lot of mileage out of the simple idea of bringing up the UI immediately.
@escherize: you should turn on gzip, that would probably half the load time 😛
in http://clojurescript.io we start with the html with loading 😄
and we have gzipped our main.js and deps.js
(For example, Replete on older devices does just that—and the compiler can take 20 seconds to load and be ready.)
@escherize: we use s3 as well, no complains so far
i wasn't sure about that, because in cljsfiddle there aren't really any fully qualified vars I could see?
I was thinking of a Frankenstein build where you just build everything using :advanced
but then keep that separate from :none
for the standard lib and evaluating compiled results. You’d almost want two JavaScript contexts.
you could try a :simple
compilation with :modules
, load the base module on page load and the compiler module later via async request
yes this is what we do
but simple sometimes does not behave like none in replumb, I have two issues open for instance, but for escherize it might be good
I’m still curious about an externs file that covers the entire standard lib, along with everything being subject to :advanced
basically it should not rename clojure.core.map
, etc... but every local, assuming there are enough locals to optimize I guess compared to the number of core functions used
so basically it is :simple
😄
Nah… I mean that it is one thing to propose a grand architectural approach, like half-advanced/half-none, or a gigantic externs file covering the standard lib, and another thing to actually execute upon it to see if it makes things faster.
Maybe something like (dir cljs.core)
is close to what would be in an externs file. Hmm.
@escherize: Take it easy. Congrats on CLJS Fiddle!
I'm having a performance issue with syntax quote/unquote. Any reason why something like this is slow?
(let [i 42] `[(test {:a [{:a ~i :stuck_out_tongue: 3}]})])
@cmcfarlen: splicing expands into a series of concatenations
But its "pinwheel the browser until it dies" slow. Context is an om next transaction.
@cmcfarlen: Safari?
@cmcfarlen: Try building with :static-fns true
@cmcfarlen: Safari has a known long outstanding bug with nested invokes
not going to do anything about it thought as there is the workaround that @mfikes has mentioned
@cmcfarlen: Hmm. Chrome? That’s interesting. Your expression is definitely harsh in JavaScriptCore w/o :static-fns true
but instant with:
$ planck
cljs.user=> (time (let [i 42] `[(test {:a [{:a ~i 1 3}]})]))
"Elapsed time: 10806.000000 msecs"
[(cljs.core/test {:a [{1 3, :a 42}]})]
$ planck -s
cljs.user=> (time (let [i 42] `[(test {:a [{:a ~i 1 3}]})]))
"Elapsed time: 1.000000 msecs"
[(cljs.core/test {:a [{1 3, :a 42}]})]
yeah, I was just noticing the same thing. Is there a downside to just running :static-fns true
? I think I'll switch to using list and '
David Nolen gave this explanation a while back: > It's an option mostly because of REPL development to allow for redefinition. For example if :static-fns true we statically dispatch to specific fn arities—but what if you redef to a different set of arities? What if you change the var to store a deftype instance that implements IFn. That kind of thing. > So for compilation :static-fns can nearly always be true, but for the REPL it's not desirable.