clojurescript

Taoufik Dachraoui 2022-01-20T11:10:56.175200Z

Hi,

Taoufik Dachraoui 2022-01-20T11:12:11.176300Z

I designed and implemented a new framework Ankbit Application Server, please have a look and any suggestions are welcome: https://www.youtube.com/watch?v=UPyEosj5zpY

🎉 1
emccue 2022-01-25T18:34:05.232300Z

That looks really, really cool

Nazral 2022-01-20T11:17:41.176800Z

is it possible to use definterface in clojurescript? Or something equivalent?

Nazral 2022-01-21T16:53:36.207200Z

Seems like it is working, thanks again !

👍 1
p-himik 2022-01-20T11:47:11.177100Z

The underlying platform, JavaScript, has no interfaces, so no. What's the real problem you're trying to solve?

Nazral 2022-01-20T12:10:42.177300Z

@p-himik porting clojure code heavily relying on interfaces to clojurescript

p-himik 2022-01-20T12:19:42.177500Z

Then it depends on why exactly a particular interface is used at a particular place. There are workarounds but I'm pretty sure there's no one specific workaround that would let you have all the things interfaces enable at once.

Nazral 2022-01-20T12:24:13.177700Z

essentially there is a (definterface Foo (bar [x])) then a (deftype NFoo [^Foo y] Foo (bar [x] ...)) , and NFoo is used in many places with calls like (.bar nfoo somevariable)

p-himik 2022-01-20T12:50:47.177900Z

I see. Usually people use protocols for that. But if you need an interface just to be able to use the dot form, then you can use Object instead:

=> (deftype X [] Object (bar [_] (println "bar")))
cljs.user/X
=> (.bar (X.))
bar
nil

Nazral 2022-01-20T12:58:31.178100Z

Thanks for the help, I'll try that !

👍 1
2022-01-20T14:35:36.180200Z

Hi! I have an odd issue where seemingly one core fn cannot be resolved, but others seem to work just fine. In this case all-ns gives an error of Use of undeclared Var app.components.icon/all-ns even though all-ns is supposed to be a clojure core function. Has anyone ever stumbled upon this and knows what I’m missing?

jkxyz 2022-01-20T14:50:07.180500Z

You can't do runtime inspection of namespaces in ClojureScript because they get compiled away. So functions like all-ns don't exist in cljs.core.

jkxyz 2022-01-20T15:18:43.180700Z

But I think you can get namespace data in macros using the analyzer: https://cljs.github.io/api/compiler/cljs.analyzer.api/#all-ns

octahedrion 2022-01-20T15:27:36.187200Z

I haven't done any CLJS work for a while. What's the best way to use JS libs these days ? As far as I can tell: • shadow-cljs is the best for npm-installed dependencies, but doesn't have any obvious way to list those dependencies in your deps.edn or elsewhere so how do you know what npm dependencies the project depends on ? • CLJSJS allows you to list your dependencies in deps.edn, which I like because I like to see what all my dependencies are, but CLJSJS is out of date with most libs and requires quite a bit of work to add new dependencies (forking etc) • :foreign-libs is simple and you can see the dependencies, but you have to download them yourself, a minor inconvenience

octahedrion 2022-01-21T09:18:46.200400Z

In the JS world it seems, as in the Python world, you install libs without reference to a version or namespace. In the Clojure world we specify libs by namespaced library name and version. It's this dichotomy which concerns me

p-himik 2022-01-21T09:28:26.201Z

That's incorrect - you do specify versions, both in the JS and in the Python world, but they are optional when you install something. By default, npm and yarn will simply use the latest release version if you omit it during installation, but the version must be present in package.json. There are two differences between JS and CLJS here though: • You have to install packages manually (there's no global analog to the .m2 folder, all node_modules are project-specific and are populated when you run the installation command) • Due to how version resolution works, there's an extra package-lock.json file that's necessary. You don't alter it manually but you do put it in your repo. During development, you use regular npm i which will change the lock file, during deployment you use npm ci which will use the lock file to ensure same exact versions are being used

thheller 2022-01-21T09:46:17.201300Z

