Fork me on GitHub
#clojure
<
2019-06-18
>
flyboarder03:06:29

I am hoping the clojure fam can help me out, there was an article (or maybe github project), that demoed running multiple versions of clojure side by side with classpath isolation, can anyone help me find it!?

jeroenvandijk08:06:28

@flyboarder it reminds me of immutant, but i'm guessing you mean something else http://immutant.org/documentation/1.1.4/initialization.html

jeroenvandijk08:06:54

(and i didn't actually use immutant)

flyboarder03:06:29

Looking for side-by-side, ie. in the same JVM

orestis04:06:32

Was that boot pods @flyboarder ?

nha09:06:57

I am quite certain he would be aware of boot pods šŸ˜‰

šŸ‘ 4
4
henrik10:06:43

Whatā€™s the correct pred for something like this?

(condp pred thing 
  map? [:map thing]
  vector? [:vector thing]
  string? [:string thing]
  ā€¦)
(Or a better solution that accomplishes the same thing)

henrik10:06:11

Just #(%1 %2)?

jeroenvandijk11:06:47

or

(require '[clojure.spec.alpha :as s])

(s/conform (s/or :map map? :vector vector? :string string?) thing)

Alex Miller (Clojure team)10:06:00

Why not just use cond?

šŸ‘ 4
henrik11:06:05

Would a protocol be quicker?

Radek12:06:47

Guys, how did you learn to solve problems the functional way? Iā€™m currently in the middle of moving some of my JS codebase to Clojure. Started out by trying to directly rewrite the code, but that didnā€™t work and I sometimes still struggle to wrap my mind around how to design the flow of the programs. So Iā€™m interested in hearing where you got this from

pyr12:06:06

@henrik use a protocol if you want openness, if you have a constrained set of shapes you want to apply that on, go for cond as suggested by @alexmiller

šŸ‘ 4
Suni Masuno12:06:44

@kyselyradek I'd love to hear other's approaches. But For me I got to functional designs a bit "backwards" learning some heuristic rules of software design and being led by them to functional. The rules I use, that got me here, are... 1) minimize and isolate mutation 2) ditto for side effects 3) ditto for state 4) Name what you are doing, not what you're doing it on (what around here I've found out is called point free) 5) A small amount of dense code is slightly better than a large amount of light code 6) write code first for other developers to read, second to do it's job 7) TDD, lots And that's a quick look at how I got here. Also some vids.... https://www.youtube.com/watch?reload=9&amp;v=US8QG9I1XW0 https://www.youtube.com/watch?v=srQt1NAHYC0

Radek14:06:09

Suni, thank you a lot for the answer! Iā€™m looking at the point-free programming now, looks like that was mainly what I was missing. However can you please explain what you meant by > 5) A small amount of dense code is slightly better than a large amount of light code I have a slight idea, but just to make sure

Suni Masuno14:06:55

I find highly composed code (which is my fav!) "does more" per line. As a result I feel like 15 lines of "really good clojure" is effectively ~100 lines of "really good java". They're both good code, and most importantly it tends to take about the same amount of time to read or write them. in those situations I tend to prefer the option that produces more "dense" code.

šŸ‘ 4
Radek14:06:55

Right, thatā€™s what I though you meant. Great, thanks a lot for your input on this! šŸ™‚

Suni Masuno15:06:14

^_^ No problem! Glad I could help.

manutter5112:06:05

@kyselyradek Neal Ford has a video on ā€œFunctional Thinkingā€ that I found helpful. https://www.youtube.com/watch?v=JeK979aqqqc

šŸ‘ 8
tomaas13:06:56

hi, in ring or maybe even in general, what is the difference between :session and :cookies?

ghadi13:06:34

@tomaas cookies are literally the HTTP cookies, whereas session doesn't come from HTTP headers, but is something that can be derived (for instance, by looking up a session ID in a database)

ghadi13:06:02

