Fork me on GitHub
#clojurescript
<
2019-01-15
>
David Pham16:01:04

Anyone worked with JavaScript promise in ClJS? Is there a good practice on how to bind the value of the promise? I used a global reagent-atom and reset! with the .then method, but is there a better way? I tried core.async channels as well, and was not successful. (I am working with D3.js)

fbielejec18:01:21

wrote a small entry on the topic, along with a macro you might find useful: https://www.blog.nodrama.io/clojurescript-chaining-js-promises-previous-value/

David Pham17:01:10

thanks a lot!

David Pham18:01:57

How do you handle async get request in your code? Do you store the result in an atom? How do you make sure that the atom is not empty?

lilactown18:01:03

@neo2551 this depends a lot on what you're trying to do with the value in your application and the rest of your app's design

lilactown18:01:27

e.g. if you're building an application using reagent, then swapping or reseting an atom might make sense! since your app will re-render when the atom is changed. if you're using other libraries or designs, there might be other ways you'll want to do it

David Pham18:01:36

Ok! Then with reagent and re-frame it makes sense because it will trigger the components that should be updated? :)

David Pham18:01:54

I am sorry for the noob question, I am not extremely confident in async coding lol

lilactown18:01:34

typically, if you're using re-frame, you have an event that triggers the GET request right?

lilactown18:01:36

e.g. a user clicks a button, which dispatch's the [:load-user-details {:user-id 12345}] event or some such

lilactown18:01:33

at that point, you'd configure your :loader-user-details event-fx handler to do the GET request, and then when the data came back, it would dispatch another event with the data that would update your application's app-db

lilactown18:01:46

there's a good intro here for dealing with async in re-frame: https://github.com/Day8/re-frame/blob/master/docs/Talking-To-Servers.md

David Pham18:01:32

Thanks! I will look at it!

David Pham18:01:03

I think I could understand reframe because it was handling the trigger automatically. I was also curious in a lighter environment. Typically, just for reading data and plotting it. But you can’t really avoid side effects then.

jstaab19:01:04

Does anyone have any opinions on https://github.com/dribnet/mrhyde? I use jsonschema a lot in my javascript application, and I'd like to add mrhyde as a way to ease interop with ajv and other js libraries. Is it more trouble than it's worth though? I can imagine a lot of things not working quite right and causing problems.

paul93122420:01:07

Hello, what is the fastest way to do this? : [1 2 3 4 5 8 9 10 14 15 16 18] -> [[1 5] [8 10] [14 16] [18]]?

rutledgepaulv03:01:18

I maintain a library that has a contiguous-by transducer. https://github.com/vodori/missing/blob/develop/src/missing/core.clj#L434-L452 It’s not cljc at the moment but easy enough to copy

rutledgepaulv03:01:44

(miss/contiguous-by identity inc [1 2 3 4 5 8 9 10 14 15 16 18])

john04:01:12

You know, there's an app for that https://re-find.it/

john04:01:35

hmm, didn't work for those inputs. You could fiddle with it though and find interesting functions.

dpsutton20:01:26

you'll probably need to describe some logic guiding your result.

Karol Wójcik20:01:48

Supposing that I want to use antd-design https://github.com/cljsjs/packages/tree/master/antd via cljsjs. Will the advanced compilation trim not used components or do I need to know some magic incantation? Btw does aliasing includes everything? What is preferred :refer or :as?

lilactown20:01:00

no, it will not trim unused components

Karol Wójcik20:01:32

How come? Why people contribute to cljsjs then?

lilactown20:01:18

it used to make it more convenient to use external JS

lilactown20:01:34

nowadays I would use shadow-cljs or the webpack strategy

paul93122420:01:43

From and ordered sequence of numbers I want to gather the intervals.

paul93122420:01:00

It doesnt even work as expected, but it's slow anyway, so are there any ideas how can I sort and group a collection if they are in one sequence, so [1 2 3], but not [1 2 4]?

lilactown20:01:05

assuming they're already in sorted order, I would use reduce but something kinda similar to what you're doing

paul93122420:01:58

on 1400 items it's 66ms, I use it for deciding if reservations are free or full, why is my approach slow? 😄

paul93122420:01:10

I try something with 'reduce', will check back 🙂

dpsutton20:01:30

stateful transducer like partition-all might be a good choice

enforser20:01:15

maybe something like this, but not written as fast:

(defn in-group?
  [prev curr]
  (= 1 (- curr prev)))

(let [r (reduce (fn [m v]
                 (if (or (empty? (:interval m))
                         (in-group? (last (:interval m)) v))
                   (update m :interval (fnil conj []) v)
                   (-> (update m :final (fnil conj []) (:interval m))
                       (dissoc m :interval))))
               {}
               (flatten  [(range 2) (range 4 8) (range 10 15)]))]
  (conj (:final r) (:interval r)))

paul93122420:01:20

@trailcapital Thank you, but unfortunately it is slower than my approach, I can't seem to find the fastest solution 😄

dpsutton21:01:16

@paul931224 use recur rather than an actual recursive call in your example

paul93122421:01:26

@dpsutton how can I reach the previous element in partition-all? I need it for the comparison

paul93122421:01:39

@dpsutton okay, I try it 🙂

dpsutton21:01:58

my idea was to mimic the source of partition-all, not use it. make a stateful transducer with an accumulating array

paul93122421:01:36

it is exactly the same speed with recur 😕

enforser21:01:09

@paul931224 can you share what you're calling to benchmark it?

paul93122421:01:28

well, only (time (my-function the-range))

enforser21:01:55

yeah, I just want to know what range you're passing in, so I can call the same one in my testing

paul93122421:01:17

oh, sorry, I misunderstood. well I make a reservation system where 12:30 is 12*60+30, so I count everything in minutes. I benchmark with a maximal 00:00-00:00 which is (range 1440), and random number of reservations., like [720 780]...

paul93122421:01:09

(concat (range 0 720) (range 780 900) (range 1000 1200)) for example, so no bigger vector than 1440 items

enforser21:01:55

This seems to be a bit faster:

(defn split-interval
  [remainder]
  ((fn f [prev remain]
     (cond
       (empty? remain) [prev]
       (or (nil? prev)
           (= (first remain) (inc prev))) (f (first remain) (rest remain))
       :else [prev remain]))
   nil remainder))

(defn interval-getter []
  ((fn f [total remainder]
     (if (empty? remainder)
       total
       (let [[interval rest] (split-interval remainder)]
         (f (conj total [(first remainder) interval]) rest))))
   []
   items))
With 1500 items, executed 10,000 times repeatedly, mine takes 2s and yours takes 3s on my machine

enforser21:01:30

mine is also getting the right end of the interval 🎆

enforser21:01:54

I got large gains from moving away from recur and loop and using fn with non-tail recursion instead

paul93122422:01:07

@trailcapital I am kind of a beginner, how does the (()) double parentheses work? where do I give my range? 😕

enforser22:01:11

(fn [] ...) defines a function, then to call the function you wrap it in parens, so... ((fn [x] (inc x)) 1) => 2

enforser22:01:24

items is the range 🙂

paul93122422:01:23

@trailcapitalmy bad, Cursive messed up the copied code. It works perfectly and unimaginably fast. Thank you for your help, much appreciated.

👍 5