Fork me on GitHub
#beginners
<
2021-05-03
>
FHE02:05:32

Sorry for the wall of text, but I just want to explain what just happened when I finally got my ClojureScript Quick Start guide program working under WSL2. --- tl;dr The question is: Should I develop CLJS using a Linux-side brower in a VcXsrv X11 window, or in a Windows browser? ---

FHE02:05:08

A crazy (to me at least) thing happened while trying to get my CLJS Quick Start Guide hello world program working on WSL2. When I finally ran my tiny hello-world test program and pointed the Linux browser at localhost:9000, it showed what it was supposed to show (Yay!)....but then this, Windows browser (the one I talking to you in) got hijacked and automatically opened a new tab to localhost:9000 (also with the correct output)!!

FHE02:05:25

When I put a JS alert in the REPL, the alert only pops up in the Linux browser, not the Windows one. Still, though. Utterly surprised it reached out and touched the Windows browser at all. I thought WSL2 (specifically, not the case in WSL1 AFAIK) OS instances were built as if on a separate network/IP. I did not expect localhost:9000 alone to work for the Windows browser side. I was actively deciding to not bother trying to get that working since I had been given advice to just do it all on the WSL2-Linux side. Stranger still is what happened later... The Windows browser I mentioned above is Firefox. The Linux one is Chrome. I just brought a Windows Chrome browser into the mix, and tried pointing that one at localhost:9000 and it works perfectly, displaying the correct page (like the Windows Firefox) but also responding with the JS alerts I put through (unlike the Windows Firefox, but like the Linux Chrome). ...but only one of the Chrome browsers will generate the JS alert, and after some testing it just appears to be whichever browser I more recently hit [F5] (refresh) on!

FHE02:05:13

So...I wasn't trying to get a Windows browser to work for this, and expected that would take some network-fu and was going down the road to getting a Linux browser to work, but...is there any reason I should use the Windows browser instead since it was kind of just dropped into my lap as a possible alternative?

seancorfield02:05:39

I have to say that I have not seen any Windows browser respond to ClojureScript running inside WSL2.

FHE02:05:03

Right? I was floored.

FHE02:05:33

Similar question: Windows Emacs or WSL2 Linux (Ubuntu) Emacs? (either one acting upon program source code files in the WSL2) I went through the process of setting up Doom Emacs on the WSL2 Ubuntu 20.04, but I just realized I could probably simply use my existing Windows Doom Emacs installation to act on the files in the WSL2 file system (in \\wsl$\Ubuntu-20.04 ).

hindol09:05:13

For me, Emacs in WSL2 works much better. If you are facing some issues with the setup, maybe I can help.

hindol09:05:31

I highly recommend Emacs on WSL2 than Emacs on Windows.

hindol09:05:26

The Windows Emacs will be slower on WSL2 files and similarly Emacs on WSL2 will be slower when editing files on the Windows filesystem. So, stick to editing files that are local to that Emacs.

FHE02:05:03

I did not expect to have options for either thing (input (source code editing) or output (browser))!

FHE03:05:42

So I guess now that I have a browser working, I should move on to installing figwheel-main on the WSL2 Ubuntu 20.04?

FHE03:05:20

Or...according to the CLJS Quick Start Guide I might need Node.js? I can't remember if, when I did my tiny webapp under Windows ages ago, I did anything with Node. How important is it? Can I just skip it and move on with installing Figwheel-Main, figuring out CIDER, and figuring out more about deps.edn (and maybe tools.deps IIRC)?

seancorfield05:05:49

I skipped node and used Figwheel. I think if you use Shadow-cljs you kind of have to embrace node and its package manager (you can use Shadow without node, so I'm told, but it's not "normal"). I can't offer an opinion on Emacs/CIDER because I haven't used it for years.

Chandru07:05:24

Hi all. What is a good way to go about building mobile apps using Clojure (or Clojurescript)? Most of the examples focus on Cljs + ReactNative but I also see that re-natal hasn’t been updated in quite sometime (and is supposedly fallen behind ReactNative APIs?).

danieroux07:05:28

"GitHub - vouch-opensource/krell: Simple ClojureScript React Native Tooling" https://github.com/vouch-opensource/krell

Chandru08:05:17

Thanks. Will look into this!

FHE18:05:36