oftentimes people use a cookie to lookup a session

Ahmed Hassan13:06:19

And cookies are stored in browser.

tomaas13:06:26

sorry, did not get it all well

tomaas13:06:19

session is created in server, but the browser must store something (id of session) so that with following requests the server can query up session data based on that id

ghadi13:06:19

cookies are often used to carry that ID

tomaas13:06:51

thank you!

Suni Masuno15:06:04

Does anyone have any advice on moving defs between namespaces on an existing project? People keep telling me intellij/cursive have cool features and I'd love it if this were one of them. But yeah, do you just go through and check aaaaalllllll the requires? (context, I found a bloated utils file and wanna break it up a fair bit)

lilactown17:06:25

is there a neater way to do this (that doesnā€™t involve swaping an atom šŸ˜›)?

(defn find-all
  "Recursively walks a tree structure and finds all elements
  that match `pred`. Returns a set of results."
  [pred tree]
  (let [results (atom #{})]
    (clojure.walk/postwalk
     (fn walker [x]
       (when (pred x)
         (swap! results conj x))
       x)
     tree)
    @results))

dpsutton17:06:47

blend tree-seq and filter?

lilactown17:06:56

ahh, I always forget about tree-seq

p-himik18:06:47

I'm going through tempura's code and stumbled across this:

(let [;;; Local aliases to avoid var deref
      merge-into-default-opts merge-into-default-opts
      scoped                  scoped
      search-resids*          search-resids*
      search-resids*-cached   search-resids*-cached
      search-resids           search-resids]
  ...)
Can someone please help me understand what the comment means?

leonoel19:06:34

My guess would be performance optimization. Any time you access a var, the compiler emits a call to <the-var>.deref(), which adds a layer of indirection plus a volatile read. A local binding is just an alias to a value, so it's easier for the JVM to optimize.

p-himik19:06:07

I see, thanks! I didn't know about <the-var>.deref().

leonoel19:06:10

actually the method name is not deref, it's getRawRoot

g18:06:50

hey everyone, in a couple places in my code iā€™m trying to decouple services by passing functions as arguments as follows:

(defn get-and-do-a-thing [accessor args]
(do-the-thing (accessor args))

g18:06:06

is there any good way to constrain the contract of the accessor function at this level?

noisesmith18:06:42

not in a way that's enforced at compile time

noisesmith18:06:29

you can use specs and exercise the accessor, which works if you remember to do so and the spec is correct

g18:06:56

yeah, thatā€™s what i thought. thanks

g18:06:04

also, when would you use binding over with-bindings?

noisesmith18:06:49

I'd only use with-bindings if something else ensured I had the vars available

noisesmith18:06:03

otherwise binding does all the stuff to get the vars behind the symbols for me

hiredman18:06:29

And in general I avoid dynamic bindings

g18:06:25

whyā€™s that?

hiredman18:06:49

Because static scoping is good

hiredman18:06:11

And functions that take arguments are good

hiredman18:06:38

There are very good odds that anything that is a dynamic var is really a function argument hidden behind awkward calling convention

bellissimo 4
hiredman19:06:33

There are places were dynamic scope is useful, but like maybe less then one or two new instances of dynamic scope per code base. So maybe you introduce a single dynamic var, wrap it in some helpers, and use it while forgetting the mechanism that underpins it from the rest of your code that does nothing with dynamic scope

hiredman19:06:47

If you are using dynamic scope so often that you have to ask about preferring bindings or with-bindings, you might have a big ball of mud

g19:06:23

yeah itā€™s mostly just one design decision thatā€™s just come up, iā€™m trying to maintain an in-memory cache of something from a database, and the question arose because i didnā€™t know if it was even going to be thread safe

g19:06:56

it doesnā€™t feel right intuitively but iā€™m trying to make a bit more of a concrete argument

g19:06:09

/ learn about the purpose of dynamic scope i guess