Fork me on GitHub
#clojurescript
<
2023-07-13
>
emccue00:07:23

Is anyone looking for a medium-large CLJS project?

Kent Bull01:07:36

open source or to work on it?

emccue01:07:56

open source

emccue01:07:38

So this is just bouncing in my head

emccue01:07:57

There are two kinds of build tools

emccue01:07:38

1. The one that just does the stuff (build.sh) 2. The one that has an abstract notion of a "task graph"

emccue01:07:40

and then within 2 there are spectrums of "is this tailored to a single language/platform" and "how much of the properties of the graph is used to do caching, parallelism, etc"

emccue01:07:40

There are a lot of (2)

emccue01:07:56

Buck, Bazel, Gradle, (Maven, Ant), mill etc

emccue01:07:03

The hypothesis is that, instead of representing the task graph in a regular language / DSL or in specialized configuration files - represent it visually

emccue01:07:24

Unreal Engine, the game engine, has a visual scripting system they call "Blueprints"

Kent Bull01:07:09

That sounds a bit, at the abstraction level, like what I understood the Boot build tool to be. Maybe someone just needs to write a UI on top of it.

Kent Bull01:07:14

I could be wrong about Boot.

emccue01:07:29

It is a full language, in a sense

emccue01:07:09

So the idea is to make something similar, but which represents the "task graph" of a build tool explicitly

emccue01:07:42

Why CLJS? Well, the libraries I know of for this (was told about) are react/JS things

emccue01:07:46

and I am in full realization of my inability to make this

emccue01:07:11

This was what I sketched up as a concept last night

emccue01:07:20

Doing stuff like making a Multi Release Jar is very hard with build tools like maven. Feels almost simple if the graph is drawn out and editable

emccue01:07:25

...if that makes sense

emccue01:07:06

I don't think a build tool for CLJ(s,*) is that interesting since for the most part it doesn't seem like we need them

emccue01:07:40

but for java, c, etc. it feels like it would be cool

emccue01:07:56

