Fork me on GitHub
#beginners
<
2022-06-06
>
oly08:06:47

So I am using clojure logging and logback, I have setup the dsn in logback but I am noticing when I use log warn or any fn from clojure logging it does not make it to sentry, general exceptions and any direct calls to the sentry library work. Any idea what I may be doing wrong should clojure logging respect the logback config ?

Mihai Chirculescu08:06:06

Super noob here. I'm reading a book and I'm trying to figure something out. I have a clojure file and 2 terminals. In first terminal I run lein repl and then (-main). I get the output as expected. Then I change the content of the file and save it. In the other terminal (not in repl), I'm running lein compile. Getting back to repl , I rerun (-main) , but I get the old output (before recompiling). This is super strange to me, coming from other languages with heavy repl interaction (eg: Ruby). It works as expected if I exit repl and reenter it (outputs what is modified), but I don't want to do that each time. How to do it (run the new binaries) without exiting repl from repl, obv?

oly09:06:46

usually you either paste the function into the repl to get the updated version or you have an editor connected which will send the updated version to the repl

oly09:06:37

calling something like eval buffer or sexp in what ever editor your using, after fist calling jack in / connect

Mihai Chirculescu09:06:07

Thanks! I'll look into it.

oly09:06:45

I would look up a guide for which ever editor your using on connecting to you project and evaluating code, on the code youtube channel likely has a good one for something like vscode

👍 1
Mihai Chirculescu09:06:56

Yup, VS Code happens to be exactly the editor I'm using 🙂 . Don't want to get into emacs yet and learn all the hot keys since for the moment I'm learning Clojure just for fun.

Ben Sless09:06:41

The editor you're using doesn't really matter here, what matters is you work from your editor and try not to create some weird state in your working directory. Calling lein compile might do that. If you change a definition, eval that definition again from your editor and you're good

Mihai Chirculescu09:06:18

> Calling lein compile might do that. It doesn't, as stated. And it's confusing that it doesn't. By "eval" you mean copy/paste, I guess. I don't want to do that either because it's multiline code and I want to keep my history clean (pressing up arraow to get previous command).

Ben Sless09:06:07

A good practice to adopt is to not type into the REPL Connect an editor and send the form you want to update with it

👍 1
Ben Sless09:06:41

That way you also have all your history in a file

Ben Sless09:06:20

And you can end up turning it into your code, instead of jumping back and forth between terminal and editor

Mihai Chirculescu09:06:21

Right. Makes a lot of sense. 👍

Ben Sless09:06:16

If you use lein compile it compiles clojure files to class files, you don't need to do that. Can I ask why you used it?

Mihai Chirculescu09:06:20

No good reason whatsoever. Just doing random stuff around, try to see what it does and try to understand why. Thanks for the help. 🙂

teodorlu11:06:55

Adding to Ben's comments, Calva (Clojure extension for vscode) has a great getting started guide which will introduce you to idiomatic clojure development :) https://calva.io/getting-started/

👍 1
talentedleader09:06:10

Is there anyway to turn a set into a list?

talentedleader09:06:41

I am trying a test, and test windows tells it is a failure, I believe it is because I am outputting a set

talentedleader09:06:09

Here is the output:

talentedleader09:06:11

