clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Nazral 2021-01-29T05:44:08.188Z

Hi everyone, I have a question regarding file upload from drag & drop. I do it this way: https://git.sr.ht/~tyruiop/constellation/tree/main/item/viz/src/main/viz/sidebar.cljs#L233 And it works perfectly fine with firefox, however with Chromium datatransfer remains empty no matter what I do, any idea how to solve it? All the solutions I found on stackoverflow for javascript just didn't work Nevermind, the problem came from Wayland, it works just fine with Xorg

clyfe 2021-01-29T06:27:56.188500Z

yes

clyfe 2021-01-29T06:28:22.188700Z

> GET http://localhost:9000/out/brepl_deps.js net::ERR_ABORTED 404 (Not Found) I'm also bothered by that.

clyfe 2021-01-29T07:30:26.188900Z

Nvm, I nailed it! This guide here is outdated: https://clojurescript.org/guides/webpack

Helins 2021-01-29T09:37:16.190300Z

Is there a guide somewhere about what the Closure Compiler has trouble with when eliminating code?

thheller 2021-01-29T09:51:09.192500Z

anything with side effects or what it thinks may be side effects 😉 not aware of more precise docs

👍 1
Helins 2021-01-30T09:09:40.222800Z

I think it struggles with laziness in general, probably fearing side effects. For instance it doesn't seem to remove things like (def foo (concat ...)) That might explain why my advanced builds are usually fat and seem to include quite a lot of unneeded junk (looking at Shadow's report). So I am wondering if it's worth the trouble to wrap top-level vars in some way, or wrap those top-level values in a (delay) for instance.

thheller 2021-01-30T09:19:29.223Z

yes, laziness is not something it understands. (delay) works

Helins 2021-01-30T10:09:21.223400Z

Then library authors should know about this as it is not something you think about too much unless you're doing a lot of CLJS.

Grigory Shepelev 2021-01-29T10:10:01.192800Z

I'm working on a small personal blog app on clojurescript using reagent and reitit as a router. For some reason component isn't updated when atom is. There is a post on Reagent docs on this proble. But it didn't helped: https://cljdoc.org/d/mthomure/reagent/0.8.1-custom-components/doc/frequently-asked-questions/why-isn-t-my-component-re-rendering- May be someone ran into same problem or it's something obvious that I can't see. Here is the code for my post:

clojure
(ns posts.second-post
  (:require [cljs-http.client :as http]
            [cljs.core.async :refer [<! go] :as async]
            [reagent.core :as reagent]))

(defonce d
  (reagent/atom nil))

(defonce request
  (go
    (let [responce (&lt;! (htt p/get "<https://www.google.com/>" {:with-credentials? false}))]
      (reset! d responce))))
      
(def post 
  {:meta {:slug "first-post"}
  ;; UPDATE DOESN'T HAPPEND HERE!
   :content [:span (str @d)]})
Here is the post view:
clojure
(ns blog.views
  (:require [blog.config :refer [conf]]
            [reagent.core :as reagent]
            [clojure.string :as string]
            [reitit.frontend.easy :as rfe]
            [blog.posts :refer [posts]]
            [cljs.core.async :refer [&lt;! go]
            ...]))

(defn post
  [match]
  (let [{:keys [path]} (get match :parameters)
        {:keys [slug]} path
        requested-post
        (first
         (filter
          (fn [p]
            (= slug (get-in p [:meta :slug]))) posts))]
    (if (some? requested-post)
       [:div  (get requested-post :content)]]
      [:span "Post not found")])))
And here is the code for my core (and router):
clojure
(ns blog.core
  (:require [blog.views :as views]
            [reagent.core :as reagent]
            [reitit.frontend :as rf]
            [reitit.frontend.easy :as rfe]
            [reitit.coercion.spec :as rss]
            [spec-tools.data-spec :as ds]
            [reagent-material-ui.core.container :refer [container]]))

(defonce match (reagent/atom nil))

(defn current-page
  []
  [container
   (if @match
     (let [view (:view (:data @match))]
       [view @match]))])

(def routes
  [["/"
    {:name :frontpage
     :view views/home}]
   ["/post/:slug"
    {:name :post
     :view views/post
     :parameters
     {:path
      {:slug string?}
      :query
      {(ds/opt :lang) string?}}}]])

