Fork me on GitHub
#clojurescript
<
2023-01-05
>
sjharms07:01:51

If I use (p/let [_ (long-running) _ _(long-running_ ...]) it works well, but is there a way if I had repeated tasks I could use (p/let [_ (dotimes [_ 5] (long-running)]) instead? I have tried a few different versions but they all appear to exit without waiting for the promise to be resolved

thheller07:01:49

dotimes returns nil so the p/let has no promise it can await

moe07:01:03

You probably want something like (p/let [... (apply p/all (repeatedly 5 long-running))] ...). repeatedly may not be exactly what you're looking for, but it sounds like you want a promesa/all around whatever sequence you're building

moe07:01:01

(but yeah, you have to build a sequence)

sjharms15:01:04

Ah ok let me give that a shot thank you

sjharms15:01:42

It looks like that doesn't work either, apply says p/all isn't a function, and I can't wrap it in p/all either or it still doesn't wait for the return

moe15:01:22

it's a function, i promesa

😆 2
sjharms16:01:55

I think the problem is I am trying to wrap multiple steps inside an anonymous function ie #(do (long-1) (long-2) ...) and it only waits for the last one, maybe I need to wrap those all in ->

moe16:01:52

no, you really do want (p/all [(long-1) (long-2) ..)

sjharms16:01:23

Yeah I just need to somehow wrap those two long calls in a repeatedly or for loop

sjharms16:01:32

Cut and pasting them works file, it just feels a little silly

sjharms16:01:35

This almost works: (p/let [... _ (repeatedly 5 (p/-> (long-1) (long-2))]) I am just now getting "Cannot read properties of undefined (reading long-1)" error message

moe16:01:24

dude that code is so far away from working

moe16:01:47

You need p/all

moe16:01:44

(repeatedly takes a function, you're not passing it one, the semantics of p/-> aren't what you want, even if were passing it a function, repeatedly returns a sequence, which p/let can't await on, unless it's wrapped in p/all, etc.

moe16:01:48

It's not clear what you're trying to do. If you have n distinct functions, then you want (p/let [x (p/all [(long-1) (long-2) ...])] ...) . if you have n distinct parameters, you want e.g. (p/let [x (p/all (for [i (range 10)] [(long n)))] ...) if you want to call the same function n times, you want (p/let [x (p/all (repeatedly 10 long-n))] ...

sjharms16:01:12

This is super helpful I am just re-reading this thread and comparing it with the code to connect those dots in my head

sjharms17:01:33

I have this but it doesn't wait as long as I would expect (I have each call waiting on a 1 sec timeout and all of them together appear to only wait 1 sec):

(p/let [_ (apply p/all [(take 10 (cycle [#(long-1) #(long-2)]))])])

moe17:01:00

you don't need the apply

moe17:01:48

but the behaviour you describe is what you should expect

moe17:01:10

the promises are being resolved concurrently

sjharms17:01:21

Ah I want them to be sequential

sjharms17:01:00

I just tried the reduce - chain but that didn't appear to wait, and I also tried a p/do but it throws an error because its a macro and not a function

moe17:01:26

yeah that was a janky suggestion, i'll give you something better once i'm off the phone

moe17:01:39

(reduce p/then (p/resolved nil) (take 10 (cycle [long-1 long-2))])

moe17:01:44

something like that

sjharms17:01:09

That worked thank you for sticking with me through this thread, very educational

sjharms17:01:07

If I were to rephrase this solution, is this correct? Starting with a unresolved promise, take the list of functions and chain them with 'then'

moe17:01:27

starting with a resolved promise

moe17:01:07

just to act as the initial value for reduce, so you don't have to invoke any of your functions yourself

thanks 2
Yimika08:01:24

This code that removes accents from string works in Clojurescript

(defn remove-accents [s]
    (let [normalize-fn (js/String.prototype.normalize)
          accent-re (js/RegExp. "\\p{M}")]
      (str/replace (normalize-fn.call s "NFD") accent-re "")))
however, shadow-cljs throws this error, likely because of normalize-fn.call? TypeError: Cannot read properties of undefined (reading 'cljs$core$IFn$_invoke$arity$2') Does anyone have an idea how to fix it?

p-himik08:01:43

Why would you write it like that? Why not just (.normalize s "NFD")?

p-himik08:01:59

Also, I doubt that it works in plain CLJS - (js/String.prototype.normalize) calls String.prototype.normalize with no arguments, so it returns an empty string.

Yimika08:01:21

I doubt this changes the string (.normalize s "NFD")

Yimika08:01:18

(remove-accents "Joãn") works pretty good

p-himik08:01:19

What do you mean by "I doubt this changes the string"?

p-himik08:01:09

This is plain CLJS, without any tools:

cljs.user=> (require '[clojure.string :as str])
nil
(defn remove-accents [s]
    (let [normalize-fn (js/String.prototype.normalize)
          accent-re (js/RegExp. "\\p{M}")]
      (str/replace (normalize-fn.call s "NFD") accent-re "")))
#'cljs.user/remove-accents
cljs.user=> (remove-accents "Joãn")
Execution error (TypeError) at (<cljs repl>:1).
Cannot read properties of undefined (reading 'call')
It doesn't work for exactly the reason I've described. In you case it works because your implementation of remove-accents is different. Maybe it's cached, maybe it comes from a different namespace, maybe it wasn't hot code reloaded, maybe something else.

Yimika08:01:51

The reason it might not work in your environment might probably be your javascript version or clojurescript version, but it does work perfectly in my environment, the issue is that on my browser, shadow-cljs throws that error

p-himik08:01:29

It's not shadow-cljs, it's JS that throws that error.

p-himik08:01:22

As I said, your code cannot work, unless your version of JS is doing something horrible. Or maybe something has overwritten String.prototype.normalize to be a function of no arguments that returns the actual normalize function.

p-himik08:01:13

(js/String.prototype.normalize) in CLJS compiles to String.prototype.normalize() in JS. That's true regardless of the version of CLJS or JS and of the tools that you're using. And using String.prototype.normalize() just doesn't make sense. It returns an empty string, not a function.

Yimika09:01:11

Oops, you are correct, there was conflict i was using the hardcoded, conflict on my repl

(defn remove-accents
  "remove accented letters"
  [s]
  (let [accent-map {"á" "a" "é" "e" "í" "i" "ó" "o" "ú" "u" "ñ" "n" "ä" "a"
                    "Á" "A" "É" "E" "Í" "I" "Ó" "O" "Ú" "U" "Ñ" "N" "Ä" "A"
                    "à" "a" "è" "e" "ì" "i" "ò" "o" "ù" "u" "À" "A" "È" "E" "Ì" "I" "Ò" "O" "Ù" "U"
                    "â" "a" "ê" "e" "î" "i" "ô" "o" "û" "u" "Â" "A" "Ê" "E" "Î" "I" "Ô" "O" "Û" "U"
                    "ã" "a" "õ" "o" "Ã" "A" "Õ" "O"
                    "ç" "c" "Ç" "C"
                    "đ" "d" "Đ" "D"
                    "ğ" "g" "Ğ" "G"
                    "ı" "i" "İ" "I"
                    "ł" "l" "Ł" "L"
                    "ń" "n" "Ń" "N"
                    "ø" "o" "Ø" "O"
                    "ş" "s" "Ş" "S"
                    "þ" "th" "Þ" "TH"
                    "ü" "u" "Ü" "U"
                    "œ" "oe" "Œ" "OE"
                    "æ" "ae" "Æ" "AE"}]
    (apply str (map (fn [c] (get accent-map c c)) s))))

👍 2
Yimika09:01:02

But still (.normalize "Joãn" "NFD") returns => "Joãn"

p-himik09:01:33

That's because you need more than just normalization - you also need replacement.

Yimika09:01:10

I tried replacement, still returns the same string

p-himik09:01:01

Perhaps the regex is not the right one. But nothing to do with CLJS.

p-himik09:01:21

Yeah, you gotta use the u flag. This works in JS:

"Joãn".normalize("NFD").replace(/\p{M}/gu, '')
The g flag is not exactly required but is probably something that you'd want to have there.

p-himik09:01:37

However, neither NFD nor NFKD seem to decompose œ, for whatever reason.

pbaille18:01:12

Hello, I was wondering how would it be possible to obtain the list of all types that implement a given protocol.

;; something like this

(implementers ISeqable)
;=> (ArrayNodeSeq BlackNode ChunkedCons ...) 

dnolen18:01:25

Probably by inspecting the compilation environment - can’t be done at runtime

pbaille18:01:22

Thank you, yes, compile time is ok for what I'm trying to do. Should I try to use cljs.analyzer.api for this ?

souenzzo18:01:44

I think that you can use #CHY97NXE2 :analysis API.

pbaille18:01:32

Thank you, nice to know !

Dallas Surewood23:01:45

How are people doing routing? Cause ClojureScript secretary seems to be abandoned, and I can't do a /:id url without it erroring out

Dallas Surewood00:01:46

I actually found that article while I was looking! Working on setting it up now