clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
zackteo 2020-09-15T03:18:16.399100Z

Hi guys, I have this project https://istd50043.github.io/project#implementation-requirements I'm trying to consider the possibility of doing this solo (so that I can do Clojure full stack) I'm thinking the "Production System" can be done with Clojurescript. "Analytics System" can be done with Clojure. But I also need to do automation scripts for AWS - not sure how possible is it to do this with babashka :o I know might be pretty intense to tackle alone. But am wondering how intense/possible is it :x (Also not sure if this is the best channel for this)

dpritchett 2020-09-15T16:17:33.423700Z

For simpler shell scripts you might consider using #joker and wrapping the AWS CLI tool rather than importing the AWS SDK into your clojure of choice.

dpritchett 2020-09-15T16:18:14.423900Z

example

seancorfield 2020-09-15T03:34:05.400400Z

@zackteo If you're not already a member, I suspect the #aws and maybe #aws-lambda channels will be helpful to you. I don't know if there are channels specific to automating ops stuff on AWS.

zackteo 2020-09-15T03:34:34.401Z

In that case, I'll move this there

seancorfield 2020-09-15T03:36:26.402800Z

It's a big enough project that different parts of it will likely be best served by asking questions in several different channels but I think some of the core questions about AWS will need answering first and those are almost certainly "non-Clojure" questions. I think it's an interesting project and should be a good challenge.

zackteo 2020-09-15T03:38:10.406600Z

I think it will be very good for me to attempt to tackle it myself. Especially with groups you end up missing out on learning the different parts. But the wonder is will it be too overwhelming a task that it would be better to take a step back

seancorfield 2020-09-15T03:38:13.406700Z

There are some Clojure-based projects for managing AWS ops stuff (Pallet comes to mind, there's a #dda-pallet but I don't know how active it is) but I'm not sure how active any of those ops projects are. I think people went back to more mainstream tech for that sort of thing?

borkdude 2020-09-15T06:37:19.408300Z

@zackteo aws is a recurring topic in #babashka - welcome to join and thinking about it

zackteo 2020-09-15T06:53:20.408900Z

@borkdude will do! 🙂

Ivar Refsdal 2020-09-15T08:07:17.409100Z

I ended up rolling my own mini library: https://github.com/ivarref/memoize-ttl

zackteo 2020-09-15T09:23:58.411200Z

@seancorfield am gonna do the project in Clojure after all! :D I miraculously found 2 peers to join me to form a 3 man team :) so it isnt as ridiculously daunting anymore

21🎉
2020-09-15T13:16:13.413500Z

What would be the best way to organize such a program in clojure ? I want to concurrently build a set of unique things existing across a cluster of "locations" (DBs in reality). Let's say for simplification that I have an expensive func (get-ids location) which might take a while to return. I have a list of locations, say a few thousands of them, and I want to share the load of calling get-ids for each of them, across, say, 16 workers, and finally get a unique set of values out of this. I have to limit the number of concurrent workers because in effect, each worker opens a connection.

2020-09-15T13:17:19.414700Z

Tried my way around with pipeline but ended up having bloated parts to rebuild the final list of results out of channels that I'm not sure they're done fetching.

jsyrjala 2020-09-15T13:18:39.414800Z

https://github.com/TheClimateCorporation/claypoole

2020-09-15T13:20:51.415100Z

that looks great! thanks

2020-09-15T13:21:51.415600Z

just out of curiosity, how would you go about organizing such a thing with the core libs, as in, for an ad-hoc solution for a one time problem?

benoit 2020-09-15T13:22:59.416800Z

I would write a pipeline that fetches the location in a thread pool or asynchronously and plug the distinct transducer on the output channel.

2020-09-15T13:25:42.416900Z

I think I went more or less that way, wasn't sure how to ensure my output channel gave me all expected results though

2020-09-15T13:26:21.417200Z

(so I could dump my final list to a file and exit the program)

benoit 2020-09-15T13:30:12.417400Z

If you close your input channel after posting your locations, the pipeline-blocking function will close your destination channel.

