clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
tomrbowden 2021-01-20T01:16:59.104200Z

Does anyone know of a ClojureScript playground equivalent of CodePen/CodeSandbox?

grazfather 2021-01-20T02:06:23.104600Z

I do not, but i imagine you could spin one up rather quickly with figwheel?

tomrbowden 2021-01-20T02:08:31.105400Z

I'd like to be able to easily share frontend code and its visual effect with others via a URL...

dpsutton 2021-01-20T02:16:27.105600Z

theres this: http://app.klipse.tech/

tomrbowden 2021-01-20T02:36:17.107800Z

@dpsutton That's quite nice for embedding live code into a website. But are there are no CLJS solutions for quickly creating a small code sandbox with dependencies (eg. reagent), and sharing it via URL?

dpsutton 2021-01-20T02:36:37.108100Z

not that i'm aware.

tomrbowden 2021-01-20T02:37:57.108900Z

OK, thanks.

Grigory Shepelev 2021-01-20T08:18:37.111200Z

Hello there! Please help. How do I set up HTML5 history with retit in my webapp on shadow-clj? I used the official example https://github.com/metosin/reitit/tree/master/examples/frontend Except for having shadow-clj instead of figwheel. And basically copy-pasting server and frontend code with the following addition on config:

:dev-http {8000
            {:root "public"
             :handler shadow.server/handler}}

Grigory Shepelev 2021-01-20T08:19:01.111800Z

And It show the weird error on any path except / .

Grigory Shepelev 2021-01-20T08:19:16.112100Z

Uncaught SyntaxError: expected expression, got '<' web-api.js:1

Grigory Shepelev 2021-01-20T08:19:59.112900Z

If there are anyone who set up retit with html5 history in cljs, please answer!

thheller 2021-01-20T10:21:44.113600Z

@altjsus that means your server served some HTML when it was expecting some Javascript

thheller 2021-01-20T10:22:22.113900Z

maybe your handler didn't properly serve the files

2021-01-20T14:26:00.114700Z

What args will be passed in to the inner function?

2021-01-20T14:31:12.115600Z

