Fork me on GitHub
#clojure
<
2021-10-29
>
emccue03:10:20

Any known/proven libraries or approaches to serving static files locally in development but from an s3 bucket/behind a cdn in production + the path replacement needed

emccue03:10:27

I’m looking into the approach taken by https://docs.djangoproject.com/en/3.2/ref/contrib/staticfiles/ but really don’t want to reinvent the wheel

emccue03:10:20

This includes CSS and CLJS, which complicates things over a “pure” backend solution

msolli06:10:48

There’s https://github.com/magnars/optimus, which handles everything but deploying the static files to S3. That’s fairly easy to do yourself, though, using https://github.com/cognitect-labs/aws-api.

p-himik08:10:53

When I was faced with a similar issue, I decided against switching between the methods of accessing the files and instead used a local version of S3 - LocalStack. There were some hiccups that was caused mostly by me relying on some undocumented AWS S3 behavior, but after those got ironed out it's now a smooth sailing.

GGfpc09:10:17

Are there any good books/Moocs on functional programming in Clojure? I've been writing for a while but I feel like most of my code is still pretty imperative.

pavlosmelissinos10:10:31

#beginners is a better place for this question • you can post self-contained parts of your code that you feel is too imperative. That'll definitely get you some pointers. There's also #code-reviews for larger pieces of code (it has much less traffic but is more targeted) • I'd start with https://github.com/matthiasn/talk-transcripts/tree/master/Hickey_Rich if I were you. They're really dense and fun to watch/read at the same time and I feel like they allow you to grok Clojure's approach more quickly than any book/mooc. All of them are awesome but I'd recommend https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/AreWeThereYet.md, https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md, https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/ValueOfValuesLong.md, https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/LanguageSystem.md, https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/ClojureMadeSimple.md, https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/Spec_ulation.md, https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/MaybeNot.md

mbertheau10:10:21

I'd like to filter a sequence and then sort it. I'd also like to avoid building data structures at every step if possible (following the idea of transducers). sort-by in the standard library doesn't have an arity that returns a transducer. There's https://github.com/cgrand/xforms which has a transducer sort-by, but I was wondering how close I can come with clojure core, without being too verbose or unwieldy. Writing that with the intermediate data structure is simple enough: (->> items (filter match?) (sort-by key)) . So, two questions: Is there a point to my quest, or am I mistaken somewhere? and 2. If there is a point, how could one do it?

cgrand10:10:29

Well you can’t sort without having the whole collection at once in memory. So the only savings can come from building this intermediate collection and sorting it in place. Or you have domain-specific knowledge that allows to sort in a more streaming manner (eg a bound on how much out of order the input is)

p-himik10:10:58

You can sort without having the input all at once in memory. But you cannot sort without having the full result in memory. And the xforms version simply accumulates everything and sorts as the last step. Not much going on there.

Ben Sless12:10:02

Not to nitpick, but you can merge sort and persist to disk instead of collections in memory

p-himik10:10:44

I wouldn't even think about putting sort in a transducer - IMO it just doesn't belong there because it can't have an intermediate result.

mbertheau10:10:58

So you're saying that the benefit of feeding items to sort one-by-one from filter instead of first accumulating them in an intermediate data structure are not worth it?

mbertheau10:10:28

xforms sort can still come in handy when you have a transducer pipeline, just for syntactical readability considerations. afaics there are no disadvantages compared to the non-transducer approach, right?

Ed10:10:51

I think so ... you have to consume the whole collection before you return a single result cos of the sort, so you could do that as the completing arity on the rf?

(->> (range 10 1 -1)
       (transduce (filter even?) (completing conj sort) []))
or something with transients for going faster 😉

p-himik10:10:45

> the benefit of feeding items to sort one-by-one from filter instead of first accumulating them in an intermediate data structure are not worth it? I'm not saying that, and it has nothing to do with transducers. (sort (filter ...)) will not create an accumulated version of a to-be-sorted collection. But there can indeed be an advantage of having the whole to-be-sorted collection ready - depends on the sort implementation. The algorithmic complexity will probably stay the same but the specifics might change. Readability is good when it's appropriate. sort is in my mind not a transducer and does not belong in a chain of transducers - using some version of sort in such a context will worsen the readability for me because I will have to sit and think about what the intent was and how that sort transducer works exactly.

p-himik10:10:17

And if you need to have a chain of transducers before you sort the result, without having a lazy collection chain, you can use sequence. This way, there will be just one lazy collection - the input to sort.

mbertheau12:10:10