(defn start
  []
  (rfe/start!
   (rf/router
    routes
    {:data {:coercion rss/coercion}})
   (fn [m]
     (reset! match m))
    ;; set to false to enable HistoryAPI
   {:use-fragment false})
  (reagent/render
   [current-page]
   (.getElementById js/document "app")))

(defn ^:export init []
  ;; init is called ONCE when the page loads
  ;; this is called in the index.html and must be exported
  ;; so it is available even in :advanced release builds
  (start))

(defn stop []
  ;; stop is called before any code is reloaded
  ;; this is controlled by :before-load in the config
  (js/console.log "stop"))

p-himik 2021-01-29T10:34:38.193Z

I don't see how exactly you're using that posts.second-post/post.

p-himik 2021-01-29T10:35:39.193200Z

Also, consider creating code snippets instead of code blocks when your code is rather long. The snippets are collapsed by default which makes it much easier to navigate the rest of the channel.

Grigory Shepelev 2021-01-29T10:36:07.193400Z

Thnx. I will try snippets next time.

Grigory Shepelev 2021-01-29T10:36:30.193600Z

(ns blog.posts
  (:require [posts.first-post :as first-post]
            [posts.second-post :as second-post]))

(def posts
  [first-post/post
   second-post/post])

p-himik 2021-01-29T10:38:45.193800Z

I need to see the view that ends up using posts.second-post/post. Anything else is irrelevant, at least right now.

p-himik 2021-01-29T10:39:47.194Z

A ratom change causes a view to re-render when both of these conditions are met: - That ratom was deref'ed in that view - That view function was used with [...] and not with (...)

thheller 2021-01-29T10:40:09.194200Z

maybe reading https://code.thheller.com/blog/shadow-cljs/2019/08/25/hot-reload-in-clojurescript.html will help

thheller 2021-01-29T10:40:30.194500Z

the trouble is most likely holding on to a reference of other namespaces that aren't directly reloaded

thheller 2021-01-29T10:41:15.194700Z

see "Holding Code references in State"

thheller 2021-01-29T10:41:33.194900Z

(def posts
  [first-post/post
   second-post/post])

Grigory Shepelev 2021-01-29T10:41:40.195100Z

@p-himik

(ns blog.views
  (:require [blog.config :refer [conf]]
            [reagent.core :as reagent]
            [clojure.string :as string]
            [reitit.frontend.easy :as rfe]
            [blog.posts :refer [posts]]
            [cljs.core.async :refer [&lt;! go]
            ...]))

(defn post
  [match]
  (let [{:keys [path]} (get match :parameters)
        {:keys [slug]} path
        requested-post
        (first
         (filter
          (fn [p]
            (= slug (get-in p [:meta :slug]))) posts))]
    (if (some? requested-post)
       [:div  (get requested-post :content)]]
      [:span "Post not found")])))

thheller 2021-01-29T10:41:42.195300Z

is a good example of this pattern that should be avoided

Grigory Shepelev 2021-01-29T10:41:50.195500Z

That's the view

p-himik 2021-01-29T10:43:27.195700Z

@altjsus My bad, the error is actually visible before that. You @ the ratom way before it gets into the view - when you assign the value to def. It's executed when the resulting JS bundle is loaded - Reagent has no way of knowing that there's a ratom involved at all. As I said, put all @ on ratoms in view functions. Or in regular functions, but then call those functions only from the view functions.

p-himik 2021-01-29T10:46:10.195900Z

@thheller I think there's a misunderstanding and it has nothing to do with hot code reloading. But still - how can the code piece that you quoted cause any issues, given that it's def and not defonce? Because first-post/post is in a different NS that, when changed, won't cause the namespace of posts to be reloaded?

1
thheller 2021-01-29T10:49:59.196100Z

a -> b -> c when you make changes in c then only b is automatically updated as well but not a. so if a is holding a reference of b that is holding a reference of c then a will become stale after an update in c

p-himik 2021-01-29T10:50:55.196300Z

And there's no feasible way to circumvent this, is there?

p-himik 2021-01-29T10:51:11.196500Z

I mean, automatically, without having to wrap everything in lambdas and var stuff.

Grigory Shepelev 2021-01-29T10:51:52.196700Z

The current situation is it's only shown on code changed and shadow-cljs reloaded. It's kinda works on recompiling only.

Grigory Shepelev 2021-01-29T10:51:55.196900Z

I guess.

Grigory Shepelev 2021-01-29T10:52:04.197100Z