just to expand why you must keep the lock file. in npm it is very very common to use version ranges when declaring dependencies, most libraries do this. so even if you specify to depend on lib-a with exactly version 2.0.0, that lib may depend on lib-b version ^4.0.0. which basically means 4.0.0 or anything newer. so without a lockfile if you run install again you'll never know what you get. the lockfile ensures you always get the same.

thheller 2022-01-21T09:47:40.201500Z

otherwise it is not uncommon to end up with lib-b version 4.5.0 that broke lib-a in some way and now you entire thing is broken. lockfiles save you at least that headache.

octahedrion 2022-01-21T10:29:48.201700Z

@p-himik yes but think of the difference between what you do when you want to use a Clojure lib vs a Python/JS lib when you read the github page: for Clojure you will see a namespaced library name and version number x.y.z/lib-name {:mvn/version "a.b.c"} to paste into your deps.edn whereas for Python/JS you will see npm install lib-name or pip install lib-name

p-himik 2022-01-21T10:31:54.201900Z

It's not a namespace, it's a group. It's just a way to make names more unique, that's all. JS is slowly moving in that direction as well. And yes, you don't have to specify versions when installing a JS/Python lib. But you can if you want to.

octahedrion 2022-01-21T10:32:50.202100Z

uhh in Maven terms it's a group, in Clojure terms that symbol's namespace!

octahedrion 2022-01-21T10:33:55.202300Z

(namespace 'org.clojure/clojure)
=> "org.clojure"

octahedrion 2022-01-21T10:35:17.202900Z

anyway zoom out - I'm talking about the difference in development process here

p-himik 2022-01-21T10:35:59.203100Z

For symbols - yes. :) But we're in the context of dependencies. Library org.clojure/clojure is a library with name clojure that belongs to a group named org.clojure. Symbol org.clojure/clojure has name clojure and namespace org.clojure. The fact that at least deps.edn and project.clj represent library names as symbols is not central here.

octahedrion 2022-01-21T10:36:37.203300Z

yes yes I know

octahedrion 2022-01-21T10:36:47.203500Z

can we talk about the actual point of the thread

p-himik 2022-01-21T10:38:17.203700Z

FWIW, from my perspective the main points have been exhausted.

octahedrion 2022-01-21T10:39:23.203900Z

ok no need to reply then

octahedrion 2022-01-21T10:44:24.204100Z

maybe it would help if I put it this way: if you had the choice between the Clojure way of managing dependencies (`deps.edn`) and the JS way, which would you choose for JS dependencies in CLJS projects ? If you could use the Clojure method would you ?

p-himik 2022-01-21T10:52:24.204400Z

Before answering that question, I would have to read up quite a bit on how exactly NPM does its thing, decide on what the implications of any potential changes to those algorithms are, study the implementation of the CLJ solution for JS dependencies, and assess how much of a risk using it would be. Given that I don't really want to do all that and that using NPM is perfectly fine the vast majority of the time, realistically I would probably wait for a good few years and study other people's experiences and analyses before adopting such a solution.

p-himik 2022-01-21T10:55:20.204600Z

And if that CLJ mechanism for JS dependencies is CLJSJS then the answer is a definite "no". I used to use it ~4 years ago or so, and I'm glad I've stopped.

thheller 2022-01-21T13:41:26.205100Z

@octo221 that is a pointless question. we gotta use what is available, not what we wish was available. we provided a lot of information, you can make your own choice. FWIW compare the "dependencies" of package.json and :deps in deps.edn and they'll look very similar. no difference if you ask me.

p-himik 2022-01-21T14:05:17.205300Z

I think that question has merit - if I were willing to put time and effort into improving the situation by creating new tools, I would've probably asked the same question. After all, you yourself created a new tool at some point - you didn't settle on what was available. :)

thheller 2022-01-21T14:28:26.205500Z

well sure that is always an option too 😉

thheller 2022-01-21T14:47:51.205700Z

but note that the problem here really isn't in the tool. it is the entire ecosystem. if nobody was using version ranges you'd have a similar setup as in maven.

p-himik 2022-01-21T14:54:37.205900Z

But hypothetically, can't a tool treat a range as a fixed Maven-like version?

