Fork me on GitHub
#beginners
<
2020-06-05
>
Jason Lee07:06:14

Does someone know how to refer a spec def from another namespace?

yuhan08:06:38

You need to ensure the other namespace is loaded by requiring it, after that its specs can be accessed as usual using qualified keywords

joshkh10:06:10

what am i doing wrong where by the case doesn't match on the class in the second example?

(= clojure.lang.PersistentVector (type []))
=> true

(case (type [])
  clojure.lang.PersistentVector "vector"
  "unknown")
=> "unknown"

delaguardo10:06:24

in case test-constants are not evaluated and clojure.lang.PersistentVector is a symbol in case context

delaguardo10:06:11

it is better to use cond or condp when you want dispatch by type

(condp instance? [1 2 3]
  clojure.lang.PersistentVector "[]"
  clojure.lang.PersistentHashMap "{}") 
something like this

joshkh10:06:52

that's interesting, thank you very much for explaining

delaguardo11:06:17

also case is a macro so you always can use macroexpand to see it’s true form 🙂

noisesmith16:06:52

(case (symbol (str (type []))) ...)
should work as well

delaguardo17:06:58

Cool trick, didn't think about it)

Timofey Sitnikov11:06:36

Good morning, I am looking at https://github.com/stuartsierra/component/blob/master/src/com/stuartsierra/component.cljc, and I cannot figure out this line: (map->SystemMap (apply array-map keyvals)) , how is it that the map->SystemMap is a function? I thought that -> was a threading operator. If I do this:

Clojure 1.10.0
user=> (type map->SystemMap)             ; does not exist in this ns
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: map->SystemMap in this context
user=> (defrecord SystemMap [a b])
user.SystemMap
user=> (type map->SystemMap)              ; now it exists, how?
user$eval138$map__GT_SystemMap__158
user=> (type map->)
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: map-> in this context
user=> (macroexpand map->SystemMap)
#object[user$eval138$map__GT_SystemMap__158 0x4e25147a "user$eval138$map__GT_SystemMap__158@4e25147a"]
Where can I read about the map->?

nmkip11:06:13

https://clojure.org/reference/datatypes > when a defrecord Bar is defined a corresponding function `map->Bar` is defined that takes a map and initializes a new record instance with its contents (versions 1.3 and later only)

Darin Douglass11:06:29

https://clojuredocs.org/clojure.core/defrecord > Given (defrecord TypeName ...), two factory functions will be defined: ->TypeName, taking positional parameters for the fields, and map->TypeName, taking a map of keywords to field values.

Timofey Sitnikov11:06:46

OK, thank you @juan.ignacio848 and @ddouglass, it simply constructs an object of the type of defined defrecord , like so:

user=> (defrecord SystemMap [a b])
user.SystemMap
user=> (def mm (map->SystemMap {:a 10 :b 20}))
#'user/mm
user=> (println mm)
#user.SystemMap{:a 10, :b 20}
Would it be correct to say that map->SystemMap is a macro? Or is it an actual function. Becasue macroexapnd outputs: #object[user$eval137$map__GT_SystemMap__157 0x35d3ab60 "user$eval137$map__GT_SystemMap__157@35d3ab60"] So does that mean its a macro?

nmkip11:06:59

That I don't know 🙂 > I thought that `->` was a threading operator. Yes, -> that's one of the threading macros. But try this on your repl: (defn foo->bar [x] x) -  and `>` , among others, are characters that are valid in function names

Timofey Sitnikov11:06:09

That is what I have been suspecting but was not sure. For that reason, I was making an assumption that it is simply a macro.

rmxm12:06:35

is there a way to capture current let bindings and automatically cast them into a map?

adam17:06:24

I am currently getting {:lang "fr"} with the following destructuring: [{{:keys [params]} :request}] how can I destructure it further to only get fr?

phronmophobic17:06:35

this might work:

[{{{lang :lang} :params} :request}]
typically, I don’t use destructuring if the nesting is more than 1 level. I find the following more readable: (-> request :params :lang)

phronmophobic17:06:18

or even (get-in request [:params :lang])

adam17:06:39

Thank you so much, the first one worked

adam17:06:33

Just confused how come :keys is not needed 😐

phronmophobic17:06:11

[{{{:keys [lang]} :params} :request}] would also work

phronmophobic17:06:25

it’s just an alternative way to write it

adam17:06:21

Got it, thanks

phronmophobic17:06:22

I only use destructuring minimally , so https://clojure.org/guides/destructuring#_associative_destructuring might be a better resource

🙏 4
Phil Hunt18:06:12

and learned a bit about Luminus's innards in the process

Nassin20:06:20

If I have :foo {:extra-deps <some-jar> :main-opts ["some command"]} in aliases, clojure -R:foo -M:foo should work correct?

Alex Miller (Clojure team)20:06:17

oh, you have a jar file

Alex Miller (Clojure team)20:06:48

should then be :foo {:extra-deps {:local/root "path/to/file.jar"} :main-opts ["some" "command"]}

