Fork me on GitHub
#clojure-uk
<
2019-04-12
>
yogidevbear06:04:23

@jr0cket what about asking someone like Carin Meier?

practicalli-johnny07:04:41

@yogidevbear we have invited Carin to speak many times and hope she is able to speak again. If you have any specific people in mind who are great speakers like Carin, please let us know.

zyxmn07:04:44

Morning 😁

agile_geek08:04:18

To set expectations, I think it's unlikely Carin will come across for ClojureX. Especially, with it being to close to Christmas but it's always worth a try!

guy10:04:49

Noob question of the day: Why do we actually require stuff vs just using the fully qualified name?

(clojure.data.json/write-str edn :key-fn ->snake_case_string)

vs

(:require [clojure.data.json :refer [write-str]])
(write-str edn :key-fn ->snak_case_string)
Other than readability etc? Is there a technical reason?

Ben Hammond10:04:41

yeah that namespace may not be available

👌 4
Ben Hammond10:04:46

if you haven't required it

Ben Hammond10:04:58

you might luck out in dev

Ben Hammond10:04:01

but not in prod

Ben Hammond10:04:17

and there's a bunch of other processing that happens

dominicm10:04:25

There's a jira containing a rejected patch which auto requires

👌 4
Ben Hammond10:04:30

vars and namespaces get created

Ben Hammond10:04:05

defmethod attach to their defmultis etc

Ben Hammond10:04:07

there are stateful mutations that happen as a consequence of require

Ben Hammond10:04:48

def being the biggest one

mccraigmccraig10:04:40

@guy a global namespace is the work of the devil - i would be much happier if it just wasn't possible to use the fully qualified name

😂 4
mccraigmccraig10:04:06

