Fork me on GitHub
#beginners
<
2020-09-01
>
sean.poulter01:09:13

Thanks. It seems we have a gap for CLJS.

fabrao02:09:04

hello all, in thread macro execution, is there any way to stop it if any of step fails?

dpsutton02:09:53

do you mean -> or ->>? then no. there is a some-> which can be used in a similar manner if your functions catch exceptions (or whatever your notion of failure) and return nil. it might be worth your time to build a little system similar to either type or something similar

jason35809:09:20

perhaps some of the clojure's monad libs can be of use here?

fabrao02:09:39

ok, I´ll take a look, thank you

zhuxun203:09:34

What is the opposite of async/alt!? That is, how to retrieve a value from the slowest channel of several?

dpsutton03:09:28

doesn't seem possible

dpsutton03:09:54

unless you provide a timeout and at that point you inspect for the last before the timeout?

dpsutton03:09:45

that could be a neat exercise. sounds quite difficult to do and handle edge cases and not arbitrarily wait

zhuxun203:09:09

I see. Then what's the easiest way to implement debouncing? If I have a function work that might return too quickly to put in a loop:

(async/go-loop
  (work)
  (recur))
How do I modify the loop so that each iteration will take at least 1 second? (So that work will not be called more frequently than once per second)

dpsutton03:09:49

and its possible it might take up to a second? Usually these situations you can wait on a timeout channel for a second and recur with the understanding that work usually takes up an incredibly small amount of time

zhuxun203:09:32

No, in this case work can take anywhere from an instant to hours

alexmiller03:09:22

I think debouncing is usually done with one of the buffers that drops

alexmiller03:09:35

like a chan with a sliding-buffer

dpsutton03:09:57

this doesn't sound like a good usage for core.async. If you're arbitrarily blocking you should probably submit this to an executor service. and there are scheduled ones that might handle this for you

alexmiller03:09:29

I assume by debouncing you're in cljs?

alexmiller03:09:26

debouncing is also built into Google Closure library

dpsutton03:09:28

i'm assuming not if (work) could take hours but not sure

zhuxun203:09:45

No I'm in CLJ

zhuxun203:09:50

I came up with this that could work:

(async/go-loop
  (let [ch (async/timeout 1000)]
    (work)
    (<! ch))
  (recur))

dpsutton03:09:19

another thing, if (work) can take hours or return instantly, it seems like perhaps you just wait a second regardless and waiting a second is appropriate if work is instantaneous and completely negligible if work took hours

zhuxun203:09:11

@dpsutton Thanks. What do you mean by "executor service"?

zhuxun203:09:58

Looks promising. So I guess these schedules do not have clojure wrappers and are used with Java interops?

dpsutton03:09:01

correct. but the designers of Clojure have made interop pretty nice and clojure functions implement all of the goodness so that you can just basically (.scheduleWithFixedDelay executor-service work 0 1 TimeUnit/Second)

dpsutton03:09:05

and you now only have to read the javadocs directly and not some wrapper's docs and then the javadocs backing them to figure out what's going on

zhuxun203:09:09

Awesome! Thanks!

nfedyashev06:09:32

Any hints on what might be causing > Caused by: java.lang.IllegalArgumentException: No implementation of method: :urls of protocol: #'clojure.java.classpath/URLClasspath found for class: jdk.internal.loader.ClassLoaders$AppClassLoader are GREATLY appreciated. Trying to avoid posting long stacktrace in this channel, all the context info is in https://github.com/juxt/joplin/issues/117

nfedyashev08:09:59

Looks like I was using the wrong jdk version

joel38016:09:45

(clojure.pprint/pprint 1) => ClassNotFoundException Is this a separate dependency?

joel38016:09:06

works in REPL not in "code"

cattabanks16:09:09

I had this issue earlier and ended up getting it to work by using this`(:use [clojure.pprint :as pp])`

cattabanks16:09:17

Note that :use is frowned upon

seancorfield16:09:07

In an ns form (:require [clojure.pprint :as pp]) (avoid :use -- it refers in every symbol from the namespace, like :refer :all, which is also frowned upon). In the REPL (require '[clojure.pprint :as pp])

alexmiller16:09:26

there are a handful of things that are "auto-referred" in the repl, like pprint

alexmiller16:09:40

in code, you'll need to require them however

joel38016:09:51

thanks, but not clear to me why fully qualified does not work (clojure.pprint/...)

hiredman16:09:14

fully qualified does not cause code to load

hiredman16:09:35

fully qualified only lets you reference code that is already loaded

joel38016:09:29

i see, just used to java handling, was perplexed.

mksybr16:09:39

I expect this to append new entry, but it just resets it to a single :data/:indexes entry

(defn insert  [table record id-key]
  (let [db (read-db)
        new-db {:data {id-key record}
                :indexes [(count (get db :data)) table ]}]
     new-db))

(write-db {})

(write-db (insert :hello {:name :hello :stock 100} 2))

mksybr16:09:12

(write-db (insert :hello {:name :hello :stock 100} 3))
;; => {:data {:hello {:name :hello, :stock 100}}, :indexes [1 :hello]}

(write-db (insert :hello {:name :hello :stock 100} :hello))
;; => {:data {:hello {:name :hello, :stock 100}}, :indexes [1 :hello]}

seancorfield16:09:25

@mksybr What do write-db and read-db do? Also, you can use triple-backticks to format blocks of code to make them easier to read:

Like this block
Is easier to read

mksybr18:09:38

(def memory-db (atom {}))
(defn read-db [] @memory-db)
(defn write-db [new-db]
  (reset! memory-db new-db))

seancorfield18:09:59

@mksybr Since write-db is just resetting the atom to the value it is given, and insert is just returning a single hash map with :data and :indexes, I'm not sure what you expected to happen?

seancorfield18:09:43

new-db in insert doesn't include any of the previous data so your DB isn't going to grow.

seancorfield18:09:17

Perhaps you want write-db to (swap! memory-db merge new-db) instead?

seancorfield18:09:45

Or perhaps insert should return a larger data structure?

seancorfield18:09:57

(you'll also have a race condition if you start using threads, since your insert function could be called multiple times before write-db so multiple :indexes will have the same value of (count (get db :data))