That's the current state of the problem.

thheller 2021-01-29T10:52:37.197300Z

well you can use :devtools {:reload-strategy :full} but that will make every reload slower

👍 1
Grigory Shepelev 2021-01-29T10:53:40.197700Z

Nope. Again I don't want to change my reload strategy. This piece don't works as expected even when code is compiled and served with another server.

Grigory Shepelev 2021-01-29T10:54:26.198Z

The problem seems-like to be described by @p-himik

thheller 2021-01-29T10:55:24.198200Z

from what I can tell you are putting the reitit match data into an atom

p-himik 2021-01-29T10:55:29.198400Z

Yes, I kinda hijacked this thread to ask thheller about a way to fix a hypothetical code reloading issue. Your problem has nothing to do with that. As soon as you move that @ inside a view, it will be working properly.

p-himik 2021-01-29T10:55:33.198600Z

@thheller Wrong atom. :)

thheller 2021-01-29T10:55:36.198800Z

that match data contains a direct reference to a view function

thheller 2021-01-29T10:55:47.199Z

you update the code but the match still contains the old view function

thheller 2021-01-29T10:56:10.199200Z

tada you have a stuck hot-reload but I'm not entirely sure this is actually what is happening

p-himik 2021-01-29T10:56:13.199400Z

Nope, that's not the described problem. Read the end of the very first code block in the OP.

Grigory Shepelev 2021-01-29T10:56:23.199600Z

I don't understand what should I fix right now.

p-himik 2021-01-29T10:56:58.199800Z

@altjsus You have to change quite a lot - you cannot just inline the value of @d like that. You have to call it when the view is rendered, not before that.

p-himik 2021-01-29T10:58:50.200Z

Here's something that's similar to what you're doing:

(def a (reagent/atom 0))

(def b (inc @a))

(defn view []
  [:span b])
It will not work because b is set when the JS is evaluated. Instead, something like this needs to happen:
(def a (reagent/atom 0))

(defn b []
  (inc @a))

(defn view []
  [:span (b)])

p-himik 2021-01-29T10:59:21.200700Z

Now that @ is called only when the view is rendered, not before. And it makes it possible for Reagent to start tracking that ratom for changes.

Shantanu Kumar 2021-01-29T10:59:41.201300Z

Can anybody suggest a replacement for goog.dom.query that was removed from Google Closure? I am trying to fix up some old code that uses query.

Grigory Shepelev 2021-01-29T11:00:08.201400Z

Ok.

Grigory Shepelev 2021-01-29T11:00:12.201600Z

Thnx.

thheller 2021-01-29T11:00:39.202100Z

(js/document.querySelectorAll ".foo")

p-himik 2021-01-29T11:00:49.202300Z

But what thheller has said will likely bite you later, so you might want to follow his advice as well.

Shantanu Kumar 2021-01-29T11:02:13.202800Z

Dos it also cover things like ".foo li label"? @thheller

thheller 2021-01-29T11:03:05.203Z

yep, pretty much all the same queries (and more) are supported

thheller 2021-01-29T11:03:39.203400Z

it just became a browser standard (a long time ago, so even old browsers support it)

Shantanu Kumar 2021-01-29T11:05:18.204Z

Thanks!

Grigory Shepelev 2021-01-29T11:18:30.204100Z

Thanks a lot. I don't know the workaround yet, but I will most likely share it in this theead.

Grigory Shepelev 2021-01-29T11:25:44.204300Z

I've got it. Changed the view to:

[:div 
 ((get requested-post :content))]
;; note the double parens
and the post itself to:
(def post 
  {:meta {:slug "first-post"}
  ;; UPDATE DOESN'T HAPPEND HERE!
   :content (fn [] [:span (str @d)])})

Grigory Shepelev 2021-01-29T11:26:04.204500Z

Applying directly what you've said. Thanks/

👍 1
clyfe 2021-01-29T11:49:11.206700Z

When using https://clojurescript.org/guides/webpack, with assets https://webpack.js.org/guides/asset-management/#loading-css, is there a way to import './style.css'; from cljs files? Mind you, the goal here is to load 3rd party css.

p-himik 2021-01-29T11:55:31.207Z

Just a guess - you can probably do that with the js* special symbol.

clyfe 2021-01-29T11:59:01.207200Z

I saw a colleague use this js* once, but I found no docs for it since. Any tips?

clyfe 2021-01-29T12:00:17.207400Z