Nassin20:06:09

thanks for confirming, now to check why isn't working

Alex Miller (Clojure team)20:06:07

what's the error and what's your command in main-opts?

Nassin21:06:14

sorry yeah, bad command line args

adam21:06:39

Hey guys, what I missing here: I am using bidi router and I have this handler:

(defn index-handler [request] (res/response request))
And this middleware but x-bob is not appended to the output of the above:
(defn wrap-lang [handler]
  (fn [request]
    (let [response (handler request)]
      (assoc-in response [:headers "x-bob"] "Robert"))))
Any idea why?

noisesmith21:06:58

@somedude314 all I can think is you aren't using the handler that your middleware created

user>
(defn wrap-lang [handler]
  (fn [request]
    (let [response (handler request)]
      (assoc-in response [:headers "x-bob"] "Robert"))))
#'user/wrap-lang
(defn handler [request]
  {:code 200 :headers {} :body "OK"})
#'user/handler
(ins)user=> (def h (wrap-lang handler))
#'user/h
(ins)user=> (handler {})
{:code 200, :headers {}, :body "OK"}
(ins)user=> (h {})
{:code 200, :headers {"x-bob" "Robert"}, :body "OK"}

adam21:06:35

Sorry totally confused here. How can I not be using it when I have it listed like this:

(def app
  (-> handler
      wrap-strip-trailing-slash
      wrap-session
      wrap-flash
      wrap-lang))

(def reloadable-app
  (wrap-reload #'app))

(defn -main [& _args]
  (run-server (if dev? reloadable-app app) {:port 8080}))

adam21:06:52

wrap-strip-trailing-slash is working fine for me

noisesmith22:06:40

it could be that some other middleware is clobbering :headers - but that wouldn't be the case if you are using the ring versions of those handlers

noisesmith22:06:55

I can't explain your bug, but I can say your code works as it should :D

adam22:06:46

Thanks 🙂 I will see if I can figure it out

adam00:06:21

@U051SS2EU I had to change my middleware to:

(defn wrap-lang [handler]
  (fn [request]
    (handler (assoc-in request [:headers "x-bob"] "Robert"))))

noisesmith00:06:49

oh you meant to change the headers coming in, rather than the response? weird

adam00:06:52

Lol. Sorry. Sort of. I only modified :headers as a test, not thinking it mattered. What I am really trying to do is injecting the current language which sometimes come from the URL prefix and sometimes from the logged in user in the context variables to pass it to my templates.

Rob Aguilera23:06:05

Hello all, working my way through some clojure exercises and I'm a little confused on what I'm getting back. I'm given a string ACGTGGTCTTAA and I need to replace each letter with a specific value. After I split it, and replace the values I get the following vector below. I need to join it back together but I'm confused on a couple of things. 1. Why is the vector itself surrounded in "" 2. What are the \ characters behind and in front of each letter mean?

;; => "[\"U\" \"G\" \"C\" \"A\" \"C\" \"C\" \"A\" \"G\" \"A\" \"A\" \"U\" \"U\"]"
I'll place my code in a thread if that helps.

Rob Aguilera23:06:36

(defn to-rna
  [dna]
  (let [dna-split (str/split dna #"")
        rna-split (str/replace dna-split #"C|G|A|T" {"C" "G" "G" "C" "A" "U" "T" "A"})]
    rna-split))

seancorfield23:06:23

@U011DBXN8DU That can't be your actual code -- your let has no body so it will return nil.

seancorfield23:06:15

I suspect you're just calling str on rna-split which produces a string that looks like it has a vector inside it.

hiredman23:06:05

you are calling str/replace on something that is not a string

seancorfield23:06:07

Ah, I see where it's going wrong... dna-split is a sequence of strings, not a string, so when you call str/replace on it, it's getting converted to a string

😁 8
seancorfield23:06:05

I don't think you need that first step at all -- just call str/replace on the dna string you are passed in.

Rob Aguilera23:06:10

Ah, I didn't have to split it in the first place.

seancorfield23:06:14

user=> (defn to-rna
         [dna]
         (str/replace dna  #"C|G|A|T" {"C" "G" "G" "C" "A" "U" "T" "A"}))
#'user/to-rna
user=> (to-rna "ACGTGGTCTTAA")
"UGCACCAGAAUU"
user=> 

Rob Aguilera23:06:44

Sorry one more question, is that the best way to go about replacing those values? I find it a little hard to read.

Rob Aguilera23:06:05

At least the map at the end {"C" "G" ...}

seancorfield23:06:30

would you find it easier to read if you separated each pair with a comma?

seancorfield23:06:53

{"C" "G",  "G" "C",  "A" "U",  "T" "A"}

👍 4
Rob Aguilera23:06:25

Yup that helps. Forgot that Clojure ignores commas. Thanks @U04V70XH6

seancorfield23:06:58

I never think of using a map or function in the third arg of str/replace so that's quite elegant...

Rob Aguilera23:06:47

The commas definitely do help.