Fork me on GitHub
#beginners
<
2020-12-21
>
st3fan00:12:13

@seancorfield so i have something to explore to do here regarding testing macros .. my test worked fine in the repl, but not when running lein test - I fixed that by changing the quote for macroexpand from ' to ` (hard to write in slack)

seancorfield00:12:19

Hmm, regular ' should work but your tests need to also have the quoted expected form.

seancorfield00:12:30

dev=> (require '[clojure.test :refer [deftest is]])
nil
dev=> (macroexpand '(when a b))
(if a (do b))
dev=> (deftest when-test
        (is (= '(if a (do b))
               (macroexpand '(when a b)))))
#'dev/when-test
dev=> (when-test)
nil
dev=> 

seancorfield00:12:41

Yup, just verified that works with lein test @st3fan

seancorfield00:12:02

(! 999)-> lein new st3fan
Generating a project called st3fan based on the 'default' template.
The default template is intended for library projects, not applications.
To see other templates (app, plugin, etc), try `lein help new`.
(! 1000)-> cd st3fan/
(! 1001)-> vi test/st3fan/core_test.clj 
(! 1002)-> cat test/st3fan/core_test.clj 
(ns st3fan.core-test
  (:require [clojure.test :refer :all]
            [st3fan.core :refer :all]))

(deftest when-test
  (is (= '(if a (do b))
         (macroexpand '(when a b)))))
(! 1003)-> lein test

lein test st3fan.core-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

zackteo01:12:32

How do I deal with Unhandled java.lang.NoClassDefFoundError when calling a function from a Clojure library that uses a Java library?

hiredman01:12:42

It depends how and where and what class it says isn't defined

hiredman01:12:17

The message on the exception will say which class, the stack trace will tell you where

zackteo01:12:42

org/apache/commons/compress/utils/InputStreamStatistics Do I need to import it somehow?

hiredman01:12:24

You don't need to import it, but it needs to be on the class path, the exact details will depend on the tools you are using

zackteo01:12:42

Do you mean lein?

hiredman01:12:52

If it is a dependency of the library you using, typical whatever tools you are using will pull in the entire dependency tree and build a class path from it

hiredman01:12:45

Yes, lein or boot or clj or maven or even by hand

zackteo01:12:27

Could you link me to how I can do this? I've a feeling it might be related to me trying the library by cloning it - am trying https://github.com/zero-one-group/fxl btw

Domino02:12:40

@zackteo if you're using lein, you have to put [zone.one/fxl "0.0.5"] in your :dependencies in your project's project.clj

Domino02:12:20

and then run lein deps in the directory of your project to update your dependencies.

zackteo02:12:34

@ricardolopez.zagal I am running the code from within the project. It seems to have to do with cider actually ... am able to run my code within lein repl and using calva

Domino02:12:48

@zackteo Wait, are you running the code within the project that you cloned?

Domino02:12:51

@zackteo You don't need to clone dependencies using git Lein does it for you from clojars using lein deps if you you create a project using lein new foo , and you put [zone.one/fxl "0.0.5"] inside project.clj, and run lein deps, you'll be able to use the repl and to make your project using that dependency It's way more practical than cloning the dependencies from git, specially if you have to use multiple dependencies.

zackteo02:12:10

No no I think You got it confused πŸ˜… my bad. Am trying to work on the library itself

zackteo02:12:23

And my mini-test for the function seems to work within a basic lein repl and from calva. So it appears that cider might be doing something that causes some issues :x

zackteo02:12:15

No worries πŸ™‚ Now I know about using lein deps after updating dependencies

zackteo02:12:21

Okay got it fixed ... Think it has to do with me not updating cider because I was on emacs native-comp and doom emacs stop supporting the version I was on

dumrat05:12:10

How do I invoke this code blocking?

dumrat05:12:15

(go (let [response (<! (http/get ""
                                 {:with-credentials? false
                                  :query-params {"since" 135}}))]
      (prn (:status response))
      (prn (map :login (:body response)))))

dpsutton05:12:37

is this cljs?

dumrat05:12:43

I don't want any async stuff, it's just that the cljs-https requires this

dpsutton05:12:53

you can't. can't block in javascript

Jakub Zika09:12:07

Hello, what do you think is the better representation of database structure. Both ways have trade-offs, no?

{:db1
  {:tables 
    {"public.people" 
      {:columns {"id" {:data_type "int"}
                 "name" {:data_type "string"}}}}}}
or (more clojure.jdbc native)
{:db1 
  {:tables [
     {:table_name "public.people" 
      :columns [
        {:column_name "id" :data_type "int"} 
        {:column_name "name" :data_type "string"}]}]}}
Thanks

Alex Miller (Clojure team)14:12:49

sets and maps are better choices for lookup than vectors

Jakub Zika15:12:53

I did not consider to use sets for better lookup. Thank you for the idea.

holymackerels10:12:32

is there a way in clojure.math.combinators to get all of the permutations by taking one from each list in a list-of-lists? for example:

;; getting from this
[[:a1 :a2] [:b1 :b2]]

;; to these
:a1 :b1
:a1 :b2
:a2 :b1
:a2 :b2

holymackerels10:12:09

I've considered getting the permutations of the indexes, like (permutations [0 0 1 1]) and then using them as indexes in each inner list, so when theres 3 inner lists each with 2 items it'd be the permutation of [0 0 0 1 1 1] as indexes

Max Deineko11:12:05

Are you looking for cartesian-product?

holymackerels11:12:57

facepalm yes! thanks

πŸ‘ 3
holymackerels11:12:32

literally couldn't be any clearer in the description > ; all the ways to take one item from each passed-in sequence

yiorgos14:12:02

what is the most idiomatic or preferable way to read a file in Clojure, using slurp or io/reader?

clyfe14:12:34

Either; slurp loads it in memory and generally is ok with small files; With reader you can stream operations.

πŸ‘ 6
delaguardo14:12:25

slurp is using http://clojure.java.io/reader internally in with-open context so slurp will close reader after consuming all the content. if you are using http://clojure.java.io/reader explicitly do not forget to close the reader after you finish processing otherwise this could lead to memory leaks

πŸ‘ 9
Domino14:12:00

Exception in thread "Thread-8" java.io.IOException: Stream closed
        at java.io.BufferedReader.ensureOpen(BufferedReader.java:122)
        at java.io.BufferedReader.readLine(BufferedReader.java:317)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at clojure.core$line_seq.invokeStatic(core.clj:3091)
        at clojure.core$line_seq$fn__5970.invoke(core.clj:3092)
        at clojure.lang.LazySeq.sval(LazySeq.java:42)
        at clojure.lang.LazySeq.seq(LazySeq.java:51)
        at clojure.lang.LazySeq.equals(LazySeq.java:121)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:167)
        at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:102)
        at malachite_mk1.core$concurrent_collision$fn__318.invoke(core.clj:118)
        at clojure.lang.AFn.run(AFn.java:22)
        at java.lang.Thread.run(Thread.java:748)
#object[java.lang.Thread 0x64864f7e "Thread[Thread-9,5,main]"]
Oh boy, this is going to be fun to debug... /s

Alex Miller (Clojure team)15:12:35

usually laziness combined with io

Alex Miller (Clojure team)15:12:56

like a with-open that returns a lazy seq

Domino15:12:37

oh, yeah that's literally the thing I'm trying to do

Domino15:12:05

Like, I'm trying to read a file line by line This works fine in the non-concurrent version of the function, but it returns this error in the concurrent one πŸ˜•

Alex Miller (Clojure team)15:12:06

either return something eager (often with into ) or invert the control and pass the thing you want to do with the lazy seq into the with-open so it's completed in scope

Alex Miller (Clojure team)15:12:53

well, if you're doing io and concurrency, you need to think carefully about that

Alex Miller (Clojure team)15:12:40

a common pattern is to have one thread that just reads and queues work, then closes when done reading

Alex Miller (Clojure team)15:12:08

and "queue" could mean to use future to spin jobs, or use a Java executor, or put work on a core.async channel

dhd16:12:51

;; I have a question similar to domino's, but i am trying to understand lazy-seqs and not run into OOM issue. ;; Say I read the file in memory. I now need to transform/parse the data and then put this data into multiple sinks (database/streamin platform/search engine ...). IE, all the data needs to end up in all the sinks. ;; So i do this with map/filter and make it lazy. In the end I need to realize the sequence in order to store it into the sink(s). Form what i understand about lazy-seqs, i need to avoid holding onto the head of the lazy-seq. ;; But I am not sure what this really means. ;; In this example, am i holding onto the head of the lazy-seq? -- ;; sinks are partial functions which are configured with database config info

(defn transform-data [file-data]
  (->> file-data 
       (map ransform1)
       (map transform2)
       (filter filter1)
       (map transform4)))
;; I think I am holding onto the head here. When I go an sink the data into the first sink, I am realizing the data and it cannot get garbage collected because there are still other sinks remaining to process the data . Is this correct?
(def sink-all-data [sinks data]
  (doseq [sink sinks]
    (sink data)))
(sink-all-data partial-sinks (transform-data (data-from-file "/foo/large-file.txt")))

noisesmith18:12:28

you are not holding onto the head, because each time you consume a new element from "file-data", the previous element can be freed

noisesmith18:12:23

the head of a lazy seq is the first element, there's nothing in that code that points to the first element of the seq and escapes scope

noisesmith18:12:35

now file-data itself could be the head of a lazy seq, that means the culprit isn't the code you shared, it's the code that creates a lazy-seq from the input and returns the first element

noisesmith18:12:09

> Say I read the file in memory. the point is to avoid this - to find a way that the entire file doesn't need to be in memory

valerauko15:12:50

we use core.async channels for this

Domino15:12:54

I'll look into that, thanks for the hint! πŸ™‚

0xclj15:12:47

At my current work, the variables we use seem to be max 3 characters, like lid, pid, mv etc. which I find are uninterpretable. When querying about it, I was told it was because we use the NoSQL document storage and short names like that help save cost. Can anyone with the relevant experience (Mongo or Azure CosmosDB) comment on that rationale?

hequ17:12:00

What is the preferred way to handle dates in clojure?

dharrigan17:12:32

I use atm, but if I was to do anything new, I would probably just use the java date time classes directly (if on java 8+) as they are nice to use and interop works really well.

πŸ‘ 6
hequ17:12:09

I was looking at that library as it seems nice but thought that maybe I ask first if people use any libraries or directly java8 api

ryan echternacht17:12:32

I think using the java8 interop is the preferred way now, especially if you're greenfield

dharrigan17:12:03

yeah, I would hit the java 8 apis directly now (or java 11, as I'm on that jdk)

dharrigan17:12:21

I may even spend some time these holidays to do that

hequ17:12:31

Ok, maybe I’ll try that as well, thanks πŸ™‚

dharrigan17:12:36

you're most welcome

dhd17:12:47

I asked this question in a thread. Sharing it with the channel.

popeye19:12:21

Team, (re-matches #"^[a-z\-]+$" "abc--") will give us the result, But if i send 2 hypen it should return nil, How can I achieve this

dgb2319:12:48

(re-matches #"^[a-z]+\-$" "abc-")

dgb2319:12:26

assuming you want to match on a string with an arbitrary combination of letters plus a single hyphen at the end.

πŸ™Œ 3
ghosttoaster20:12:14

Is it possible to run a public static main method from a generated class from within a repl?

noisesmith20:12:04

yes, (ClassName/main (into-array String [arg1 arg2 ...]))

ghosttoaster20:12:30

Whoa so you have to have a String array even if its empty?

noisesmith22:12:36

you can provide an empty string array, but varargs are treated as arrays on a byte code level, and unlike java clojure makes no attempt to hide this

noisesmith22:12:09

I might be misremembering, shouldn't be hard to try both

GGfpc20:12:13

(defn get-user-books
  "Retrieves a user's books"
  [user consumer token]
  (for [i 1
        books {}]
    (let [response (obtain-books i)
          updated-books (conj books response)]
      (if (< 50 (count response))
        updated-books
        (recur updated-books (inc i))))))
This code fails to compile with Can only recur from tail position but isn't recur the last statement?

J20:12:19

Hi! It’s possible to use a private git repo with deps.edn?