Fork me on GitHub
#beginners
<
2019-12-24
>
Hi07:12:56

I guess that js->clj` only available in Clojurescript and I have to use a lib for parsing JSON.

andy.fingerhut07:12:23

There is no function js->clj built into Clojure that runs on the JVM, if that is what you are asking, and yes, there are libraries for reading JSON readily available, including the data.json contrib library and Cheshire

4
andy.fingerhut07:12:25

That is what you get when you try to evaluate a symbol that has no definition. Were you expecting something else?

Vincent Cantin08:12:59

is there a simpler way to convert a namespaced keyword into a namespaced symbol, compared to that? (symbol (namespace :a/b) (name :a/b))

Vincent Cantin08:12:00

oh .. I tried (symbol :a/b) and it worked, never mind.

Vincent Cantin10:12:32

What is the correct way to get the namespace where a macro is used? I tried (ns-name *ns*) but it does not resolve to the right namespace when I run it in the tests (note: I used the test runner inside IntelliJ).

noisesmith18:12:59

*ns* is the namespace that's currently active, and people's intuitions of what that should be is often (usually?) wrong.

noisesmith18:12:15

do you want the ns of the form that invoked the macro?

noisesmith18:12:57

here this macro accurately knows the namespace it is used in:

(cmd)user=> (ns some.other.ns)
nil
(cmd)some.other.ns=> (defmacro knows-the-ns [] `(quote ~(ns-name *ns*)))
#'some.other.ns/knows-the-ns
(cmd)some.other.ns=> (some.other.ns/knows-the-ns)
some.other.ns
(cmd)some.other.ns=> (in-ns 'user)
#object[clojure.lang.Namespace 0x3b77a04f "user"]
(cmd)user=> (some.other.ns/knows-the-ns)
user
(cmd)user=> (in-ns 'clojure.core)
#object[clojure.lang.Namespace 0x27305e6 "clojure.core"]
(cmd)clojure.core=> (some.other.ns/knows-the-ns)
clojure.core

noisesmith18:12:31

it still knows where it was first expanded if used from another ns

(ins)clojure.core=> (in-ns 'user)
#object[clojure.lang.Namespace 0x3b77a04f "user"]
(ins)user=> (defn ns-known [] (some.other.ns/knows-the-ns))
#'user/ns-known
(ins)user=> (user/ns-known)
user
(cmd)user=> (in-ns 'clojure.core)
#object[clojure.lang.Namespace 0x27305e6 "clojure.core"]
(cmd)clojure.core=> (user/ns-known)
user

👍 4
Vincent Cantin13:12:00

I did the same as you did and it works in my program but not in the tests. I suspect that it’s the test environment of IntelliJ which is launching/evaluating the tests without switching to the namespace of the file in which they are defined.

noisesmith18:12:51

weird... - could be a #cursive bug

wactbprot11:12:54

Hi all, I want to have some example data (e.g. maps containing strings) for my functions. Is it ok to provide these via the meta data feature or would this be a abuse?

delaguardo12:12:39

this is completely ok if you want to add tests to your function. https://clojuredocs.org/clojure.core/test but it is better to keep them separately or inside of function body if you need those samples as a part of function’s logic

wactbprot12:12:02

thx for the answer, what do you mean by > inside of function body how, as a comment?

delaguardo12:12:58

(let [sample-data ...]
  (do-somthing-with-sample-data))

delaguardo12:12:56

inside of function body is applicable only to the case when you need that data to compute the function

wactbprot12:12:19

ok, I understand, thx again!

jakuzure13:12:25

hi, so I have a function getdata where I make vectors to combine some data: (map #(vec [%1 %2 %3 %4]) (getartist desc) (getsong desc) shortcode acc_captions) I want to output this to a csv file like so:

(with-open [writer (io/writer "out-file.csv")]                                              │·····
  (csv/write-csv writer                                                                     │·····
                 [["Titel" "Interpret" "Link" "Beschreibung"]                               │·····
                  getdata]                                                          │·····
                 :separator \;))  
but it doesn't do what it's supposed to do, I guess because I need to somehow untangle the vector of vectors first? (first getdata) works, but I'm not sure how to do if for all the vectors, can anyone help?

delaguardo13:12:01

(cons ["Titel" "Interpret" "Link" "Beschreibung"] getdata) something like this? write-csv expects data to be in the form of vector of vectors

jakuzure13:12:47

that did the trick! thanks very much

category13:12:59

Hi all, just confirming ring-mock is still the best way to do TDD with ring ?

Gulli13:12:56

I'm a beginner, but do you actually need mocks in FP?

Enyert Vinas13:12:17

I think you need mocks in any paradigm. Because is the way to test the difference responses from an external source. At the end you want to isolate your unit tests from side effects

Gulli14:12:19

That's true

smashedtoatoms14:12:09

You can also pass in instances or functions that make the external calls to your functions and not use a lib at all. I haven't used a mocking lib in any language in 5ish years. It has the added perk of making repl dev easier too.

category18:12:25

thanks, are you able to point to any examples of the above for ring?

hindol20:12:09

Also look at shrubbery. Makes it really easy to create mock implementations from a protocol. You will still need to structure your code so that the external dependency is passed in as a parameter, like @UR2C8GK1R said.

hindol20:12:41

What exactly about ring? Do you want to mock HTTP calls?

category01:12:54

@UJRDALZA5 Nope, just > pass in instances or functions that make the external calls to your functions and not use a lib at all for TDD in ring

hindol04:12:05

I did this recently. I created a protocol Client wrapping the external dependency.

(defprotocol Client
  "A JSON-RPC client."
  (open [this url] "Opens a connection to the given URL")
  (send! [this conneciton message] "Sends a JSON-RPC request to the open connection")
  (close [this conneciton] "Closes the connection"))
Here is the test.
(deftest send!-test
  (let [id       (uuid)
        response (json/write-str {:jsonrpc "2.0"
                                  :result  "0x0"
                                  :id      id})
        client   (mock client/Client {:send! response
                                      :close nil})]
    (testing "open can open channels for all supported schemes"
      (doseq [url [""
                   ""
                   ""
                   ""
                   "unix:///var/run/geth.ipc"]]
        (let [channel (open url :route-fn (fn [_] client))]
          (is (= [:send!-fn :close-fn] (keys channel)))
          (try
            (is (= {:result "0x0"
                    :id     id}
                   (send! channel "eth_blockNumber" ["latest"] :id id)))
            (finally (close channel))))))))
The mocked client is passed via :route-fn. Complete code in this repo: https://github.com/Hindol/json-rpc

jysandy04:12:41

@US3519YR5 you could also stub Clojure functions using with-redefs. https://clojuredocs.org/clojure.core/with-redefs This would be my preferred method of mocking where possible since you won’t need to create protocols specifically for testing.

Jordan Robinson15:12:17

Hi all, I have a small question that has had me stumped for a little while. I need to be able to filter this vector on the nested field "classifier"

[{:name "foo",
  :type "foo",
  :path "foo/foo",
  :classification [{:other_type "x", :classifier "A"}]}
  {:name "bar",
  :type "bar",
  :path "foo/bar",
  :classification [{:other_type "y", :classifier "B"}]}]
I can get the value with (:classifier (first (:classification (first coll)))) where coll is the data, but that of course assumes that it would be the first value. I've tried quite a few things around filter and get-in but because the value is nested in a vector, then a map, then a vector, then a map, this seems quite difficult Is there something obvious that I'm missing?

enforser17:12:58

I think the step you’re looking for is that you want two iterators - one to go over the the initial vector, and one to go over the :classification values for each map. Maybe something like:

(defn foo
  [x]
  (filter #(some (comp (partial = "A") :classifier) (:classification %)) x))

enforser17:12:09

This keeps all of the objects in the initial vector with a classifier A, you can change the #(some ...) to check if the value under :classification is what you want to keep. Using an iterator instead of first allows you to check more than just one item in that vector.

Jordan Robinson18:12:15

hey, thanks very much! That helps a lot - I found my own solution about 30 mins ago and was about to post an update, but I think your solution is much more elegant so I'll probably use that 😄

Jordan Robinson18:12:11

my solution looks like this:

(defn get-classifications 
  [item]
  (map #(:classifier %) (:classifiers item)))

(defn item-with-classification 
  [classification] 
  (filter #(some #{classification} (get-classifications %)) items))

Jordan Robinson18:12:06

I definitely think yours is better though, thanks again! 👍

hiredman20:12:50

(for [x m [k v] x :where (= k : classification) y v :where (= "A" (:classifier y))] x) or something like it

hiredman20:12:41

Get rid of the map destructuring that is more of a generic tree traversal thing

Calyce16:12:22

Hello, small question regarding destructuring in a let. Is it possible to do in one pass something like [a _ b] ["foo" "bar" "baz"] and having "a" as a keyword ? I tried [#(keyword %) _ b] but it's not working.

bronsa16:12:27

destructuring is about "pulling out" not transforming values

Calyce16:12:36

Thanks. I just wanted to be sure that I was not missing a feature ;-)

Raj16:12:53

Hi there! Can anyone help me out with clojurewerkz/buffy? How do you read from an input-stream into buffy buffer?

Renzo Tomlinson22:12:31

i'm trying to understand the :aliases section in the deps.edn file. I read the aliases section from https://clojure.org/reference/deps_and_cli but don't really understand the context in which these aliases working. I sorta understand the concept for defining aliases, allows me to bind a symbol to a namespace outside of mine to make it easier to reference, but I don't see if or how that translates to defining aliases in the deps.edn The particular deps.edn i'm struggling with is from the cdk-clj example. https://github.com/StediInc/cdk-clj/blob/master/examples/basics/deps.edn

andy.fingerhut22:12:55

A quick comment: An alias inside of Clojure, and :aliases inside of deps.edn, aren't really directly related to each other, except that they both have alias in their names.

Renzo Tomlinson22:12:17

ah okay, that is immensely helpful

andy.fingerhut22:12:19

Meaning, creating one does not affect the other.

Renzo Tomlinson22:12:29

should I think of deps.edn as "outside" of clojure?

andy.fingerhut22:12:41

It is outside of the Clojure program, yes.

andy.fingerhut22:12:38

An alias in deps.edn is a way of saying "here is one, or several, dependencies, or JVM command line options to use, etc. that I sometimes want to use when starting Clojure, but probably not all of the time. Give that collection a short name, so I can use that short name on the command line to include those"

Renzo Tomlinson22:12:30

i think i sorta get it. there's a json file (cdk.json) that I have defined which just has

{"app":"clojure -A:dev -i cdk/stedi/lambda_creator/cdk.clj}
cdk is using this command to run clojure with alias dev

hindol04:12:43

Just being pedantic, the alias is :dev which is specified directly after -A. The : is not a separator, it is part of the alias, just like in deps.edn.

Renzo Tomlinson21:12:32

oh, thanks for pointing that out 🙂

Renzo Tomlinson23:12:39

ah okay, I think im getting it

Renzo Tomlinson23:12:46

thank you. this has been really helpful