Fork me on GitHub

Is there a room to optimize this little function (it's working fine):

(defn grab
  "When the predicate is true, use the first map to extract the key's value. Use the second map otherwise."
  [key pred? first-map second-map]
  (let [val-map (if pred? first-map second-map)
        keywordized (keywordize-keys val-map)]
    (key keywordized)))
Passing tests:
(deftest grab-test
  (testing "Order and keyword/string support."
    (is (= (grab :name true {:age 50 :name "Jack"} {"age" 10 "name" "Mark"}) "Jack"))
    (is (= (grab :name false {:age 50 :name "Jack"} {"age" 10 "name" "Mark"}) "Mark"))))
Note that first-map second-map keys may be strings or keywords, is it worth it to check or the check might be more expensive than the conversion?


(or (m (name k)) (m (keyword k))) - the map acts as a function looking up a key


Ah this is great, thanks


what does keywordize-keys do in the let ?


(is (= (grab :name false {:age 50 :name "Jack"} {"age" 10 "name" "Mark"}) "Mark")) would fail without it since it's string indexed


If key is always a keyword, you could do (if (contains? val-map key) (key val-map) (get val-map (name key))) (and avoid the keywordize stuff altogether.


If it isn't, then you could do (let [k (keyword key)] (if (contains? val-map k) (k val-map) (get val-map (name k))))


Calling keyword on a keyword just returns it. Calling name on a keyword returns the string version of it.


Either way, no need to keywordize the val-map @somedude314


Awesome thanks, key is always a keyword

Binny Zupnick07:06:23

Going through Brave and True, it defines data structures such as {:pegged true, :connections {6 3, 4 2}} .

Binny Zupnick07:06:52

Something tough to get used to, coming from OOP, is the lack of naming or clarity just by looking at things

Binny Zupnick07:06:01

on one hand I assume I'd get used to it, but it's hard not to think that it's inherently more readable to do something like:

{:pegged true, :connections [{:destination 6 :fly-over 3}  {:destination 4 :fly-over 2]}


this is more readable to me as well. maybe he is just demonstrating the flexibility of "maps" but i like your naming better.

Binny Zupnick07:06:57

but it seems pretty standard in Clojure to prefer minimalist variable namings and data structures where as in OOP it's been beaten into me NEVER to use names like 'x'. Maybe variable names and these types of data structures are two different conversations, though

David Pham08:06:42

Hi everyone, is there a way to load some namespace on start using deps.edn?


As a main run entry? Or secondary?


The former is declaring a (defn main- [& args] ...) and using -m namespace.core


The latter is putting -i path/to/file.clj before your -m ... argument


is there some easy function that allows me to express 'double precision but not NaN or Inf' ?


my (small) problem is that i need it to work on clj + cljs, so i can't use Double/isNaN easily


and i was a bit surprised that here are no functions for this out of the box

David Pham11:06:21

Did you try double-in with specs?


this is exactly what i was looking for!!

David Pham11:06:16

My pleasure :)

Michael J Dorian12:06:59

Hey friends, I'm using http-kit to handle a post request for a form (basically a single text input field and a submit button) In the request map I get back :body which is a org.httpkid.BytesInputStream, which I can treat as a java input stream and convert to a string with

(defn BytesInputStream-to-string
  "This _must_ be the wrong way to do this"
  [^org.httpkit.BytesInputStream bytes offset]
  (.skip bytes offset)
  (apply str
          #(char %)
          (loop [acc []]
            (let [byte (.read bytes)]
              (if (not= byte -1)
                (recur (conj acc byte))
But I feel like this can't possibly be the intended way to read posted form data with httpkit. For reference the caller to this function looks like this:
(defn print-post-handler
  (let [pass (BytesInputStream-to-string (:body request) 9)] ; skip the "inputVar=" portion of the input with an offset of 9


There are several middlewares that do stuff with the incoming request. One would be ring.middleware.json which contains: wrap-json-body wrap-json-response that wrap the request and response body, converting the input stream into clojure datastructures and the return response into json

Michael J Dorian13:06:40

Ah, excellent. Thanks simple_smile


Am I doing something wrong here (js/window.getEventListeners <dom-node>) throws window.getEventListeners is not a function


(.getEventListeners js/window <dom-node>)`


where is getEventListeners coming from? doesn’t seem to be a built in function,


Aaron tried that too, doesn’t work


if it did exist, (js/window.getEventListeners <dom-node>) should work fine


window.getEventListeners(node) works in chrome


it appears to be part of the google chrome console utilities


Yup just figured


In Elixir, atoms (keywords in Clojure, e.g., :some-identifier) are kept in memory for the application's lifetime. Does the same happen in Clojure?


Howdy y'all

👋 1
Michael Stokley21:06:19

if i s/def a spec in a given namespace, how should i refer to it from another namespace?


@michael740 By it's name. Specs have (qualified) keywords as their "names".


If you use ::foo that resolves to foo in the current namespace. If you use ::bar/foo that resolves according to the alias bar (i.e., per a require [some.namespace :as bar] -- so ::bar/foo would resolve to :some.namespace/foo)


Spec names do not have to correspond to namespaces.


So we have things like (s/def :something/whatever ...) and that is referred to as :something/whatever everywhere.

Michael Stokley21:06:01

spec names are global, and can be referred to from any namespace, regardless of which namepace the spec was s/def-ed in?


Specs are held in a central, global registry, accessed via their name -- either a keyword or a symbol (s/fdef some-fn ...)


(you can actually s/def on a symbol too but that would be very unusual)

Michael Stokley22:06:19

great, this is working! thanks again, Sean.


First time asking here. I'm confused with this: ((hash-map :a 1, :b 2, :c 3) :b). Why is this a correct syntax? I'm still in chapter 3 of brave clojure, so I'm not sure if it'll be discussed on other chapters. Examples in chapter 3 only uses keyword lookup like in (:b {:a 1, :b 2, :c 3}) to get the value from the map. TIA.


You can use a map as a function, so the first form is doing that. It's the same as ({:a 1, :b 2, :c 3} :b). Also, keywords act like a function that looks themselves up, which is why the second form (`(:b {:a 1, :b 2, :c 3})`) works. Usually in code the map is not right in there, so it looks more like this (for a map called users): (users 123). You can also use the get function to make it more explicit if that's clearer: (get users 123)

👍 1

@nate What's the underlying principle behind "map as a function"? I just can't get my head around it yet. Thank you.


if you look at the mathematical definition of "function", a hash-map is closer to meeting that definition than most functions are


I think it comes from the idea that a map maps from keys to values, and so they're kinda like functions in that you give them the key (like an argument) and you get a value (like a return value).

👍 1

so because it looks like a function, might as well use it like a function

👍 1