(some related stuff i've been reading)

emccue01:07:20

but yeah - free project idea

nivekuil03:07:37

ever look at pathom? dependency resolution is easy work for a backward chaining logic engine, just model dependencies as attributes, and it comes with a UI pathom-viz that gets you 90% of the way there

emccue04:07:21

@U797MAJ8M I'm unclear on how pathom relates?

emccue04:07:04

(my brain isn't attuned to the problems of execution so is it maybe that?)

nivekuil05:07:20

> The hypothesis is that, instead of representing the task graph in a regular language / DSL or in specialized configuration files - represent it visually you can represent a task graph in clojure as pathom resolvers -- it is surprising how powerful this abstraction is -- and get much of the visual part for free... but reading it again I think you may just mean parsing some existing data outputted by some tool, and converting that to something a charting library like cytoscape would understand?

emccue14:07:02

I don't expect you to watch the whole thing obv. but this is what i am imagining for the user experience

emccue14:07:42

> you can represent a task graph in clojure as pathom resolvers -- it is surprising how powerful this abstraction is -- and get much of the visual part for free... The point isn't to have code that is introspect-able to make a graph, its to have users engage directly with the visual representation

emccue14:07:42

(~15 min in seems a good point to jump to)

DeepReef1112:07:29

I have a problem calling a value from another file in my entry file. Both files are in main folder. I found this in config, isn't there something else I need to do to be able to reference the other file? ===== shadow-cljs is configured by a shadow-cljs.edn file in your project root directory. You can create a default one by running shadow-cljs init. It should contain a map with some global configuration and a :builds entry for all your builds.

{:source-paths [...]
 :dependencies [...]
 :builds {...}}
An example config could look like this:
{:dependencies
 [[reagent "0.8.0-alpha2"]]

 :source-paths
 ["src"]

 :builds
 {:app {:target :browser
        :output-dir "public/js"
        :asset-path "/js"
        :modules {:main {:entries []}}}}}
The file structure for this example should look like this:
.
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ shadow-cljs.edn
โ””โ”€โ”€ src
    โ””โ”€โ”€ my
        โ””โ”€โ”€ app.cljs
===== If I have (def one 1) in config.cljs, shouldn't I be able to reference it with my.config/one in app.cljs? What else is needed?
.
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ shadow-cljs.edn
โ””โ”€โ”€ src
    โ””โ”€โ”€ my
        โ””โ”€โ”€ app.cljs
        โ””โ”€โ”€ config.cljs

e12:07:27

you need to require your config namespace from inside app namespace

thheller12:07:13

correct, you need (ns (:require [my.config :as cfg])) and then cfg/one.

โœ… 2
DeepReef1112:07:08

Ok, will try that . It is strange because in a project I was referring, it is using the keyword :refer, but it only refer a value in the file yet other stuff is still available. I suppose I'll be able to understand that later

e12:07:38

if you use a fully qualified name like my.app.config/one then it will work if that ns has been loaded for some other reason in the app. but it's not good form to rely on that.

e12:07:06

(the other reason might be eg that another namespace has required it)

โœ… 2
DeepReef1112:07:34

That's what I thought! Thanks

thheller13:07:44

(ns (:require [my.config :refer (one)])) and just one is totally fine too

thheller13:07:28

avoid using full qualified names such as my.config/one in code directly though. you are much better off using alias references (e.g. :as or :refer)

โœ… 2
scarytom15:07:32

Anyone noticed this curiosity with range before? In Clojure, passing a nil as the first arg to range throws NPE, but in ClojureScript it doesn't and odd things can happen:

(range nil 0)
=> ()
(range nil 1)
=> (nil)
(range nil 2)
=> (nil 1)
What's worse is if you have the start and the step both being nil:
(range 0 0 0)
=> ()
(range nil 0 nil)
INTERNAL REPL ERROR: Got an unexpected reply from relay, check Inspect
Timeout while waiting for result.
Evaluates to an infinite seq of nils!
(take 10 (range nil 0 nil))
=> (nil nil nil nil nil nil nil nil nil nil)
๐Ÿ’ฅ

p-himik15:07:58

There are many, many similar instances of undefined behavior.

scarytom15:07:50

worth me raising it as a problem on http://ask.clojure.org do you think?

thheller15:07:07

not really. it all ulitmately comes down on how JS is different to Java

thheller15:07:24

null + 1 is fine in JS, in the JVM it throws

scarytom15:07:26

indeed. this is a little more dangerous because, at least in our case, the unexpected infinite sequence crashes the browser.

madis15:07:12

Hello fellow Clojurians! I'm looking to open REPL connection to #C6N245JGG :node-test build, but when the tests complete, the runtime (node.js process) exists. Do you have recommendations on how to achieve it? I've been looking through shadow-cljs code but haven't found a good way. Also tried couple tricks like listening STDIN, and js/setTimeout (in tests and the runner) but no there either. Or would the solution be to create normal :node-script build with the same files (including test deps and sources) and bind to a port (similar to node.js server, just with test dependencies)?

p-himik15:07:01

For future reference, as you can see by the highlighted #C6N245JGG link, there's a channel for it so it's best to ask such questions there. But no need to move this message that's already been posted.

madis15:07:13

Sorry, I haven't used Slack for long time and thought hashtag was just to mark a topic, but it's a channel reference. Thanks for reminding!

thheller15:07:04

:node-test doesn't support a REPL since the entire point is running the tests and exiting with a non-zero exit code on failing tests

thheller15:07:20

you can create a :node-script build or just use the built-in shadow-cljs node-repl

thheller15:07:43

then just require and run whatever from the REPL

madis15:07:07

Great. Thanks! I'll try both! Shadow-cljs is awesome! If you have a way to donate Bitcoin via Lightning, I'd be happy to support the project

thheller15:07:51

LN looks interesting but I haven't done anything with it yet, so only traditional github sponsors and so on for now ๐Ÿ˜‰

madis15:07:57

If you happen to be on Nostr, I could send you Zaps (SATs via lightning https://nostr.how/en/zaps) (non-custodial). Or https://tippin.me/ is easy too with Twitter (custodial)

thheller15:07:55

nostr is another interesting thing I didn't have time to check out yet ๐Ÿ˜›

thheller15:07:19

too much cool stuff out there

madis15:07:14

Yeah. I'm building some MVP-s of my ideas related to Bitcoin & Lightning using shadow-cljs. Loving it!

๐Ÿ‘ 2
DeepReef1115:07:30

Why I can't assign % to value in let?

(-> (js/logseq.App.getAllPages)
    (.then #(
             do(
                (let [pages %]
                  (println pages))
                ))))
When I remove the let part and just use println %, it works. Error:
Syntax error macroexpanding cljs.core/let.
Call to cljs.core/let did not conform to spec.

p-himik15:07:35

Try properly formatting your code - you'll see why.

p-himik15:07:58

Hint - there's an extra couple of ().

p-himik15:07:53

Oh, wait, never mind. While it would also fail, it would result in a different error - an attempt to call null.

p-himik15:07:15

Are you sure that error comes from that let and not some other? If yes, then there should be more details to that error that show exactly where the spec has failed.

DeepReef1115:07:00

The following gives an error at the let part but is able to println % properly:

(-> (js/logseq.App.getAllPages)
    (.then #(
             do(
                (println %)
                (let [pages %]
                  (println pages))))))

p-himik15:07:20

That should be a different error then - about calling null since you have an extra () after do - you're trying to call the result of (let ...). The macroexpand error happens during compilation and is probably some earlier error that has nothing to do with the above.

DeepReef1115:07:54

Oh, you're right, the error is not related... it was a previous error

DeepReef1115:07:14

I get this error in the app console:

VM421:2 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'call')
    at eval (eval at shadow$cljs$devtools$client$browser$global_eval

p-himik15:07:27

Try #(let [pages %] ...) - you don't need do. And with do it would be

#(do
   (let [...] ...))

DeepReef1115:07:42

So the println called within let is in error

p-himik15:07:36

(println ...) always returns nil. (let [...] (println ...)) also returns nil then. (do ...) evaluates its body and returns the result of the last form. (do (...)) (that you have) calls ... as a function and returns its result. In your case, that ... is (let ...), so you're trying to call nil as a function. Hence why I keep talking about extra () which turn a plain value into a function call.

โœ… 4
DeepReef1115:07:27

Oh I see! Took me long to see it , thanks a lot!

๐Ÿ‘ 2
Mario G19:07:48

I was wondering why clojure.core/future and promise are not translated/available into CLJS. Does anyone know what was the challenge or limitation? Thanks

dpsutton19:07:45

js doesnโ€™t have threads or blocking. So no way for a future to run concurrently and no way for a promise to receive a value and execution to continue

๐Ÿ‘ 2
dpsutton19:07:57

so in

(let [p (promise)]
  (future (Thread/sleep 2000) (deliver p :hi))
  @p)
this kicks off a thread that waits for 2 seconds in the meantime, the current thread continues and dereferences p. That has no value (yet) so it waits. After two seconds the other thread delivers the value :hi to the promise, and the main thread gets its value and continues

leif20:07:34

Reading this, it looks like core.match is still not compatible with the bootstrapped/cljs variant, is that correct? (https://clojure.atlassian.net/browse/MATCH-116)

leif21:07:09

There does seem to be abbinare, but it looks out of date: https://github.com/viebel/abbinare