(defn timer-component []
  (let [seconds-elapsed (reagent/atom 0)]     ;; setup, and local state
    (fn [a b c d e f g h i j k ]        ;; inner, render function is returned
      (js/setTimeout #(swap! seconds-elapsed inc) 1000)
      [:div "Seconds Elapsed: " @seconds-elapsed])))
If I add arbitrary args, e.g., a, b, c, d, e,f… nothing goes wrong. The function arity is fine. Weird.

thheller 2021-01-20T14:33:13.115900Z

the same args as the outer fn

thheller 2021-01-20T14:33:30.116300Z

just might change on update, the outer ones you only get once

2021-01-20T14:35:46.116400Z

In any case the outer args would change?

2021-01-20T14:36:28.116600Z

[out-func arg1 arg2] They are fixed written in the code.

2021-01-20T14:37:44.116800Z

Fundamentally, when reagent calls the inner func, where are the args from?

thheller 2021-01-20T14:47:35.117Z

as I said ... they are the same args. don't have time to explain this further sorry.

thheller 2021-01-20T14:48:23.117200Z

all this does is let you create state once on mount, after that is only calls the inner function

2021-01-20T14:53:09.117400Z

I saw this: https://cljdoc.org/d/reagent/reagent/1.0.0/doc/tutorials/when-do-components-update-#1-props which answers my question.

prnc 2021-01-20T15:27:57.119Z

Hi everyone πŸ‘‹ what is the correct way to handle uuid deserialisation from transit in cljs? the default is to com.cognitect.transit UUID instead of cljs.core/UUID, Thanks πŸ™

prnc 2021-01-20T15:30:50.119200Z

is it still: just add (extend-type com.cognitect.transit.types/UUID IUUID) to your code, as per: https://github.com/cognitect/transit-cljs/issues/41?

dpsutton 2021-01-20T15:42:34.119500Z

yeah go ahead and do that. that's the most confusing bug ever ha

prnc 2021-01-20T15:43:30.119700Z

yeah it was pretty surprising to see

prnc 2021-01-20T15:43:37.119900Z

thanks!

Hagenek 2021-01-20T15:54:06.120500Z

Do you guys know of any beginner-friendly and free tutorials for ClojureScript // ClojureScript Reagent?

exit2 2021-01-20T15:58:18.120600Z

I found https://www.braveclojure.com/ was helpful

exit2 2021-01-20T15:58:47.120800Z

And then the reagent docs, once you have a grasp on the clj/cljs syntax

grounded_sage 2021-01-20T16:20:09.121600Z

Is there a simple way to escape core async using callbacks?

jtkdvlp 2021-01-20T16:21:46.122600Z

there are take! and put! fns using callbacks I guess, but why use callbacks? XD https://clojure.github.io/core.async/#clojure.core.async/take!

grounded_sage 2021-01-20T16:23:13.122800Z

How would I rewrite this

(defn async-plus []
    (go (<! (go (+ 1 1)))))
So when I call it I get the result and not the channel.

jtkdvlp 2021-01-20T16:24:09.123100Z

cljs or clj?

grounded_sage 2021-01-20T16:24:14.123300Z

cljs

jtkdvlp 2021-01-20T16:24:39.123900Z

so you want make it a sync call?

grounded_sage 2021-01-20T16:25:09.124600Z

I want to escape channels

alexmiller 2021-01-20T16:25:32.125200Z

I think take! is your only option there

dpsutton 2021-01-20T16:25:44.125300Z

you've got extra levels of go and <! there just pointing out. And you cannot. Imagine (+ 1 1) took three seconds. There is no notion of blocking or waiting in js like that

jtkdvlp 2021-01-20T16:26:06.125900Z

In cljs you cant make it sync, since you are async you will always be async. In clojure you could wait for the result blocking the current thread, on cljs you cant cause its single threaded js

grounded_sage 2021-01-20T16:27:00.127Z

I’ve got it there for simplicity. Assuming that the (+ 1 1) is an operation that must be async. The <! is to simulate me taking from it. Which also must itself be in a go block.

dpsutton 2021-01-20T16:27:52.127700Z

(go (&lt;! (go (+ 1 1)))) would be equivalent to (go (+ 1 1)) they both will be a channel with the value 2 on it

grounded_sage 2021-01-20T16:28:45.128900Z

Yea I just thought that between the first go and take. When the value is received. There would be a way to use a callback or something to return it. But I can’t figure it out.

jtkdvlp 2021-01-20T16:29:29.129500Z

(take! (go (+ 1 1)) your-callback-fn) or (go (your-callback-fn (&lt;! (go (+ 1 1))))

grounded_sage 2021-01-20T16:31:46.130300Z

(defn async-plus []
 (take! (go (+ 1 1)) identity))
returns nil when called

jtkdvlp 2021-01-20T16:33:03.130700Z

from the docs:

Usage: (take! port fn1)
       (take! port fn1 on-caller?)
Asynchronously takes a val from port, passing to fn1. Will pass nil
if closed. If on-caller? (default true) is true, and value is
immediately available, will call fn1 on calling thread.

fn1 may be run in a fixed-size dispatch thread pool and should not
perform blocking IO, including core.async blocking ops (those that
end in !!).

Returns nil.

grounded_sage 2021-01-20T16:34:08.131Z

I’m obviously stuck. Seems there is no solution?

dpsutton 2021-01-20T16:35:08.132100Z

no. you can't wait for an async operation to continue and carry on like that. the callback has to be the thing to handle it

jtkdvlp 2021-01-20T16:35:26.132700Z

in clojure you could do (println (&lt;!! (go (+ 1 1)))) in CLJS you cant

grounded_sage 2021-01-20T16:35:47.133400Z

So I probably have to introduce an atom here and try and figure out some trickery

dpsutton 2021-01-20T16:35:50.133600Z

imagine (take! (go (+ 1 1)) identity) the (+ 1 1) takes 20 seconds. javascript has no way to pause the world while waiting for the twenty seconds

grounded_sage 2021-01-20T16:36:12.134300Z

I know. I just thought there might be a simple callback solution.

dpsutton 2021-01-20T16:36:16.134400Z

it's just going to call (identity 2) in twenty seconds

grounded_sage 2021-01-20T16:37:38.135300Z

all good. I think I have to rethink how I want to approach this

Jp Soares 2021-01-20T18:10:40.136700Z

Question about self-hosting cljs. Is there a way to use the compiler option :warning-handlers with cljs.js/eval-str? It looks like the available options of [cjs.js/eval-str](https://cljs.github.io/api/cljs.js/eval-str) are limited.

(defn evaluate [s callback]
  (cljs.js/eval-str
    compile-eval-state
    s
    nil
    {:eval cljs.js/js-eval
     :load (partial shadow.bootstrap/load (analyzer/empty-state))
     :warning-handlers [my-fn]
     :context :expr}
    (fn [result] (do (js/console.log result)
                     (callback result)))))
I also tried to pass compiler-options as an argument of analyzer/empty-state but I had no success.

Ivan Curic 2021-01-20T19:57:29.138900Z

anyone else is having problems with Calva in VS-Code and clojure-lsp never managing to start?

Ivan Curic 2021-01-21T12:39:55.023100Z

it seems something fixed it… no idea what πŸ˜… will do if I encounter it again.

pez 2021-01-21T12:50:56.023500Z

Deal! πŸ˜ƒ

babardo 2021-01-20T20:00:51.139400Z

Hello im starting to dig into promise chaining in cljs, and for the moment I'm happy with core.async. (https://clojurescript.org/guides/promise-interop#using-promises-with-core-async)

babardo 2021-01-20T20:01:44.139500Z

But I don't know how to compose πŸ˜• Is it an easy way to get back a js/promise from a channel?

babardo 2021-01-20T20:02:34.139700Z

I'm thinking on wrapping chan in a js/promise and using take! to trigger the callback. Is there a better way to do?

dpsutton 2021-01-20T20:05:09.140100Z

i think it would be something like this:

(def c-&gt;p [c]
  (let [p (js/Promise.)]
    (take! c #(.resolve p %))
    p))

πŸ™ 1
dpsutton 2021-01-20T20:05:16.140300Z

oh and return p sorry

babardo 2021-01-20T20:07:19.140700Z

thx I will add a bit of error handling and it will be nice πŸ™‚

dpsutton 2021-01-20T20:09:01.140900Z

if you check the source of the macro p->c it will be largely like this

dpsutton 2021-01-20T20:09:52.141100Z

ah its &lt;p!.

πŸ™ 1
babardo 2021-01-20T20:11:02.141300Z

ah yes, it does the error checking :thumbsup:

dpsutton 2021-01-20T20:12:06.141800Z

cljs.user=&gt; (source clojure.core.async.interop/p-&gt;c)
(defn p-&gt;c
  "EXPERIMENTAL: Puts the promise resolution into a promise-chan and returns it.
   The value of a rejected promise will be wrapped in a instance of
   ExceptionInfo, acessible via ex-cause."
  [p]
  (let [c (async/promise-chan)]
    (.then p
           (fn [res]
             (if (nil? res)
               (async/close! c)
               (async/put! c res)))
           (fn [err]
             (async/put! c
                         (ex-info "Promise error"
                                  {:error :promise-error}
                                  err))))
    c))

dpsutton 2021-01-20T20:12:31.142Z

make a channel, use the then of the promise to put on the channel. same idea here. make a promise, when you take from the channel resolve the promise with it

Hagenek 2021-01-20T20:14:26.142800Z

Thanks:smiley: I am on chapter 4 of Brave True now

Helins 2021-01-20T23:26:38.147Z

Unless I am mistaken, it looks like having a namespace ending in 'init' (eg. my.namespace.init) completely breaks things. It compiles without a fuzz but other namespaces are loaded as undefined. Does it make sense? Using Shadow-CLJS

Helins 2021-01-21T12:45:45.023300Z

There is something else at stake... My namespace which is pretty much empty is loaded but results in being undefined when used somewhere else... I've spent hours on this

p-himik 2021-01-21T12:51:54.023700Z

If it still doesn't work after clearing everything build-related, can you create a minimal reproducible example and share the link to its repo?

thheller 2021-01-21T13:22:35.024Z

if you get an exception during load that may prevent the namespace from being created. check the browser console.

thheller 2021-01-21T13:23:05.024200Z

other than that my.namespace.init is completely fine and should work

Helins 2021-01-21T15:17:10.030900Z

It's madness, utter madness. I've spent a whole day on this! Never ever have I encountered something as maddening and I had my fair share of weird behavior with CLJS... I have a CLJC file in a folder. At this point it's just a namespace with (def foo 42) as a test. When required from a CLJS file, everything is fine, I can access foo. When required from a CLJC file, then suddenly everything breaks. The namespace becomes undefined, even in CLJS. Compilation is fine, requiring is fine (error comes when trying to access foo on undefined later). But wait it gets worse. This very same file, when put in another folder works right away from everywhere. I have a cursed folder name piece and any CLJC file inside of it, when required from another CLJC file, produces this behavior. It's not about permissions, I have even re-created that folder to make sure. I have literally DOZENS of other CLJC files required by CLJC files. It's just about that damn piece folder. Works with piece2. Furthermore, the JS output file looks absolutely fine. Clearing .shadow-cljs, .cpcache and all compiled JS files, the browser cache... doesn't make a difference.

p-himik 2021-01-21T15:26:41.032Z

Please create a minimal reproducible example.

thheller 2021-01-21T15:49:56.032200Z

just run shadow-cljs browser-repl

thheller 2021-01-21T15:50:05.032400Z

and then (require 'my.namespace.init)

thheller 2021-01-21T15:50:25.032600Z

what does "the namespace becomes undefined" even mean?

thheller 2021-01-21T15:51:32.032800Z

do you get any warnings? do you maybe have (ns my.namespace.init) and also (ns my.namespace) (defn init []...)?

thheller 2021-01-21T15:52:14.033200Z

it is rather unlikely this has anything to do with caching and so on so rather look in your own code for causes

Helins 2021-01-22T17:00:56.041600Z

No warnings at all, and I can require and use this namespace from the browser-repl just as from any Clojurescript file. "becomes undefined" means that when it is required from a CLJC file, then is sorts of suddenly disappear. When I try to access a var such as foo from the REPL or anywhere in my code, I get a TypeError: Cannot read property 'foo' from undefined. And it's so weird I have to repeat it, it only happens with namespaces in that one folder. I really can't see what could produce this mystery in my own code or code organization, I am following the same simple structure I've been using for dozens of files... I'll try to make a repro case but since I have no idea what is going on, I'm not sure I'll succeed (and I cannot share the source of this quite massive commercial project).

pez 2021-01-20T23:40:59.148400Z

Hello. Can you post this in #calva?

πŸ‘€ 1