Fork me on GitHub
#beginners
<
2020-07-22
>
UrsaCalc06:07:36

What the best way design clj fn that eliminates state ( like config\db connection etc)

lsenjov06:07:10

• IO boundaries with pure functions underneath • binding dynamic vars • Closures over db connections

UrsaCalc06:07:22

@lsenjov can you give some example ( binding and closure over DB), thx

lsenjov06:07:17

Binding lets you bind a dynamic variable. It’s technically still stateful but it’s convenience for things like db connections/configs https://clojuredocs.org/clojure.core/binding for examples

lsenjov06:07:50

IIRC binding also carries down the stack, not just in the function it’s called

lsenjov06:07:35

Closures over connections is probably not for this, but it’s passing down an initialised function/class down the stack for usage as an argument

(let-fn [db (init-db {:connstring "asdf"})]
 (do-things-with-db db))

lsenjov06:07:19

Also check out the mount library for handling state like this

Stas Makarov11:07:34

Hi! How can I make these functions prettier?

(defn add-days
  ;; Adds number of days to the js date object.
  ;; Months will roll over (  )
  [date days]
  (let [copy (js/Date. (js/Number date))]
    (. copy setDate (+ (. copy getDate) days))
    copy))

(defn today []
  (let [now (js/Date.)]
    (. now setHours 0 0 0 0)
    now))

jsn13:07:20

you should probably use doto

Stas Makarov17:07:32

Thanks! I think it looks better now, but probably there's a room for improvement still..

(defn today []
  (doto (js/Date.) (. setHours 0 0 0 0)))

(defn add-days
  ;; Adds number of days to the js date object.
  ;; Months will roll over (  )
  [date days]
  (let [copy (js/Date. (js/Number date))
        val (+ days (. copy getDate))]
    (doto copy (. setDate val))))

jsn20:07:59