benoit 2020-09-15T13:31:16.417600Z

So when your code detects that the destination channel closes, you can assume that you have the complete set of ids and can dump them in the file.

2020-09-15T13:33:51.417900Z

ah yes, good idea

benoit 2020-09-15T13:33:55.418100Z

And if you build your input-channel with to-chan on the collection of locations. you don't even have to bother closing this input channel, it will be done automatically.

2020-09-15T13:35:12.418300Z

would you assume that the chan is closed when you're taking nils out of it ?

benoit 2020-09-15T13:35:21.418500Z

yes

2020-09-15T13:35:40.418700Z

yep, feels weird but makes sense, thanks a lot

jsyrjala 2020-09-15T13:36:57.418900Z

My first attempt would be something like this

jsyrjala 2020-09-15T13:37:06.419100Z

(require '[com.climate.claypoole :as cp])
(let [adresses [address1 address2 address3]]
  (cp/upmap 10 (fn [address] (connect-address address)) addresses))

2020-09-15T13:38:08.419300Z

yep ok, using claypoole then, Tbf it looks simple enough to be pulled in, thanks

alexmiller 2020-09-15T13:58:33.419500Z

nil is not an allowed value in a chan

alexmiller 2020-09-15T13:58:42.419700Z

so if you take and get a nil, you know the chan is closed and drained

1👍
nivekuil 2020-09-15T16:04:24.420100Z

what's a good way to express "at least 2" elements in a sequence? I believe count will traverse an entire seq?

2020-09-15T16:06:56.420600Z

you can use bounded-count

2020-09-15T16:09:01.422300Z

bounded-count came from one recent release, if you have older clojure, you can use simply (->> x (take 2) count)

nivekuil 2020-09-15T16:09:56.422700Z

oh, cool thanks :) tbh I wish there were a many? in clojure.core that did this; I find myself having to sprinkle this around in a few places for UI-related stuff since we humans like our grammatical numbers

2020-09-15T16:11:20.423400Z

it seems that nobody else needs it

Joe Lane 2020-09-15T16:11:27.423600Z

Might also be worth looking at https://clojuredocs.org/clojure.pprint/cl-format

dpritchett 2020-09-15T16:17:33.423700Z

For simpler shell scripts you might consider using #joker and wrapping the AWS CLI tool rather than importing the AWS SDK into your clojure of choice.

dpritchett 2020-09-15T16:18:14.423900Z

example

nivekuil 2020-09-15T16:38:46.424700Z

actually, (count (range ..)) appears to be constant time in cljs, so it seems to always be ďżą~ďżą4x faster to use count instead of bounded-count there -- not that it's meaningfully slow either way, at about 25 nanos for bounded-count according to simple-benchmark.

dpsutton 2020-09-15T16:44:15.425100Z

range implements ICounted so it will be constant time

alexmiller 2020-09-15T16:44:39.425600Z

not necessarily

alexmiller 2020-09-15T16:44:49.426Z

only finite long ranges

dpsutton 2020-09-15T16:44:50.426100Z

ICounted
  (-count [rng]
    (Math/ceil (/ (- end start) step)))

dpsutton 2020-09-15T16:44:54.426300Z

(cljs)

alexmiller 2020-09-15T16:45:09.426700Z

infinite ranges obvs can't be ICounted

dpsutton 2020-09-15T16:46:05.427500Z

its nonsensical but it works

(count (range))
1.7976931348623157e+308

alexmiller 2020-09-15T16:46:27.427800Z

if "works" = wrong :)

dpsutton 2020-09-15T16:47:07.428400Z

yes. in cljs it seems they are never infinite. ([] (range 0 (.-MAX_VALUE js/Number) 1))

dpsutton 2020-09-15T16:47:38.429Z

never delved into this before so fun to learn

alexmiller 2020-09-15T16:47:41.429200Z

I mean, technically even in Clojure counting is int-bounded due to Java collection apis right now

isak 2020-09-15T16:51:12.429900Z