Alright, thanks!

cgrand20:10:58

Actually it’s giving me ideas to better leverage transducers in sort: 1/ rather than using an ArrayList I could use a list of fixed size arrays (thus avoiding copy on resizes). Sort each array on it’s own then merge sort (in place or in flight by organizing arrays into a heap). 2/ perform sorts and in-place merge on another thread

👍 1
FiVo10:10:07

Just for my understanding of atoms. If i have lots of concurrently happening operations on the atom that take little time and some "heavy" operation it might happen that the heavy operation never "makes it" even if initiated ages ago? Something like

(def queue (atom clojure.lang.PersistentQueue/EMPTY))
  ;; happens all the time in lots of go blocks
  (defn dequeue! [queue] (ffirst (swap-vals! queue pop)))
  ;; heavy operation
  (swap! queue into lots-of-data)

FiVo10:10:29

Also (pop clojure.lang.PersistentQueue/EMPTY) does not throw, contrary to what the docstring says.

tlonist10:10:04

Is there any way to show REPL with presentation mode from intellij?

FiVo10:10:29

I guess that is a question for #cursive

👍 2
simongray12:10:10

How do I require/import a deftype’d type from one namespace so that I can implement a protocol method for it in another? I’m already requiring the namespace and importing the type, but I still get “does not exist” error.

the-alchemist12:10:42

got an example? that would help…

simongray13:10:40

never mind, fixed it. When importing, you apparently need to make sure dashes are converted into underscores, unlike when requiring. That seemed to be the issue.

the-alchemist13:10:07

hmm, good to know!

Ed13:10:14

you don't need to import it at all, do you???

(ns scratch)

(deftype Monkey [paw])

(deftype spider-monkey [legs])

(ns user
  (:require [scratch]))

(defprotocol Climber
  (climb [this that]))

(extend-protocol Climber
  scratch.Monkey
  (climb [this that] (prn 'Monkey 'climb that)))

(extend-protocol Climber
  scratch.spider-monkey
  (climb [this that] (prn 'Spider 'Monkey 'climb that)))

(climb (scratch/->Monkey "legs") "tree")
(climb (scratch/->spider-monkey "legs") "tree")
works for me ... am I doing something different??

simongray13:10:47

This was in a third-party library, not in the same file. Not sure if that makes a diffence, but all of the resources I google told me to import and it wouldn’t recognise the class at all without it, so….

Lucas Jordan18:10:14

What is the best way to get the eid from datomic (client), given a lookup ref?…. I tried the following but was surprised to get all values: Thanks!

(d/pull (:db-after tx1) '[:db/id] [:test/identity b-ident])

Lucas Jordan18:10:47

Well this works… but it feels wordy 🙂

(defn eid-for-ref [db ref] (let [attribute (ref 0)
                                 value (ref 1)
                                 query [:find '?e :in '$ '?a '?v :where ['?e '?a '?v]]
                                 result (d/q query db attribute value)]
                             (ffirst result)))

pithyless22:10:56

@U02AY0CR9CM perhaps using datoms?

(some->> {:index :avet
          :components lookup-ref)
         (datomic.client.api/datoms db)
         first
         :e)
Datoms are indexed and associative, so instead of ... first :e one could use ... ffirst

Lucas Jordan00:10:29

Hm, interesting. Thanks!

Jacob Rosenzweig19:10:29

Is there a simple way to apply a series of functions to a var like the ->> operator but using a dynamic list. E.g.

(->> thing
     step-one
     step-two
     step-three)
Where I really want something like:
(applies-all-steps thing [step-one, step-two, step-three])

Jan K19:10:34

(reduce #(%2 %1) thing [step-one, step-two, step-three])

Jacob Rosenzweig19:10:06

Oh yeah reduce is a prime candidate here. thx.

Alex Miller (Clojure team)19:10:44

((apply comp (reverse [step-one step-two step-three])) thing) :)

Jacob Rosenzweig19:10:55

((apply comp (reverse [string/capitalize string/lower-case]) "This is a dog")) Results in an error ; ClassCastException java.lang.Character cannot be cast to clojure.lang.IFn clojure.core/comp/fn--4727 (core.clj:2459)

Jacob Rosenzweig19:10:48

Oh I see the error

Jacob Rosenzweig19:10:29

Reading parens is hard for me apparently

Alex Miller (Clojure team)19:10:50

(->> o f1 f2 f3) is just (f3 (f2 (f1 o))), comp is exactly function composition on a list of fns, but need to reverse ordering