Fork me on GitHub
#beginners
<
2021-05-28
>
Lukas09:05:44

Hey, not sure if this is the right place to ask: I'm using pedestals response-for function:

(test/response-for (:io.pedestal.http/service-fn @lhrb.server/server)
                     :post "/q"
                     :headers {"Content-Type" "application/edn"}
                     :body "(+ 2 2)")
After the first eval, changes to the request body do not have any effect and I always get the first request returned. Could anyone help me resolve this Issue?

Lukas09:05:46

Okay seems like it's not an issue with the response-for fn, since I observe the same behavior with curl

Lukas09:05:16

Oh gosh my bad ... I had a var in the repl which I used instead of the argument passed by the function. 🙈 Sry

Timofey Sitnikov11:05:11

Good morning, I am puzzled by the https://github.com/drewr/postal/blob/7606a66c10b66abd3476c6f4c828fb4b87d3792d/src/postal/core.clj#L29, which is the following:

(defn send-message
  ([{:keys [host] :as server}
    {:keys [from to bcc subject body] :or {to "" subject ""} :as msg}]
     (when-not (or (and from to)
                   (and from bcc))
       (throw (Exception. "message needs at least :from and :to or :from and :bcc")))
     (if host
       (smtp-send server msg)
       (sendmail-send msg)))
  ([msg]
     (send-message (meta msg) msg)))
In the function definition, after the function name there is is a function call, where are the function parameters?

tvirolai11:05:16

They're not actually function calls, although they're written similarly. The function has two arities (see https://clojure.org/guides/learn/functions#_multi_arity_functions) defined for it, so there are two distinct function bodies, one for arity of two (server, msg) and the latter for arity of one (msg).

1
Timofey Sitnikov12:05:03

@tvirolai, thank you for clarifying, I did read about it, but for some reason it did not register as such.

bastilla13:05:33

Altering a data structure (map) multiple times (in a stateful way) with one line (without loop/recur) A simple question here regarding basic techniques. The case of 'altering stuff one single time' is page-3-stuff of any book, of course:

(let [cat-v [:data :content :objects]
	  dim-app-db (assoc-in app-db cat-v {})]
  ;; Process dim-app-db
Now I want to alter the target structure multiple times. My imperative mind set keeps producing this code:
(let [categories '([:data :content :objects]
     			   [:data :content :media :objects])
	  dim-app-db (let [func (fn [db categories]
				                (if (empty? categories)
				                  db
				                  (recur (assoc-in db (first categories) {})
				                         (rest categories))))]
				        (func app-db categories))]
  ;; Process dim-app-db
But this is quite some clutter. I was thinking of a more lispy/functional way of altering the target structure (app-db) multiple times. Stateful transducers came to my mind. I read about it, but couldn't pattern match it into my needs so far. Is there a one-liner that does the job more graciously?

NoahTheDuke13:05:40

why do you want to avoid loop/recur? it does what you want

NoahTheDuke13:05:06

lemme see if i can rewrite what you have

NoahTheDuke13:05:43

(let [categories '([:data :content :objects]
                   [:data :content :media :objects])
      dim-app-db (loop [db app-db categories categories]
                   (if (empty? categories)
                     db
                     (recur (assoc-in db (first categories) {})
                            (rest categories))))]
  ;; Process dim-app-db

🙌 1
bastilla13:05:32

Hi @nbtheduke . I don't want to avoid it at all cost. It's fine with me. (I LOVE loop/recur, in fact). I was just wondering if I do total beginner's mistakes. Maybe there is a way shorter technique and I just don't know it. This is a standard case, and I write this code quite often. (And it's lenghy and requires a new fn all the time.)

bastilla13:05:08

Ah, yeah, that's better code for sure. About the same lenght, and the approach has not changed. But certainly more elegant. Thanks!

NoahTheDuke13:05:03

there’s also reduce

NoahTheDuke13:05:12

dim-app-db (reduce #(assoc-in %1 %2 {}) db categories) i think (haven’t run that)

NoahTheDuke13:05:10

first arg to the reducing function is the accumulator, second is the current value from the sequence, and the accumulator (which starts as the db) is returned at the end

🙌 1
👍 1
bastilla13:05:44

Hrm... you sure this works? If so this is exactly what I was looking for. 1 millions thanks, man!!!

bastilla13:05:16

Yeah, just reading this! 🙂 I knew reduce but wasn't aware it's capable of such things also. Awesome. Only downside is, I have to change A LOT of code now, lol. No, seriously, thanks. I had a moment of epiphany.

😂 1
🎉 1
NoahTheDuke13:05:48

so glad to help!

Souler T15:05:22

I expected (map (comp (map inc) vector) [1 2 3] [1 2 3]) will give me ((2 2) (3 3) (4 4)) But it give me (#object[c] #object[c] #object[c]) instead. Is there anyone know how to explain this or what keywords should I look for? Thanks !

dpsutton15:05:58

(map inc) is a transducer. If you switch to (partial map inc) you'll get your intended behavior

Souler T15:05:04

Thanks! I'll go search for related concepts. 🍻

Max15:05:07

When you’re doing simple conversions from one coll type to another, do you prefer to use set/`vec`/`list*` or (into #{}/[]/())? Or when would you prefer one or the other?

ghadi15:05:46

converting to a concrete list/seq isn't usually necessary

ghadi15:05:34

I use set/vec if it's a simple coercion, if there are more transformations I consider using (into [] transducer collection)

Max16:05:45

Yeah for me this comes up most often when I need the specific properties of a particular collection, for example using a set to check membership or a vec to ensure end-appending with conj in a reduce or something

practicalli_john17:05:12

Can I use clojure sets as a key in a hash-map, using a value within that set key as a lookup to get the value associated with the key? For example, I have a set of pet types that are collectively called pets. If I call get on the hash-map with "Cat" as an argument, then I would like to get "Pet" as the result. Instead I get nil, so it seems I am missing something. (assume I have a long list of sets and associated group names I want to call them, which I'd like to use as a lookup)

(get {#{"Cat" "Dog" "Rabbit" "Hamster"} "Pet"} "Cat")

dpsutton17:05:19

no you cannot. and in general that wouldn't be well-defined (get {#{:a :b} :foo #{:a} :bar} :a) would have two valid choices for lookup

dpsutton17:05:14

but if your domain has disjoint sets you could roll your own deftype that had the sets and then "unrolled" the sets into a regular map with each key in the set attached to the value for the set. and when you dissoc you drop all of the keys from that set

hiredman18:05:40

clojure.set/index

sova-soars-the-sora20:05:35

I want to detect customer country by ip address and show a handful of nations one page and have a default for the others... any reasonable index of ip prefixes to countries one can use?

seancorfield20:05:38

@sova Not really. IP address groups aren’t all that geographic in nature and they’re very fragmented. Best option is to use a service like http://ipinfo.io

sova-soars-the-sora22:05:00

clj-http: status 404 {:status 404, :headers {"referrer-policy" "strict-origin-when-cross-origin", ... I'm not sure what's up, if I run this locally the client/post works fine, but from the live box it returns an error

indy22:05:13

Does doing a curl of the same request from the live box work?

sova-soars-the-sora22:05:33

I switched to client/get and it works

sova-soars-the-sora22:05:31

would this be my middleware preventing a clj-http.client/post ?