(doto (js/Date. date) (.setDate (+ days (.getDate date))) ?

Chicão12:07:30

Hi, someone can help me? I have this object

#object[Transit$TaggedValue [TaggedValue: f, 100.0]]
And I want to convert to number 100.0 I don't know how do it. in the frontend it shows [TaggedValue: f, 100.0]

Chicão12:07:43

I try use [cognitect.transit :as t]

Aviv Kotek14:07:59

hey, for simple XML creation/parsing, what is the differences between clojure.xml and clojure.data.xml, I see data.xml has more features, why having both libs?

alexmiller14:07:22

clojure.xml is a very old stab from early in the Clojure language and should be considered deprecated at this point

Aviv Kotek14:07:15

hi Alex, how would you traverse such structure? (data.xml.Element), I'd like some easy traversal like in clojure.zip, basically to parse an XML input

alexmiller14:07:07

you can use clojure.zip

Aviv Kotek08:07:38

so basically why would I need the data.xml, if I anyway move my data-structure to a zipper? why not just load directly to zipper or build a zipper? I mean, instead of String->data.xml->zipper and opposite why not just String->zipper, without using data.xml,

Aviv Kotek08:07:49

what is the usage of data.xml that I don't have with clojure.zip, thanks!

alexmiller14:07:48

we have not removed it so as not to break any existing code (have not yet gotten around to marking it deprecated but we will)

alexmiller14:07:00

so, use clojure.data.xml

Zebra14:07:17

Is there a way to dynamically start/stop and add/remove components using Stuart Sierra component library? All examples i've seen are pretty static

noisesmith16:07:07

if you hold the component system in a var, you can stop it (or stop parts of it) whenever

Aviv Kotek14:07:30

thanks alex!

seancorfield16:07:50

@dobbey.have.socks It's complicated in general because start / stop return a new instance of the component so you would have to rebuild the entire system. Adding and components dynamically is possible (before you start the system -- for the same reason as stated): you just assoc them in, but again that returns a new instance of the system.

seancorfield16:07:07

(there's a #component channel if you want to dig deeper)

naxels16:07:40

Quick question, I found a filter function online that helps me filter my xml-seq into the correct filter, however don’t know how it ‘works’

(def navPoints
  (->> document
       xml-seq
       (filter (comp #{:navPoint} :tag))))
In my understanding, this would mean (from Clojure book):
((comp f1 f2 f3) x) is equivalent to (f1 (f2 (f3 x)))
but then when i ‘decomp’ this, i can’t seem to make it work:
(filter #({:navPoint (:tag %)}))
What am I missing?

naxels16:07:49

^ this returns an error btw

naxels16:07:59

i get that #{} is a set with unique values

naxels16:07:19

but guess i don’t understand comp that well

naxels16:07:19

i also tried:

(filter #(#{:navPoint (:tag %)}))
which fails as well

naxels16:07:47

using map I can recreate what I am looking for after some struggling:

(map #{:navPoint} (map :tag a))
but don’t understand why without #{} won’t work:
(map :navPoint (map :tag a))
it will return: (nil nil nil nil nil nil nil nil nil nil)

manutter5116:07:42

The filter is using #{:navPoint} as a predicate, which is something you can do with sets that's pretty cool.

(#{:foo :bar} :foo)
=> :foo
(#{:foo :bar} :foo2)
=> nil

manutter5116:07:56

So (map #{:navPoint} [:wayPoint :navPoint :someOtherPoint]) will apply the #{:navPoint} test to each of the three keywords in the vector, and will return (nil :navPoint nil)

manutter5116:07:05

In other words, a set is a set, but in Clojure it also works like a function that takes one argument. If the argument is an element in the set, return it, otherwise return nil.

manutter5116:07:27

It's a bit of syntactic sugar because it supports a very useful idiom.

naxels16:07:34

thanks for the explenation

naxels16:07:25

do you also happen to know the ‘decomp’ of this for my understanding:

(filter (comp #{:navPoint} :tag))

naxels16:07:09

i know that just doing

(filter :tag)
works by filtering on only parts of the xml that have the :tag

naxels16:07:25

but then how do you add the next part of #{:navPoint} ?

noisesmith16:07:09

(comp #{:x} :a) returns :x for {:a :x} and nil for anything that doesn't have that k/v pair

naxels16:07:55

that explains why the filter seems to work on the data set

naxels16:07:02

how would you write this decomposed?

naxels16:07:15

just for my learning and understanding of comp

noisesmith16:07:16

(fn [el] (#{:a} (:x el)))

noisesmith16:07:23

or (fn [el] (let [x (:x el)] (get #{:a} x))

naxels16:07:36

awesome, thanks

naxels16:07:53

i can confirm this works:

(def navPoints
  (->> document
       xml-seq
    ;    (filter (comp #{:navPoint} :tag))))
       (filter (fn [el] (#{:navLabel} (:tag el))))))

naxels16:07:06

knowing that el is the input argument to the function

naxels16:07:29

and that this will also work:

(def navPoints
  (->> document
       xml-seq
    ;    (filter (comp #{:navPoint} :tag))))
       (filter #((#{:navLabel} (:tag %))))))

naxels16:07:44

but seems less readable ha

noisesmith16:07:38

yeah - some people like "point free" style (which is the term to google if you want to know more about why people use comp / partial / apply / juxt etc. so much)

noisesmith16:07:16

the argument being that not having to give names to intermediate things clarifies the code (which is true unless you have never written point free code)

naxels16:07:33

thanks i will research that

naxels16:07:58

i really want to learn Clojure but seem to get hung up on what should be trivial things like parsing a Json or Xml

noisesmith16:07:39

as a social signifier, point free sometimes says "I need to write code but would rather be doing math" haha

noisesmith16:07:03

but in all seriousness, its elegant once you learn it, and totally mind bending before that

naxels16:07:50

but in all seriousness, its elegant once you learn it, and totally mind bending before that
yeah that is exactly my problem 😅

naxels16:07:05

i’m doing all kinds of exercises with comp, partial, apply

noisesmith16:07:18

(and the convention of using hash-maps and sets as if they were functions comes directly from the most commonly used mathematical definition of function btw)

naxels16:07:25

and then i work on the XML i’m trying to parse/filter now and see this solution online and go.. huh!!?

nick16:07:08

Trying to understand why the simplest clj app(generated via lein new app luminusdiff) works fine locally:

~  luminusdiff  cat project.clj
(defproject luminusdiff "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url ""}
  :dependencies [[org.clojure/clojure "1.10.1"]]
  :main ^:skip-aot luminusdiff.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
~  luminusdiff  cat src/luminusdiff/core.clj
(ns luminusdiff.core
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))
~  luminusdiff  lein run -m luminusdiff.core
Hello, World!
And fails on CI/Github Action:
Run lein run -m luminusdiff.core
Retrieving nrepl/nrepl/0.7.0/nrepl-0.7.0.pom from clojars
Retrieving clojure-complete/clojure-complete/0.2.5/clojure-complete-0.2.5.pom from clojars
Retrieving nrepl/nrepl/0.7.0/nrepl-0.7.0.jar from clojars
Retrieving clojure-complete/clojure-complete/0.2.5/clojure-complete-0.2.5.jar from clojars
Can't find 'luminusdiff.core' as .class or .clj for lein run: please check the spelling.
java.io.FileNotFoundException: Could not locate luminusdiff/core__init.class, luminusdiff/core.clj or luminusdiff/core.cljc on classpath.
 at clojure.lang.RT.load (RT.java:462)
    clojure.lang.RT.load (RT.java:424)

Github/CI env:
JAVA_HOME_8.0.262_x64: /opt/hostedtoolcache/jdk/8.0.262/x64
JAVA_HOME: /opt/hostedtoolcache/jdk/8.0.262/x64
JAVA_HOME_8_0_262_X64: /opt/hostedtoolcache/jdk/8.0.262/x64
CLOJURE_INSTALL_DIR: /opt/hostedtoolcache/ClojureToolsDeps/1.10.1-469/x64/lib/clojure
Perhaps somebody have an idea on what might be causing it?

noisesmith16:07:28

are you sure that lein is being run inside the right directory?

seancorfield16:07:39

@nfedyashev Most likely you're not running lein run in the corre... yeah, what @noisesmith said 🙂

noisesmith16:07:07

those deps it downloaded are its own deps, you should have seen your deps download if you had any :D

seancorfield16:07:27

(there were no deps aside from Clojure listed in project.clj)