This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-22
Channels
- # announcements (1)
- # babashka (28)
- # beginners (120)
- # braveandtrue (6)
- # calva (59)
- # cider (10)
- # clj-kondo (10)
- # cljfx (2)
- # clojure (66)
- # clojure-europe (20)
- # clojure-germany (1)
- # clojure-italy (3)
- # clojure-nl (4)
- # clojure-norway (1)
- # clojure-serbia (17)
- # clojure-spain (1)
- # clojure-uk (17)
- # clojurescript (120)
- # clojureverse-ops (4)
- # core-async (5)
- # cursive (18)
- # data-oriented-programming (1)
- # datomic (4)
- # deps-new (8)
- # emacs (14)
- # fulcro (16)
- # funcool (2)
- # kaocha (4)
- # lambdaisland (5)
- # luminus (1)
- # malli (47)
- # membrane (9)
- # mid-cities-meetup (2)
- # music (1)
- # off-topic (44)
- # pathom (13)
- # practicalli (2)
- # re-frame (15)
- # reagent (34)
- # reveal (25)
- # ring (56)
- # rum (1)
- # shadow-cljs (23)
- # sql (14)
- # startup-in-a-month (1)
- # tools-deps (10)
- # vim (9)
- # vscode (3)
- # xtdb (9)
I’m assuming that this also applies to Cljs libraries.. https://blog.fikesfarm.com/posts/2017-11-18-clojurescript-performance-measurement.html cc @mfikes
I’m working through @asmeredith’s Learn Clojurescript. Is listing 5.4 is the same deps.edn file as listing 5.1? I added the aliases, ran clj -M:dev, and got “Error building classpath. Error reading edn. Invalid file, expected edn to contain a single value.”
{:deps {org.clojure/clojurescript {:mvn/version “1.10.773”}} :paths[“src”]} :aliases {:dev {:main-opts [“-m” “cljs.main” “--compile” “test-cljs-project.core” “--repl”]}}
{:deps {org.clojure/clojurescript {:mvn/version “1.10.773”}}
:paths[“src”]
:aliases
{:dev {:main-opts [“-m” “cljs.main”
“--compile” “test-cljs-project.core”
“--repl”]}}}
you had aliases and the map it corresponded to outside of the top level mapwhich is why the tooling was complaining that the edn file had more than one value. It should have only a single map
The function compile-str
in cljs.js
doesn't seem to ever call the finished callback, I'm not sure what's going on, any suggestions on the best way to debug this?
Is there a way to use template literal tag functions from js in cljs? I need to do
sql`SELECT * FROM my-table
`
but not sure how, or if it’s possible.If I'm not mistaken tagged template literals are still just functions, so you should be able to call the fn with the string as the only argument
(sql "SELECT * FROM my-table")
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
ah, I've misunderstood slightly. the template literal fn only receives args for the interpolated values positionally, not the whole string as it's only arg
https://codeburst.io/javascript-template-literals-tag-functions-for-beginners-758a041160e1
the 0th argument to the fn is the template string
the n+ args are the interpolated values
Thanks! I also tried the template tag in node and realized it just returns
{sql: "SELECT * FROM tabl WHERE id=$1",
type: "SLONIK_TOKEN_SQL",
values: [7]}
Okay, I did finally get the compile function to return. Although now I have another question:
When I use eval-str
in cljs.js
on some module B that requires module A, the load function finds the module A, and then executes both module A and B.
However, if I use compile-str
instead, the load function seems to find both A and B, but only seems to compile B.
(And if so, is there any way I can get a compile-str
like function, that either: (i) compiles A and B together, or (ii) compiles B in a way that doesn't require me to manually call compile-str
on A?
(When I do try to pass the result of compile-str
to js/eval
I get: Error: goog.require could not find: A.core)
@leif https://clojure.atlassian.net/browse/CLJS-3288 and https://clojure.atlassian.net/browse/CLJS-3286 are two open issues regarding self-hosted cljs to be aware of. We recently switched to https://github.com/borkdude/sci for eval and are quite happy with it, found it less complex to setup and it’s lighter weight. It even works with advanced compilation. The downside is that it’s a slower as it’s an interpreter, not a compiler.
I'm looking for something that can output javascript that I can potentially transform with babel, can sci do that?
You're correct that sci
is a clojure interpreter (not a compiler)
Although I guess if it has the capability to pause computations that would be enough for me.
(Like if I could set up (loop [] (recur))
to be breakable and not inherently freeze the browser until the tab is reloaded.
That sounds challenging (in a javascript environment) but not strictly impossible... I think you'd have to hack something into sci
to allow evaluation to be interruptable with core.async
(for example)
I don't know enough about sci
but I'd say if you're willing to modify it, you should be able to make a core.async
loop that does a few steps of evaluation and then checks if the kill
channel has been closed
@blak3mill3r Oh, I'm using stopify (https://www.stopify.org/) right now, which seems to work surprisingly well for how small a project it is.
some inspiration to keep trying: https://m.youtube.com/watch?v=MdmQUlD7P40
Even when instrumenting sci with all kinds of checks, there is still probably a program that can work around it
There are advanced type systems with less powerful programming languages, like Dhall, which provably terminate
Although ya, it would be nice if we could solve the halting problem, fortunately what I"m trying to do is MUCH simpler then that. 😉
but sci did have some flags to control execution time https://github.com/borkdude/sci/issues/348
but 0.1 still had them? https://github.com/borkdude/sci/blob/master/CHANGELOG.md#breaking-changes
The https://arxiv.org/abs/1802.02974 seems to indicate that the techniques are more general than just javascript > We apply Stopify to 10 programming languages
@smith.adriane Only partially.
When you look at the source code for their little clojurescript debugger demo, it actually compiles to javascript first.
Stopify sounds cool. I think you might have luck running sci
with Stopify.
@blak3mill3r I'll give it a shot and let you know how it goes. 🙂
I'm curious... I mean I guess Stopify must be doing some sophisticated static analysis and source->source translation
kinda like core.async...
I think you can even fool core.async, by putting`(Thread/sleep 1000000)`, it won't help you there
I mean that core.async's implementation details involve code splitting/rewriting using clojure macros
On the other hand, if it did, you could run your eval in a thread and then kill the thread if it took too long ;)
Yeah I thought for a moment about WebWorkers
run self-hosted cljs or sci in a WebWorker and perhaps there's an API to kill it after a timeout
@blak3mill3r A webworker won't work, I want to manipulate the dom.
you'd have to do that indirectly which would be a pain
Although I guess if its possible to get react working with actors (sounds painful), I'd be willing to give it a go.
Modified from a recent message I sent to Arjun:
<script src=""></script>
<script>
const prog = `
var i = 0;
debugger;
while(i < 10) {
console.log(i);
i = i + 1
};`;
let runner = stopify.stopifyLocally(prog);
runner.g = {console};
runner.run(() => {
console.log(runner.g.i);
console.log("DONE!");
});
</script>
@leif there is (an old) version of sci on npm available, if you want to try it out quickly
I have deprecated the npm package more or less since it's way easier to configure it from CLJS and the compile it to JS yourself
Ah, found it: https://www.npmjs.com/package/@borkdude/sci
Yeah, still seems to work:
> const { evalString } = require('@borkdude/sci');
undefined
> evalString("(str (assoc {:a 1} :b 2))")
'{:a 1, :b 2}'
Sadly it doesn't quite seem to work with stopify...although maybe I'm doing something wrong
sci.js?3eac:910 Uncaught Mn {message: "Dc(...).append is not a function [at line 1, column 1]", data: k, Bc: TypeError: Dc(...).append is not a function
at Function.VU.f (webpack-internal:///./node_module…, name: "Error", description: undefined, …}
var stopify = require ('@stopify/stopify');
var sci = require('@borkdude/sci');
window.stopify = stopify;
let runner = stopify.stopifyLocally(sci.evalString("(println (+ 1 2))"));
runner.g = {console};
runner.run(() => {console.log("DONE!");});
@leif this is a warning you will get when using println, this doesn't work with sci out of the box, you will have to bind the out stream to something
so for just testing this, it's better to configure your own println or just avoid printing for now
> evalString("(println (str (assoc {:a 1} :b 2)))", {"namespaces": {"clojure.core": {"println": console.log}}})
{:a 1, :b 2}
Hmm:
Uncaught TypeError: this.input.charCodeAt is not a function
at Parser.fullCharCodeAtPos (index.js?0cd6:781)
at Parser.nextToken (index.js?0cd6:766)
at Parser.parse (index.js?0cd6:1672)
at Object.parse (index.js?0cd6:7305)
at Object.stopifyLocally (compiler.js?e91e:100)
at eval (in.js?73b4:10)
at Object../in.js (out.js:96)
at __webpack_require__ (out.js:20)
at out.js:84
at out.js:87
But it just occurred to me that it could be that sci is putting something in the window object that the stopify sandbox isn't allowing.
all mutation is local to sci, it never mutates the outside world unless you configure it to (hence no printing by default)
var stopify = require ('@stopify/stopify');
var sci = require('@borkdude/sci');
window.stopify = stopify;
//console.log(sci.evalString("(+ 1 2"));
const prog = `
console.log(sci.evalString("(doall (range))"));
`;
let runner = stopify.stopifyLocally(prog);
runner.g = {console, sci};
runner.run(() => {console.log("DONE!");});
it's stoppable ^ like that? That's pretty nifty
@blak3mill3r Sadly no. 😞
So in this case, sci is coming in from the outside world. Hence why I suspect it doesn't work. So now I need to see if I can bring sci itself in.
Ah, sad. So I can't seem to get stopify to work with webpack packages just at the moment. I'll poke Arjun and see what he has to say. I'll get back to you about this later @blak3mill3r and @borkdude . Thanks for all your help btw! 🙂