Would tell you guys what it returns in babashka, but still waiting for the answer

dpsutton 2020-09-15T16:52:13.430700Z

ah, the clojure version of (range) is (iterate inc 0) which obviously won't implement Counted whereas the "infinite" version of (range) in cljs does

alexmiller 2020-09-15T16:52:34.431Z

also, the non-long version of range in Clojure does not implement ICounted

alexmiller 2020-09-15T16:52:44.431400Z

as there are many weird edge cases

dpsutton 2020-09-15T16:52:56.431700Z

yeah i remember you saying you spent a lot of work in there

dpsutton 2020-09-15T16:53:16.432100Z

thanks for that tedious work 🙂

alexmiller 2020-09-15T16:53:46.432400Z

user=> (counted? (range 0.0 10.0))
false
user=> (counted? (range 0 10))
true

nivekuil 2020-09-15T16:55:25.432500Z

user> (counted? '(1 2 3)) true user> (counted? `(1 2 3)) false

nivekuil 2020-09-15T16:55:30.432600Z

that I really don't understand.

alexmiller 2020-09-15T16:56:38.433200Z

the first is a persistent list, which is realized (and thus countable, like all persistent colls)

alexmiller 2020-09-15T16:56:54.433400Z

the second is a sequence

alexmiller 2020-09-15T16:57:12.433800Z

sequences are not (necessarily) realized so not necessarily countable

alexmiller 2020-09-15T16:57:58.434400Z

why it's a sequence is pretty obscure and probably should be considered an implementation detail

nivekuil 2020-09-15T16:58:00.434500Z

very interesting. think that's mentioned here https://clojure.org/reference/reader#syntax-quote

borkdude 2020-09-15T17:35:16.434600Z

bb is JVM-based so same as clj

1
borkdude 2020-09-15T17:36:32.434800Z

2👍1
mauricio.szabo 2020-09-15T22:19:40.437100Z

Hi, I'm trying to test a highly asynchronous test, and found out some bizarre behavior of clojure.test: sometimes, my assertions simply are not registered if they are on another thread. I was able to shring to the following code:

(t/deftest bar
  (t/testing "Why this does not work?"
    (.submit (java.util.concurrent.ForkJoinPool/commonPool)
             ^Runnable (fn []
                         (Thread/sleep 200)
                         (t/do-report {:type :fail, :expected 10, :actual 12})))
    (Thread/sleep 1000)))

mauricio.szabo 2020-09-15T22:21:06.438800Z

The task submitted to the ForkJoinPool, when it calls do-report, prints the failure on my terminal (but not on nREPL / Socket REPL) but does not register on clojure.test that a failure occurs

ghadi 2020-09-15T22:24:19.439100Z

fail how?

ghadi 2020-09-15T22:24:44.439700Z

that pool submission code above does not convey dynamic bindings...

ghadi 2020-09-15T22:25:10.440300Z

guess: do-report uses dynamic bindings?

seancorfield 2020-09-15T22:35:48.441300Z

@mauricio.szabo I think @ghadi is right -- clojure.test is full of dynamic bindings so that's likely to be your problem.

seancorfield 2020-09-15T22:36:36.442Z

*testing-vars* and *testing-contexts* are the two used by do-report that jump out at me immediately.

mauricio.szabo 2020-09-15T22:49:16.443600Z

Oh well... So I'll need to bring these asserts into the main thread, right?

mauricio.szabo 2020-09-15T22:51:21.443700Z

It doesn't register that there was an assertion, nor register the failure. So run-tests thinks that it's an empty test and returns a success.

2020-09-15T22:52:27.444500Z

That is usually for the best, but you can also look at bound-fn

2020-09-15T22:53:59.446700Z

If you don't put the assertions on the main thread you also have to make sure your assertions on other threads have run to completion before the main thread exits, which can also be tricky

mauricio.szabo 2020-09-15T23:09:31.451700Z

@hiredman yes, I was in fact working on a library to ease async tests in ClojureScript, and wanted feature-parity with Clojure. Seems that it'll not really be possible, unfortunately