(that would then offer at least the possibility of having multiple versions of a particular namespace loaded at the same time, and a similar solution to node's for resolving jar-hell)

👍 4
Ben Hammond10:04:22

can you wrangle java ClassLoaders hierarchies to achieve this?

mccraigmccraig13:04:03

given the underlying java namespacing by ClassLoaders, clojure would have to wrangle ClassLoaders to achieve this

mccraigmccraig13:04:38

it's obvs never going to happen - the global namespace thing is baked into clojure and unchangeable now

mccraigmccraig13:04:29

but everytime i find myself in jar-hell i look at npm and it's reified non-global packages and wonder why i can't have that

Ben Hammond10:04:42

I imagine that could get fiddly though

rickmoynihan11:04:10

@guy: require is the complecting of load https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/load and refer https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/refer for the common easy case. loading compiles and builds the namespace and executes its side effects. refer lets you access vars in another namespace. alias does something similar but is basically what backs the :as behind require.

4
thomas11:04:05

practical question... I need to design a GET method that gets multiple ID's.. how would you do this? as query params?

thomas11:04:14

something like that?

thomas11:04:29

or do a POST or PUT with a body?

rickmoynihan11:04:30

&status=1&status=2&status=3

rickmoynihan11:04:00

query params can be multi valued

thomas11:04:20

ok, learned something new already today 🙂

rickmoynihan11:04:21

ring will give you a sequence of them if you do that

thomas11:04:58

this isn't Ring... but Spring Boot... but I am sure that can do it as well.

rickmoynihan11:04:02

though people do comma sometimes comma separate them… but you can save yourself having to parse/decode them

rickmoynihan11:04:29

yeah most web frameworks have a way to handle it

thomas11:04:04

thank you for your help @rickmoynihan

thomas11:04:25

this does work indeed in Spring: public String method(@RequestParam(value="phone") String[] phoneArray)

thomas11:04:53

This works for url?phone=123&phone=345 and also for url?phone=123,345

rickmoynihan11:04:28

ok I think the former is part of http standards… the latter is just quite common but non-standard

maleghast12:04:20

Quick question... If you had a vector of vector pairs, like this:

[[4.640824 48.998544] [4.624537 48.994391] [4.62473 48.99418] [4.625631 48.9938] [4.641167 48.997896] [4.640824 48.998544]]
And you needed it to be a string, like this:
"4.640824 48.998544, 4.624537 48.994391, 4.62473 48.99418, 4.625631 48.9938, 4.641167 48.997896, 4.640824 48.998544"
would you use (reduce ...)?

maleghast12:04:44

(I am trying to stop myself from seeing every transformation as a nail, what with me having this big Reduce Hammer)

maleghast12:04:59

(I have a working reduce, well except that my string will have a comma on the end that I need to trim off after the reduce. Yes, commas and whitespace in the resultant string are meaningful)

jasonbell12:04:16

user> x
[[4.5 4.8] [4.5 4.8] [7.8 9.5]]
user> (flatten x)
(4.5 4.8 4.5 4.8 7.8 9.5)
user> (clojure.string/join " "(flatten x ))
"4.5 4.8 4.5 4.8 7.8 9.5"
user> 

jasonbell12:04:30

ah hold on, i see the commas

maleghast12:04:07

I get this:

(clojure.string/join ", " (first testvec))
"[4.640824 48.998544], [4.624537 48.994391], [4.62473 48.99418], [4.625631 48.9938], [4.641167 48.997896], [4.640824 48.998544]"

maleghast12:04:37

I missed the flatten, hold on...

maleghast12:04:47

Yay, result!

(clojure.string/join ", " (flatten (first testvec)))
"4.640824, 48.998544, 4.624537, 48.994391, 4.62473, 48.99418, 4.625631, 48.9938, 4.641167, 48.997896, 4.640824, 48.998544"

maleghast12:04:21

Thanks so much @jasonbell - I REALLY need to raise my "do stuff without using reduce" game when it comes to Clojure, so this is VERY helpful 🙂

jasonbell12:04:52

What the community is all about really.

jasonbell12:04:59

Helping each other.

👆 8
jasonbell12:04:33

With additional heckling and singing from @thomas and @otfrom respectively.

guy12:04:23

(apply str (interpose ", " (flatten x)))
=>
"4.640824, 48.998544, 4.624537, 48.994391, 4.62473, 48.99418, 4.625631, 48.9938, 4.641167, 48.997896, 4.640824, 48.998544"
Alternative 👀 maybe?

guy12:04:40

apply str interpose is like a poormans join though

jasonbell12:04:55

@guy nice one, apply was my first thought. I’ve never used interpose though.

guy12:04:27

Yeah its a fun fn

thomas12:04:36

🎶🎵🎻

guy12:04:39

I think its lazy too :thinking_face:

guy12:04:47

not that, that makes a difference

guy12:04:12

yeah

([coll]
     (apply str coll))

guy12:04:20

thats the str/join 1 arity implementation

otfrom12:04:40

I'd say using reduce is almost always a good idea unless you can use map/`filter` and friends. Most of clojure is around using those basic tools for working with seq-able or channel shaped things

Sam H12:04:51

Did you not want the comma between every pair originally?

Sam H13:04:18

(def x [[4.640824 48.998544] [4.624537 48.994391] [4.62473 48.99418] [4.625631 48.9938] [4.641167 48.997896] [4.640824 48.998544]])

(->> x
     (interpose ",")
     flatten
     (clojure.string/join " "))

"4.640824 48.998544 , 4.624537 48.994391 , 4.62473 48.99418 , 4.625631 48.9938 , 4.641167 48.997896 , 4.640824 48.998544"

rickmoynihan13:04:23

@maleghast I always avoid flatten as it leads to all sorts of antipatterns, as it’s unconstrained on depth so can gloss over underlying problems; e.g. leave you producing data in the wrong way then flattening it to tidy it up. I’d normally prefer something like: (str/join ", " (mapcat identity [[1 2] [3 4]]))

rickmoynihan13:04:56

a heuristic is that code with a flatten near the end can often be fixed by replacing an earlier map with a mapcat.

rickmoynihan13:04:32

generally it’s much better to fix a problem upstream

Ben Hammond13:04:24

would it lower the tone to suggest?

(str (reduce (fn [^StringBuilder sb [x y]]
               (doto sb (.append x) 
                        (.append \space) 
                        (.append y) 
                        (.append \,)))
             (StringBuilder.)
             [[1 2] [3 4]]))

Ben Hammond13:04:52

that buys you an unwanted trailing comma of course

guy13:04:09

can’t you just drop the last one?

rickmoynihan13:04:05

if you want to do it efficiently and correctly then you’re best transducing

rickmoynihan13:04:06

(transduce (comp (mapcat identity) (interpose ", "))
             (fn
               ([] (StringBuilder.))
               ([x] (str x))
               ([^StringBuilder sb s] (.append sb s)))
             [[1 2] [3 4]])

rickmoynihan13:04:18

oh sorry I misplaced the commas… but the point still applies

guy13:04:42

How does the middle part work?

rickmoynihan14:04:04

arity 0 constructs the starting value (a string builder) arity 1 is called when its finished, and converts the string builder into a string arity 2 appends as per reduce

👍 4
Ben Hammond13:04:52

won't (apply str be just as efficient?

guy13:04:56

Is that a anon fn, with 3 types of arity?

guy13:04:57

wow, today i learned

Ben Hammond13:04:33

^^^ its a reducing fn

rickmoynihan13:04:40

you can’t do this with a stringbuilder though, as you need to convert it back to a string

👎 4
Ben Hammond13:04:00

I like the theoretical purity of specifying the initial value in the zero-arg reducing fn

Ben Hammond13:04:20

but I usually specify the initial value into the transducer

rickmoynihan13:04:20

you can equally pass it as the starting value of reduce

rickmoynihan13:04:26

yeah either works — whatever floats your boat 🙂

rickmoynihan13:04:57

I was assuming you’d break the anon function out into a lib function though

rickmoynihan13:04:28

e.g. rf-append

reborg13:04:57

minor impro: (mapcat identity) => cat

👍 4
rickmoynihan13:04:55

I always forget about that… mapcat identity has been ingrained into my brain since pre clojure 1.0 🙂 1.7 is so hipster

rickmoynihan13:04:46

though right enough that’s a pure transducer function

reborg14:04:25

yeah, same here, I have something triggering when I see mapcat identity :thinking_face: in a transducer and then I remember of the cat

reborg14:04:41

As of the completing suggestion, it looks nice:

(transduce
 (comp cat (interpose ", "))
 (completing 
   (fn [^StringBuilder sb s] (.append sb s)) 
   str)
 (StringBuilder.)
 [[1 2] [3 4]])

rickmoynihan14:04:00

@reborg: :thumbsup: Though I think this corrects my misread of the spec:

(transduce
   (comp (map (partial clojure.string/join " "))
         (interpose ", "))
   (completing
    (fn [^StringBuilder sb s] (.append sb s))
    str)
   (StringBuilder.)
   [[1 2] [3 4]])

reborg15:04:34

ahhh too bad you killed the cat :)