thheller 2022-01-21T15:27:38.206300Z

no? maven also has ranges, just nobody uses them because they are bad

thheller 2022-01-21T15:28:11.206500Z

also npm has different conflict resolution strategy. that would also need to change. really you have to replace all of npm to make any meaningful change 😛

p-himik 2022-01-21T17:37:27.207600Z

Ah, of course! Thanks. I managed to completely forget that Maven supports ranges. 😅

Derek 2022-01-20T15:29:46.187300Z

For your shadow-cljs bullet point, the NPM dependencies would be in your package.json and accompanying lock file (package-lock.json or yarn.lock)

octahedrion 2022-01-20T15:33:22.187500Z

I'd prefer to keep matters as much under Clojure's control as possible though

Derek 2022-01-20T15:35:04.187700Z

Not sure if still applicable but I’ve seen https://github.com/RyanMcG/lein-npm in the wild

octahedrion 2022-01-20T15:35:22.187900Z

I'm using deps.edn

Drew Verlee 2022-01-20T15:35:35.188100Z

shadow-cljs.edn can reference a deps.edn

Drew Verlee 2022-01-20T15:36:18.188400Z

It makes some things harder though and is only worth if your using some other tooling in and around deps.edn, but it's not a big switch back and forth.

p-himik 2022-01-20T15:43:10.188700Z

I always go with your first point. Managing JS dependencies should be done via JS tools. Otherwise it's a constant gamble on whether whatever mechanism you're using is recent enough to keep up with the current state of affairs in the JS world.

thheller 2022-01-20T19:05:22.195500Z

IMHO the only viable option is to use the npm packages directly and keeping your package.json + lockfile in version control. whether thats npm or yarn doesn't matter much. also whether you let shadow-cljs handle the JS or something like webpack doesn't matter much either, your choice there

thheller 2022-01-20T19:06:14.195700Z

one thing almost guaranteed to get you in trouble is ignoring package.json + lockfile and trying to "hide" them with something like lein-npm or similar stuff

2022-01-20T16:28:47.194400Z

Hi, I have kind of an odd issue. I’m currently using a component library that has a dialog trigger which is a button under the hood. You can pass a prop called as-child:true which will merge all props into the child component. However, if you have another component as the child, it doesn’t seem to work. This works fine in React, so I’m wondering if I’m missing something. Here’s a simple example, and https://www.radix-ui.com/docs/primitives/components/dialog

(defn dialog [children]
  [:> Dialog
   [:> DialogTrigger {:as-child true :aria-label "Placeholder"}
    children]])

(defn share-dialog []
  [dialog
    [button {:class "bg-black text-white"} "Open"]])

2022-01-28T21:36:19.330379Z

this is what we’ve had to do lol.. it’s still not perfect as it fails with other radix components, but very close

2022-01-28T21:39:59.772439Z

hoping there’s an easier way at this point

Drew Verlee 2022-01-22T05:29:37.208100Z

What is compiling that code into react? It might need to to pass a js object not a clojure hashmap. Are there errors?

lilactown 2022-01-20T17:04:36.194700Z

try calling reagent.core/as-element on children before it's passed to the DialogTrigger

👀 1
2022-01-20T17:09:26.195Z

no luck

lilactown 2022-01-20T17:11:52.195200Z

hmm not sure then.

2022-01-20T19:14:05.195900Z

So, since a HTML <button> works with it. It’s probably that I need a way to pass props into <Button> with something like a forwardRef

2022-01-20T21:29:48.198800Z

Hi all, using the latest clojurescript, set up according to the quick start, I'm getting warnings when using goog.labs.userAgent.browser . Any idea why this is happening?

(require '[goog.labs.userAgent.browser :as gbrowser])
;; => nil
(gbrowser/isChrome)
;; WARNING: Use of undeclared Var goog.labs.userAgent.browser/isChrome at line 1 <cljs repl>
;; => true
It's interesting that I get the warning, but then the function works just fine. Note that in a project more complicated than a quick start this is causing builds to fail.

2022-01-20T21:42:16.199100Z

^ nvm, already reported at https://clojure.atlassian.net/browse/CLJS-3344