@U9E8C7QRJ The write-up on the git page for krell says shadow-cljs can be used for react native, but I don't see anything to that effect on the git page for (or other things I've read about) shadow-cljs. Do you happen to know how much shadow-cljs actually helps with mobile? (I realize you're not recommending it, though. Ha ha.)

Eric Ihli04:05:25

This might be a little bit outdated now, but it's about a minimal fully-functioning React Native app that's well-documented. https://github.com/eihli/cljs-react-native-starter/blob/master/src/example/core.cljs

Audrius09:05:32

What would be the best way to parse this string -XX:+UseG1GC to 2 tokens: xx and +UseG1GC ? first token between - and : and second is what is left after : . I think there might be a function that does exactly that.

delaguardo09:05:36

regex or some parser combinator library, https://github.com/blancas/kern for example

3
✔️ 3
pavlosmelissinos09:05:48

If - is always going to be the first character, clojure.string/split might also be more than enough (for a quick and dirty solution):

(clojure.string/split (subs "-XX:+UseG1GC" 1) #":")

=> ["XX" "+UseG1GC"]
(clojure.string/split (subs "-XX:+UseG1GC:lala" 1) #":")

=> ["XX" "+UseG1GC" "lala"]
you can even set a limit
(clojure.string/split (subs "-XX:+UseG1GC:alala" 1) #":" 2)

=> ["XX" "+UseG1GC:alala"] 

✔️ 3
jumar10:05:27

Just curious: why are you doing that? 🙂

Audrius10:05:02

I just need to show these parameters in UI. As we can restart the whole app with different JVM start up parameters if needed

Endre Bakken Stovner16:05:57

Is there a way to have Clojure automatically run the latest version of my code? So that whenever I save a file, the code in that file updates whatever is running?

noisesmith16:05:58

there are tools that help with that, eg. tools.namespace/refresh or the ring refresh wrap-reload plugin, but nothing universally adopted

sova-soars-the-sora16:05:24

if you're talking about a web server there is also the wrap-reload middleware

noisesmith16:05:50

thanks - I was thinking of that but forgot the name

noisesmith16:05:59

that's the "ring refresh" I was thinking of

noisesmith16:05:31

there are certain constructs like defmulti and defprotocol that break in weird ways if you just blindly reload on file write

sova-soars-the-sora16:05:42

that's true, certain things get a little kinky with reloading, like if you change a route definition or add a route, i find that sometimes i need to restart the server... but usually it works great if there is no clash

sova-soars-the-sora16:05:13

in clojurescript land shadow-cljs and figwheel will both "hot-reload" code ... a very useful feature for cljs development

noisesmith16:05:13

right - and for any given construct there's a right way to reload that doesn't break things, but just reloading every file in the order saved is never it

Endre Bakken Stovner16:05:38

Will have to look into those, thanks!

noisesmith16:05:38

there are also more heavy handed things in the design domain, like stuartsierra/component or weavejester/integrant which are designed to make apps that always reload correclty (though usually they require you to explicitly reload and don't rely on file change on disk)

noisesmith16:05:14

these definitely have advantages beyond reloadability (like making testing easier, and making it easier to impose a larger scale design of a program)

Endre Bakken Stovner16:05:58

Yes, I really like the look of integrant, but haven't tried it yet. Mount is the one used in luminus so I just went with it :)

noisesmith16:05:17

OK, well mount also has facilities for reload - if you set up your tool to run (mount/stop), then reload your namespaces, then (mount/start), that should take care of everything (as long as you use mount correctly)

🙏 2
noisesmith16:05:53

I don't like mount because instead of resolving things like dependency cycles via data, it cuts the gordian knot and uses globals

2
noisesmith16:05:01

using tools.namespace which I mentioned above

dpsutton16:05:43

and depending on where you are in your journey, asking for things like this could mean that you are missing the benefits of repl driven development. Clojure is kinda designed to have things always up-to-date with a primitive of eval. Re-evaling forms will "update" a live system as you go. Getting used to how the repl works can often make this desire for reload-on-save go away

Endre Bakken Stovner16:05:58

But surely just saving is even less work than sending stuff to the REPL? But you are correct, I am not good with REPL-driven development.

dpsutton16:05:31

kinda. the way many of these things work is that on save, they will look for other namespaces that depend on the saved namespace and refresh all of them by sending all the forms to the repl. So in one sense saving a file is less work, but you want to trigger a lot of work based on saving the file.

noisesmith16:05:50

the act of saving is less work, the things you need to do to verify the state of the code or experiment with the data in context is significantly harder outside a repl based flow - to the degree that many devs don't even end up doing it or replace it with nearly acceptable alternatives like tests or printlns

noisesmith16:05:30

it's just that once you are using the repl to best advantage, the whole reloading files thing becomes much less important

Endre Bakken Stovner16:05:35

I will have to learn it then 🙂 Wish I still had my purelyfunctional subscription, they had a course on REPL-driven development :thumbsup:

noisesmith16:05:53

(and this isn't to say that repl replaces testing, just that people will use tests for the kind of exploritory thing you can do in a repl - which is possible but much more work)

noisesmith16:05:37

actually my one beef with repl driven dev is that it can lead to workflows where people are tempted to skip writing good tests (because hey I verified it worked in the repl right?)

☝️ 2
NoahTheDuke17:05:41

this is my major problem with common lisp (and the CL eco-system). the existing test libraries aren't great and most libraries don't include more than perfunctory tests because of the heavy reliance on developing in the repl

noisesmith17:05:07

yeah, it could be framed as a moral hazard, to borrow a concept from economics

noisesmith17:05:02

(I do have beef with how moral hazard is applied to policy - funny how moral hazards that benefit the poor are never acceptable, and ones that benefit the rich are never articulated...)

dpsutton16:05:55

you took a good stab at that didn't you?

dpsutton16:05:03

creating tests from a repl session?

noisesmith16:05:04

which isn't a problem with rdd itself, just a growing pain of adopting the repl

noisesmith16:05:37

@dpsutton I had some ideas but nothing I'd suggest for mainstream use (maybe with more thought and design, eventually...)

noisesmith16:05:17

I did make a tool that dumps data from an app or repl in a way that can easily be re-inflated from a test, yeah https://github.com/noisesmith/poirot

Ory Band17:05:39

hi. i need to send some http requests. which http client do you recommend? clj-http, http-kit, aleph, other?

NoahTheDuke17:05:36

i've been really happy with http-kit.

Ory Band17:05:41

have you tried any alternative? any specific reason? or was it just the first option you tried that worked fine

Ory Band17:05:05

thanks also

Ory Band17:05:45

i forgot to mention i'm mostly interested in making async http calls

NoahTheDuke18:05:36

it's the one in use when i joined my current project and have stuck with it when doing other things since

🙏 2
sova-soars-the-sora21:05:28

I used http-kit for a long time, it is very nice, but it does not support range queries for streaming audio or video (so the seek bar will work on iOS). So I use ring and a ring middleware some very kind gentleman wrote to support range queries. If you are not hosting / delivering audio or video through your website then http-kit is fine, if you need to, consider using ring with the range query middleware.

GGfpc19:05:24

Is there any way I can see the request body sent by http kit?

phronmophobic20:05:27

there’s a number of different ways to work with the request body. :as text is probably the most straightforward, but it depends on your use case

GGfpc20:05:00

Sorry, I'm not sure if I made it clear. I want to see the body that I'm sending

GGfpc20:05:07

to make sure it's formatted correctly

phronmophobic20:05:29

the way I would do that is with netcat, nc In terminal

nc -l 1234 > request.body
Then send a request to "http://localhost:1234/myreq"

phronmophobic20:05:22

that will write the request body to the file named request.body

sova-soars-the-sora21:05:34

Super groovy cartoon movie

GGfpc18:05:59

both options worked perfect, thanks 🙂

borkdude20:05:15

FWIW babashka also comes with httpkit, both client and server. It's a quick way to test it out if you're interested in trying the lib.

👌 3
raspasov04:05:20

That’s pretty neat.

borkdude20:05:53

A quick way to see both the request body and response is to launch the server and fire a request at it with the client:

$ bb -e '(org.httpkit.server/run-server (fn [r] (clojure.pprint/pprint r))) @(org.httpkit.client/get "")'
\cc @ggfpc12495

sova-soars-the-sora21:05:28

I used http-kit for a long time, it is very nice, but it does not support range queries for streaming audio or video (so the seek bar will work on iOS). So I use ring and a ring middleware some very kind gentleman wrote to support range queries. If you are not hosting / delivering audio or video through your website then http-kit is fine, if you need to, consider using ring with the range query middleware.

leif21:05:55

Is there anything like dynamic-wind in clojure(script)? (Where code will run, even if the scope is left via an exception.)

andy.fingerhut21:05:41

Something besides try / catch you mean?

leif21:05:55

Yes, because I don't want to intercept any exceptions, just reset an atom on the way out.

noisesmith21:05:03

I think dynamic wind is more like try / finally(?)

noisesmith21:05:31

it's not about catching, but rather ensuring your finally block always runs, regardless of code path / errors, right?

leif21:05:35

Close, it's more like try/catch(e)->rethrow-e/finally

andy.fingerhut21:05:14

I think noisesmith might be right that try with no catch, only a finally, will propagate the exception, but still run your finally code on the way out.

noisesmith21:05:27

cljs.user=> (try (throw (js/Error.)) (finally (print "OK")))
OK
Execution error (Error) at (<cljs repl>:1).
looks like a start at least

leif21:05:31

unless a try/finally block doesn't intercept exceptions?

noisesmith21:05:55

throw followed by finally seems odd

noisesmith21:05:55

a throw is saying your code block is done for good

leif21:05:59

Oh yes, you're right, that works.

noisesmith22:05:28

right, without catch the exception does what it would have otherwise, it's just that your finally clause runs too

leif22:05:01

Cool, thanks. 🙂

noisesmith22:05:14

try/finally is how locking ensures correctness in clj for example (no need for this in cljs with no threading)

borkdude22:05:11

also thread bindings are managed this way to ensure they are unwinded after the binding expression, there are more examples of this, probably with-open too

leif22:05:25

Makes sense, thanks. 🙂

leif21:05:20

Alternatively, is there anything like reset! , but only inside of a lexical scope?

Adrian Aleixandre23:05:12

Hey does anyone have experience with https://github.com/binaryage/chromex? I am having trouble extending the js/clojure marshalling system and could use some help! How do I go about extending the gen-marshalling config?