🙀 4
rickmoynihan14:04:48

outputs ;; => "1 2, 3 4"

rickmoynihan15:04:09

Unix/Ops question: How do people here wait in a shell script for a HTTP service to start… looking for something smarter than sleep 15, i.e. something that will poll a service until it comes up and returns 200 then unblock… or after a certain configurable timeout return an error I can trap exit on.

rickmoynihan15:04:21

Looking for some unix command line tool I can just apt-get

rickmoynihan15:04:27

I’ve written bash/`curl` scripts that loop in the past waiting for the 200; but never bothered trying to terminate after a timeout and return a non-zero status code…

rickmoynihan15:04:43

ahh thanks… looks like what I want. Also looks like it wraps the timeout stuff in bash I mentioned

maleghast15:04:43

This is a very cool tool ^^

maleghast15:04:04

Also, thanks ALL for the extended discussion of my "how not to reduce" question 🙂

maleghast15:04:11

Fascinating stuff

dominicm15:04:57

but what about posix shell! 😄

trollface 4
4
flefik20:04:42

curl -L --retry 20 --retry-connrefused -s -S --max-time 120 localhost:3000

flefik20:04:55

this will keep retrying for 2 minutes then die

flefik20:04:50

you might want to skip -S depending on your appetite for verbosity

rickmoynihan21:04:48

thanks that looks great