nvm, found (js* "alert('xyz')")

p-himik 2021-01-29T12:01:05.207600Z

Yeah, I usually just look at the sources - cljs/core.cljs or cljs/core.cljc.

clyfe 2021-01-29T12:08:18.207800Z

Whines: "Can't import outside a module". I'll just make a special pack.js where I add all the css, and add it to webpack emit.

jtkdvlp 2021-01-29T14:09:12.208700Z

Hi there 🙂, it seems to me I found a bug in cljs core.async (`clj` works well). Do you guys agree with me? How to report it? The issue:

(cljs.core.async/go
  (println "XXX vorher")     
  (let [old 1
      new „my-new"]
   (println "XXX nacher")
   (println [old new])))

=&gt; „XXX vorher"
=&gt; „XXX nacher"
=&gt; TypeError TypeError: 1.call is not a function
Changing the new symbol to xnew works:
(cljs.core.async/go
  (println "XXX vorher")     
  (let [old 1
      xnew „my-new"]
   (println "XXX nacher")
   (println [old xnew])))

=&gt; „XXX vorher"
=&gt; „XXX nacher"
=&gt; [1 „my-new"]
The following snippet of macroexpanding shows the error I mean. The new for instantiating cljs.core/PersistentVector got resolved with the value I bound to new
...
(clojure.core/let
 [inst_35971
 (println "XXX nacher")
  
 inst_35972
 (. cljs.core/PersistentVector -EMPTY-NODE)
  
 inst_35973
 (js* "[{},{}]" 1 "my-new")
  
 inst_35974
 ("my-new"
  cljs.core/PersistentVector
  nil
  2
  5
  inst_35972
  inst_35973
  nil)
  
 inst_35975
 (println inst_35974)
 state_35977
 …]
…))
So do not use new as symbol! :-$

p-himik 2021-01-29T16:19:28.208900Z

Looks like a bug to me. The right process to report such things is outlined in the first section here: https://clojure.org/dev/creating_tickets

👍 1
teachtyler 2021-01-29T20:21:31.214200Z

has anyone tried to spin up shadow-cljs with 2 build ids where there is :main electron :ui reagent and then a server.cljs file for express-node?

teachtyler 2021-02-01T18:36:13.287800Z

https://github.com/teachtyler/Fraction

teachtyler 2021-02-01T18:38:40.288100Z

I've just been running shadow-cljs watch main ui and then launching the express server from the repl, but i can already tell this is just hacky

teachtyler 2021-01-29T20:22:56.215Z

having issues with express, I might need to rethink my plan

Oliver George 2021-01-29T20:42:02.215400Z

Hands up if you've completed the clojure survey

👍 5
17
Oliver George 2021-01-29T20:42:52.215600Z

Link: https://www.surveymonkey.com/r/clojure2021

thheller 2021-01-29T21:28:05.216900Z

whats the issue? i often have 2 or more builds running

teachtyler 2021-01-29T21:37:39.219900Z

so i actually have 3 builds lol, kinda got it to work by calling my main server within the :main electron file, but this didn't provide HMR because it's just 2 and I was trying to make a 3rd one specifically for express

knubie 2021-01-29T21:37:46.220100Z

I'm seeing some unexpected results when benchmarking transducers: I would expect this: (into [] (comp (map inc) (filter even?)) (take 100000 (repeatedly #(rand-int 2)))) to be faster than this: (-&gt;&gt; (take 100000 (repeatedly #(rand-int 2))) (map inc) (filter even?)) But the transducer version is actually much slower (~30ms vs. 1.5ms)

teachtyler 2021-01-29T21:39:04.220200Z

reading it back doesn't even make sense 😅 I'll push this to github real quick where it was sort of working

clyfe 2021-01-29T21:39:24.220400Z

Extra into there, how about without it?

dpsutton 2021-01-29T21:40:03.220600Z

this is laziness vs realizing a large vector here

🎯 1
dpsutton 2021-01-29T21:40:21.220800Z

the second is doing almost no work. the first form is doing all of the work and constructing a vector around the results to boot

alexmiller 2021-01-29T21:41:01.221100Z

wrap a doall around the second to get apples to apples

knubie 2021-01-29T21:41:09.221300Z

ah, got it

knubie 2021-01-29T21:41:15.221500Z

results make more sense now

knubie 2021-01-29T21:41:18.221700Z

thanks guys