actual:
#{"/Fotos/Mallorca-2017/dc-10.jpg" "/Fotos/Azoren-2018/buffet" "/Fotos/Azoren-2018/restaurant/dc-43.jpg" "/Fotos/Azoren-2018/restaurant/dc-42.jpg" "/Fotos/Mallorca-2017/dc-19.jpg" "/Fotos/Azoren-2018/restaurant/dc-41.jpg" "/Fotos/Mallorca-2017/dc-11.jpg" "/Fotos/Azoren-2018/restaurant/dc"}
expected: (= expected actual)
  actual: (not (= "/Fotos/Azoren-2018/buffet\n/Fotos/Azoren-2018/restaurant/dc\n/Fotos/Azoren-2018/restaurant/dc-41.jpg\n/Fotos/Azoren-2018/restaurant/dc-42.jpg\n/Fotos/Azoren-2018/restaurant/dc-43.jpg\n/Fotos/Mallorca-2017/dc-10.jpg\n/Fotos/Mallorca-2017/dc-11.jpg\n/Fotos/Mallorca-2017/dc-19.jpg" #{"/Fotos/Mallorca-2017/dc-10.jpg" "/Fotos/Azoren-2018/buffet" "/Fotos/Azoren-2018/restaurant/dc-43.jpg" "/Fotos/Azoren-2018/restaurant/dc-42.jpg" "/Fotos/Mallorca-2017/dc-19.jpg" "/Fotos/Azoren-2018/restaurant/dc-41.jpg" "/Fotos/Mallorca-2017/dc-11.jpg" "/Fotos/Azoren-2018/restaurant/dc"}))

talentedleader09:06:42

I need to give an output like this:

talentedleader09:06:45

/Fotos/Azoren-2018/buffet
/Fotos/Azoren-2018/restaurant/dc
/Fotos/Azoren-2018/restaurant/dc-41.jpg
/Fotos/Azoren-2018/restaurant/dc-42.jpg
/Fotos/Azoren-2018/restaurant/dc-43.jpg
/Fotos/Mallorca-2017/dc-10.jpg
/Fotos/Mallorca-2017/dc-11.jpg
/Fotos/Mallorca-2017/dc-19.jpg

talentedleader09:06:09

But I think my output is a set: #{"/Fotos/Mallorca-2017/dc-10.jpg" "/Fotos/Azoren-2018/buffet" "/Fotos/Azoren-2018/restaurant/dc-43.jpg" "/Fotos/Azoren-2018/restaurant/dc-42.jpg" "/Fotos/Mallorca-2017/dc-19.jpg" "/Fotos/Azoren-2018/restaurant/dc-41.jpg" "/Fotos/Mallorca-2017/dc-11.jpg" "/Fotos/Azoren-2018/restaurant/dc"}

talentedleader09:06:30

Here is my code:

talentedleader09:06:33

(ns dirdiff.core
  (:gen-class))
(require '[clojure.set])

(defn no-prefix [prefix]
    (comp (filter #(clojure.string/starts-with? % prefix))
          (map #(subs % (count prefix)))))

(defn load-string-set [a file]
    (->> file
         slurp
         clojure.string/split-lines
         (into #{} a)))


(defn deleted-files
  "Die Funktion gibt einen String zurück, der beschreibt, welche Dateien gelöscht wurden.
   Um dies zu ermitteln, nimmt sie zwei mit dem Befehl find erstellten Dateien entgegen.
   prefix-davor bezeichnet das Prefix, welches von den Zeilen in der davor-Datei vor dem Vergleich entfernt werden soll.
   prefix-danach bezeichnet das Prefix, welches von den Zeilen in der danach-Datei vor dem Vergleich entfernt werden soll.
   davor bezeichnet die Datei als String, die den ersten Dateisystemzustand beschreibt.
   danach bezeichnet die Datei als String, die den zweiten Dateisystemzustand beschreibt."
  [prefix-davor prefix-danach davor danach]
  ; TODO
(disj (clojure.set/difference (load-string-set (no-prefix prefix-davor) davor)
                        (load-string-set (no-prefix prefix-danach) danach)) "/Fotos/Azoren-2018/buffet/dc-40.jpg"
"/Fotos/Azoren-2018/buffet/dc-41.jpg"
"/Fotos/Azoren-2018/buffet/dc-42.jpg"
"/Fotos/Azoren-2018/buffet/dc-43.jpg"))


  
(deleted-files "davor" "danach" "resources/davor.txt" "resources/danach.txt")

talentedleader09:06:55

Here is the test file:

talentedleader09:06:02

(ns dirdiff.core-test
  (:require [clojure.test :refer :all]
            [dirdiff.core :refer :all]))

(deftest show-deleted-test
  (testing "Find deleted files"
           (let [expected (slurp "resources/erwartet.txt")
                 actual   (deleted-files "davor" "danach" "resources/davor.txt" "resources/danach.txt")]
             (is
               (= expected
                  actual)
               (str "erwartet:\n" expected "\n\nactual:\n" actual)))))

talentedleader09:06:18

And here is the bash line command window in full version:

talentedleader09:06:28

cloud9.bewerber2:~/environment/dirdiff $ lein test

lein test dirdiff.core-test

lein test :only dirdiff.core-test/show-deleted-test

FAIL in (show-deleted-test) (core_test.clj:9)
Find deleted files
erwartet:
/Fotos/Azoren-2018/buffet
/Fotos/Azoren-2018/restaurant/dc
/Fotos/Azoren-2018/restaurant/dc-41.jpg
/Fotos/Azoren-2018/restaurant/dc-42.jpg
/Fotos/Azoren-2018/restaurant/dc-43.jpg
/Fotos/Mallorca-2017/dc-10.jpg
/Fotos/Mallorca-2017/dc-11.jpg
/Fotos/Mallorca-2017/dc-19.jpg

actual:
#{"/Fotos/Mallorca-2017/dc-10.jpg" "/Fotos/Azoren-2018/buffet" "/Fotos/Azoren-2018/restaurant/dc-43.jpg" "/Fotos/Azoren-2018/restaurant/dc-42.jpg" "/Fotos/Mallorca-2017/dc-19.jpg" "/Fotos/Azoren-2018/restaurant/dc-41.jpg" "/Fotos/Mallorca-2017/dc-11.jpg" "/Fotos/Azoren-2018/restaurant/dc"}
expected: (= expected actual)
  actual: (not (= "/Fotos/Azoren-2018/buffet\n/Fotos/Azoren-2018/restaurant/dc\n/Fotos/Azoren-2018/restaurant/dc-41.jpg\n/Fotos/Azoren-2018/restaurant/dc-42.jpg\n/Fotos/Azoren-2018/restaurant/dc-43.jpg\n/Fotos/Mallorca-2017/dc-10.jpg\n/Fotos/Mallorca-2017/dc-11.jpg\n/Fotos/Mallorca-2017/dc-19.jpg" #{"/Fotos/Mallorca-2017/dc-10.jpg" "/Fotos/Azoren-2018/buffet" "/Fotos/Azoren-2018/restaurant/dc-43.jpg" "/Fotos/Azoren-2018/restaurant/dc-42.jpg" "/Fotos/Mallorca-2017/dc-19.jpg" "/Fotos/Azoren-2018/restaurant/dc-41.jpg" "/Fotos/Mallorca-2017/dc-11.jpg" "/Fotos/Azoren-2018/restaurant/dc"}))

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

talentedleader09:06:49

I believe the failure is caused because I couldnt give this exact output:

talentedleader09:06:51

/Fotos/Azoren-2018/buffet
/Fotos/Azoren-2018/restaurant/dc
/Fotos/Azoren-2018/restaurant/dc-41.jpg
/Fotos/Azoren-2018/restaurant/dc-42.jpg
/Fotos/Azoren-2018/restaurant/dc-43.jpg
/Fotos/Mallorca-2017/dc-10.jpg
/Fotos/Mallorca-2017/dc-11.jpg
/Fotos/Mallorca-2017/dc-19.jpg

talentedleader09:06:00

Any ideas how can I convert that set into this output?

🧵 2
talentedleader10:06:22

I am sorry, I am new here. I did not know that we should reply ourselves in one thread...

Stuart11:06:57

Is the problem that its just not sorted ?

Stuart11:06:05

as sets aren't sorted

Stuart11:06:36

(the output to me looks sorted), so just call (sort) in your load-string-set method. But why put it into a set in the first place if you don't want set ? That's what (into #{} does. it puts it into a set.

talentedleader12:06:03

Thank you Stuart, I did the sort and sorted them as well... I lack the knowledge of ways to comparing the two text files, so all I could find and understand was the part with

(clojure.set/difference (load-string-set (no-prefix prefix-davor) davor)
                        (load-string-set (no-prefix prefix-danach) danach))

talentedleader12:06:45

And I understood it just automatically creates a set, with the elements that differ between two of the functions (load-string-set ....)

Stuart12:06:36

ah yep, ok so that will give you the elements that are in one set and not in the other, so if both sets are the same, then the resulting set should be empty.

talentedleader12:06:41

Sadly I just manually deleted the 4 text files, because they shouldnt be included, only the main file regarding them should be there: /Fotos/Azoren-2018/buffet

talentedleader12:06:07

I couldnt find a way to get that result by only comparing...

dorab16:06:00

Instead of converting the set to a list and then comparing lists, have you considered doing the converse - converting the list to a set and then comparing sets? The idea being that sets are not sorted and are guaranteed to not have duplicate elements.

talentedleader16:06:25

I think for now I have spent so much time on sets, it would be better to go on with sets, I have very limited time left sadly

talentedleader16:06:45

I cant explain what really happens here:

talentedleader16:06:48

(defn no-prefix [prefix]
    (comp (filter #(clojure.string/starts-with? % prefix))
          (map #(subs % (count prefix)))))

talentedleader16:06:06

I would appreciate it if you can help me understand what happens here, in each line

dorab17:06:03

It's a bit complicated but let me try. (map #(subs % (count prefix)) returns a function. A transducer, in this particular case. But for now, just think of it as a higher-order function. This function takes a collection of strings and returns a collection of strings with some number of characters removed from the beginning. The number of characters removed is the number of characters in one of its parameters prefix. (filter #(clojure.string/starts-with? % prefix) returns a function. Also a transducer as above. This function takes a collection of strings and keeps only those strings that start with prefix. Strictly speaking the return values of both functions are lazy sequences, but for now, I'll just use the term "collections" to keep things simple. There are also complexities around transducers that I am purposefully ignoring. comp is a composition of functions. So, no-prefix is a function that takes a collection of strings that keeps only those strings that start with prefix and then removes the prefix from the beginning of each string. If you're not familiar with the Clojure functions, you can read the documentation at clojuredocs. For example, the filter function is at https://clojuredocs.org/clojure.core/filter

talentedleader17:06:57

Thanks @U0AT6MBUL, you are the best!

Mihai Chirculescu09:06:09

Clojure uses the Boolean operators or and and. or returns either the first truthy value or the last value. and returns the first falsey value or, if no values are falsey, the last truthy value. This makes sense from a logical point, given what is truthy in Clojore and what is not. But what would be a valid example in which you would want to use and or or in order to receive an actual value that will not be evaluated as boolean? Is it common practice? For the moment, for me, it would only make the code more difficult to read to use and or or for non-bools return type instead of some other function.

Ben Sless09:06:17

(or user-provided-thing (create-default-thing ,,,))

1
👍 1
1
ghadi10:06:15

Yeah, it’s very common (if-let [f (and sunny? sun-protection-routine)]

👍 1
Mihai Chirculescu10:06:02

Thanks, will get back to your example in the future.

Mihai Chirculescu11:06:20

In your example, wouldn't replacing and with an if work the exact same way? If yes, why not using if since it's easier to read the code?

Mihai Chirculescu11:06:50

Ah, no, return would be nil , I think.

Mihai Chirculescu11:06:28

Alright, I get it. Thank you!

Eric20:06:42

if-let is a shorter way of writing a (let [val ... followed by a nested (if val ... to avoid the nesting. I came across it for the first time in this example from the documentation for not-empty. https://clojuredocs.org/clojure.core/not-empty#example-5e8e0242e4b087629b5a18d0

Dad-Shoes12:06:48

Hello, I am getting started and am having trouble finding a router similar to react-router in js. I have looked into re-frame and reitit and both seem to be more complex than I need. Does anyone have a recommendation for a router to help switch between tabs in an SPA? Thank you in advance 🙂

teodorlu13:06:38

You want to have working links like http://yoursite.com/#page1 or http://yoursite.com/#page2? In your shoes, I think I’d either use reitit, or listen to https://developer.mozilla.org/en-US/docs/Web/API/Window/hashchange_event directly.

teodorlu13:06:29

You might get better answers in other channels - for example #clojurescript, #reagent or #reitit.

Dad-Shoes13:06:38

I think that's what I am looks for. I'll spend sometime playing with it. There is a ton out there so I wasn't sure which one to spend my time on.

👍 1
Daniel Craig13:06:17

You could also consider bidi https://github.com/juxt/bidi

👍 1
oly13:06:24

How would I set this "-Dapi.googleads.maxLogMessageLength=-1" when running clj -Mrun is it possible ? or do I set it in deps somehow ?

Alex Miller (Clojure team)13:06:05

on cli, clj -J-Dapi.googleads.maxLogMessageLength=-1 -M:run

oly13:06:23

ah -J-D is what I was missing 🙂

Alex Miller (Clojure team)13:06:27

in :run alias, you would set :jvm-opts ["-Dapi.googleads.maxLogMessageLength=-1"]

Alex Miller (Clojure team)13:06:58

note that -M takes aliases, which are keywords and should start with a colon

oly13:06:14

ah cool thanks for that, I did not have the correct terminology to find it in google

Alex Miller (Clojure team)13:06:42

also see clj -h or man clj

oly13:06:47

I think I looked on that page and searched for -D, I think its a java terminology thing, is it a param a property a setting etc

Alex Miller (Clojure team)14:06:36

those are called Java system properties

oly14:06:38

okay cheers thanks for your help, it got me the logs I needed 🙂

oly14:06:06

I seem to be doing a lot more interop these days so I often get stuck by not knowing the terminology from the java world

Eugene Mosh14:06:09

Hello friends! What is Luminus? Just set of templates or something more? And what is the difference between Luminus and Kit?

practicalli-johnny15:06:49

Luminus is a template to generate projects that provide working code and respective libraries. The generated project provides examples of how various libraries are typically coded together, so useful as a learning tool even if you dont used the template for your actual projects. Luminus has many options to tailor how a project is created, enabling a range of different clojure, clojurescript or fullstack projects. Kit is a relatively new project that takes a more data centric approach compared to Luminus, with Integrant and reitit Luminux and Kit projects have quite a lot in common with each other apart from that) If you havent used Luminus yet, then I'd suggest starting with Kit (it uses reitit for routing which is very nice)

practicalli-johnny15:06:14

There is a #kit-clj channel for specific help with Kit, although the documentation of the project looks very detailed.

Eugene Mosh17:06:46

Thanks a lot!!

👍 1
popeye16:06:24

I am reading the data from a file, and How to identify if the data has reached more than 6mb?

Drew Verlee23:06:37

What do you mean by "the data" you could read a file and not store the result. I'm guessing how you choose to store the data (hashmap vs vector vs string) will impact the size.

R.A. Porter05:06:04

If your goal is to read only up to 6mb and fail if your input is larger, you could use a java.nio.ByteBuffer allocated to the specified limit. If you wanted to truncate at your max (which would be odd and potentially a problem depending on source file type), you could do that just by tracking the count of bytes read. In both those cases, you’d be managing the reading in a loop.

R.A. Porter05:06:01

But if it's actually a file and not an arbitrary input stream, it's best to ask the OS for the file size prior to reading it at all.

popeye08:06:35

re phasing my question