Fork me on GitHub
#beginners
<
2020-12-17
>
Chicão00:12:01

Hi how can I rewrite some function from an lib ?

andy.fingerhut00:12:20

You want to take an existing library you are using in your Clojure code, and redefine a function inside of that library?

Chicão00:12:08

Yes, I do.

andy.fingerhut00:12:42

You could do this by changing to the namespace where that function is defined, e.g. (in-ns 'that.library.namespace)

andy.fingerhut00:12:58

Then do (defn fn-i-want-to-redefine [arg1 arg2 ...] ...)

Chicão00:12:35

Thanks for help me

andy.fingerhut00:12:44

Then (in-ns 'user) if you were in a REPL, to switch back to the user namespace that one often works in, or switch to any other namespace you want. Or stay in the namespace that.library.namespace if you really want to.

andy.fingerhut00:12:39

That will redefine the function in the running JVM -- it will not change the source code of the library that will be loaded if you quit that JVM and start another one.

👍 6
roelof11:12:24

Why do I get here a function instead of the result

roelof11:12:52

(defn splitSum []
  (let [part1 (future (sum 0 (/ 1e7 2)))
        part2 (future (sum (/ 1e7 2) 1e7))]
    (+ @part1 @part2)))

(time splitSum)

Lennart Buit11:12:04

time times an expression, so you are timing how long it takes to retrieve(?) splitSum

Lennart Buit11:12:25

You’d probably want to call splitSum: (time (splitSum))

☝️ 3
roelof11:12:40

then I get this error on this code :

(defn splitSum []
  (let [part1 (future (sum 0 (/ 1e7 2)))
        part2 (future (sum (/ 1e7 2) 1e7))]
    (+ @part1 @part2)))

(time (splitSum))

roelof11:12:05

Caused by: java.lang.ClassCastException: class clojure.lang.Delay cannot be cast to class java.lang.Number (clojure.lang.Delay is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap')
        at clojure.lang.Numbers.add(Numbers.java:153)
        at ground_up.chapter6$splitSum.invokeStatic(chapter6.clj:37)
        at ground_up.chapter6$splitSum.invoke(chapter6.clj:34)
        at ground_up.chapter6$fn__197.invokeStatic(chapter6.clj:39)
        at ground_up.chapter6$fn__197.invoke(chapter6.clj:39)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3702)

noisesmith17:12:46

that means that sum returned a delay, not a number

lioneltonnon11:12:14

[SOLVED] Hello, I have an issue I can't resolve via googling with the Clojure Koans 03_lists.clj : See line 36-39 in the screenshot below. Regardless of what I type in the blank, the terminal running koan returns "Unable to resolve symbol: catch in this context" .

jumar12:12:10

This works for me just fine:

"But watch out if you try to pop nothing"
  (= "No dice!" (try
          (pop '())
          (catch IllegalStateException e
            "No dice!")))

  "The rest of nothing isn't so strict"
  (= () (try
          (rest '())
          (catch IllegalStateException e
            "No dice!"))))
I cloned this repo: https://github.com/functional-koans/clojure-koans Are you using the same one? How do you run it? (via lein koan run?)

nmkip12:12:24

pop and catch arent inside the try function

jumar12:12:20

Ah, I missed that 🙂

👍 3
lioneltonnon12:12:09

Yes, I'm using the same repo. I also use Paredit, could it be that paredit changed the content of the koan?

lioneltonnon12:12:14

Ah got it. it's because of parinfer. Thank you!

👍 3
Clark Urzo12:12:25

Trying to set up vim fireplace and I'm getting this error https://github.com/tpope/vim-fireplace/issues/372

Clark Urzo12:12:50

I've RTFM but the issue isn't mentioned there

Clark Urzo13:12:11

Fireplace is working perfectly for clj files though

dharrigan13:12:53

@signup867 you may get more help in the #vim channel

dharrigan13:12:02

Lots of people there use vim + fireplace

Chicão14:12:48

Hi, i've this request grpc ^io.grpc.example.AccountsRequest request and I want read metadata like token from headers. Someone knows how I can do it?

roelof15:12:10

is i possible to add up number in range and not using reduce ?

R.A. Porter15:12:09

You could use apply.

valerauko15:12:11

You can use apply: (apply + (range 10))

roelof15:12:21

oke, I have to see how that can work in updating a atom

roelof15:12:38

thanks for showing me this

Alex Miller (Clojure team)15:12:03

well numbers in a range can also be added with (first + last) * n /2 :)

Alex Miller (Clojure team)15:12:00

(* (+ 0 9) (/ 10 2)) == (reduce + (range 10))

roelof15:12:26

thanks, but I do not think that is the purpose of this challenge

Instead of using reduce, store the sum in an atom and use two futures to add each number from the lower and upper range to that atom

roelof16:12:00

or is this simeple swap! atom (apply + (range 10)) ?

noisesmith17:12:45

swap! needs a function, a number isn't a function

valerauko15:12:53

I'd like to learn more about how the CLJS compiler(s) work. Specifically, how do the cljc bits make it to both the java and the JS side? Do library authors have to publish both an npm package and on Clojars to make the library available in CLJS?

andy.fingerhut15:12:04

Some libraries publish .cljc source files packaged inside of a JAR file to Clojars, I believe, and that same JAR file can be used from ClojureScript, I think? Don't trust my answer since I rarely use ClojureScript, but I believe several libraries are published to Clojars that way

andy.fingerhut16:12:50

e.g. medley is a small library with a single .cljc file published as a JAR on Clojars: https://clojars.org/medley

Fpineda16:12:49

Hi everyone, a beginner question, is some kind of convention using the ! naming a function like add-todo! ?

dpsutton16:12:30

often means a side-effecting function. in this case would store the "todo" in some mutable storage, be it a db, some client side db, etc.

👍 3
valerauko16:12:42

I use ! for mutating / impure stuff

👍 3
Fpineda16:12:06

okay okay got it, thanks! 🙌

Célio16:12:56

Where can I find examples of tools.cli using the :in-order option? I’m having a hard time figuring out how to use it correctly.

roelof16:12:28

stilll feel like a really beginner

(defn atomSum []
  (let [atom  (atom 0)
        part1 (future (swap! atom (apply + range(0 (/ 1e7 2)))))
        part2 (future (swap! atom (apply + range((/ 1e7 2) 1e7))))]
    (deref atom)))

(atomSum) 

roelof16:12:20

but now atomSum is 0 instead of the right answer.

caumond18:12:42

Hi, depending on your IDE, the procedure is quite different, but to "debug", I use to 1) reread carrefully 2) decompose the function in smaller ones and run a test function for each 3) insert some println 4) use the inspector features 5) I even found some 6) I discovered dotrace which may help. Personnaly I usually stop @ 2, sometime 3. Teach him how to fish and you feed him for his life time 😁

roelof18:12:50

I use now vs code with the calva plugin

caumond19:12:52

ok, the best experience is to start a repl, connect to it with vs-code, launch "evaluate current form"

caumond19:12:46

start with inner expressions

caumond19:12:10

like (/ 1e7 2), then (range ...) and so on

roelof20:12:32

thanks for the hints

manutter5117:12:32

You have range on the wrong side of the (

octahedrion17:12:41

derefthose futures too

roelof17:12:36

still not the right answer

(defn atomSum []
  (let [atom  (atom 0)
        part1 (deref (future (swap! atom (apply + (range 0 (/ 1e7 2))))))
        part2 (deref (future (swap! atom (apply + (range 0 (/ 1e7 2))))))]
    (deref atom)))

noisesmith17:12:49

swap! takes a function, apply is not returning a function

noisesmith17:12:04

perhaps you want (swap! atom + (apply ...))

roelof17:12:32

that does the job

roelof17:12:37

(defn atomSum []
  (let [atom  (atom 0)
        part1 (deref (future (swap! atom +  (apply + (range 0 (/ 1e7 2))))))
        part2 (deref (future (swap! atom +  (apply + (range 0 (/ 1e7 2))))))]
    (deref atom)))

(atomSum)

roelof17:12:53

the only thing I got is that part1 and part2 are not used

noisesmith17:12:38

right, the only thing they do is make sure you don't deref the atom at the end before the futures are done executing

roelof17:12:21

so it s not a problem that I have to solve ?

roelof17:12:34

this code is good clojure code ?

noisesmith17:12:51

well, it does expose a problem with the code - the futures don't do anything useful because you don't create one until the other returns

noisesmith17:12:31

(defn atom-sum
  []
  (let [a (atom 0)
        part1 (future (swap! a + (apply + (range (/ 1e7 2)))))
        part2 (future (swap! a + (apply + (range (/ 1e7 2)))))]
    @part1
    @part2
    @a))

noisesmith17:12:57

that will take ~half the time as yours because the sums happen in parallel, instead of one at a time, that's why we use futures

roelof17:12:22

im was trying to solve this one

roelof17:12:28

; Instead of using reduce, store the sum in an atom and use two futures to add
; each number from the lower and upper range to that atom. Wait for both 
; futures to complete using deref, then check that the atom contains the right 
; number. Is this technique faster or slower than reduce? Why do you think 
; that might be?

noisesmith17:12:37

yeah - if you create both futures, then deref, it's faster (if you have multiple CPUs), if not it's slightly slower

roelof17:12:39

this is also working

(defn atomSum []
  (let [atom  (atom 0)
        part1 (future (swap! atom +  (apply + (range 0 (/ 1e7 2)))))
        part2 (future (swap! atom +  (apply + (range 0 (/ 1e7 2)))))]
    (deref part1)
    (deref part2)
    (deref atom)))

roelof17:12:57

I have a 4 core machine so cores enough

roelof17:12:08

so this is better ?

roelof18:12:59

the code now is something slower then this one

(defn sum3
  [from to]
  (reduce + (range from to)))

(defn splitSum []
  (let [part1 (future (sum3 0 (/ 1e7 2)))
        part2 (future (sum3 (/ 1e7 2) 1e7))]
    (+ @part1 @part2)))

(time (splitSum))

roelof18:12:25

but much faster then this one :

(time (sum3 0 1e7))

roelof18:12:56

clj::ground-up.chapter6=> 
"Elapsed time: 501.8355 msecs"
24999995000000
clj::ground-up.chapter6=> 
#'ground-up.chapter6/sum3
clj::ground-up.chapter6=> 
#'ground-up.chapter6/splitSum
p.chapter6=> 
"Elapsed time: 8clj::ground-up.chapter6=> 
"Elapsed time: 466.1117 msecs"
4.9999995E13
clj::ground-u87.6055 msecs"
49999995000000

Joe17:12:30

In AOC I struggled to do something that feels like it should be quite simple: For a set of integers, return a sequence of n-tuples with every combination of those integers. So for integers 0 and 1 looking for an 2-tuple, you would get [[0 0] [0 1] [1 0] [1 1]] etc. I ended up doing something heinous like (combo/permuted-combinations (apply concat [(repeat 3 0) (repeat 3 1)]) 3) - did I miss something obvious here? (NB: I know now that for the specific case where integers are 0 and 1 I'm effectively looking for the binary numbers between 0 and 2^n, but am looking for something more general)

rakyi20:12:50

=> (combo/selections [0 1] 2)
((0 0) (0 1) (1 0) (1 1))
but I think people usually try to solve AOC without libraries, not sure if they are allowed

👍 3
Joe20:12:37

Thanks, that’s what I’m looking for. And AOC takes enough of my time without having to implement my own combinatorics 😀

Vincent Cantin14:12:10

@U751SU53R I am not aware of that rule. Thx for the fn.

dpsutton17:12:45

(i misread sorry)

Tuan-Anh21:12:01

Hello Clojurians!

Tuan-Anh21:12:54

I recently pick up Clojure and I'm really liking it so far, which is why I wanted to join the Clojure slack group. I hope I can learn from everyone and contribute (eventually)

Tuan-Anh21:12:14

Thanks! actually on 2nd thoughts, I'm gonna rejoin with my personal email, feels like using work email for this is not a great idea haha

seancorfield21:12:04

@tuananh.le Let me (or any other Admin) know if you want that work-email-based account deactivating once you are signed up with your personal email.

Tuan-Anh21:12:49

Hey @U04V70XH6, nice to meet you! I will definitely let you know once I set up my personal email so you can deactivate this one

Tuan-Anh22:12:57

Actually I'm gonna use my work email for now haha.

seancorfield22:12:29

No problem. Feel free to DM me any time if you need activation/deactivation on any of your email accounts here on Clojurians!

Tuan-Anh22:12:38

Yea thanks a lot! Looking forward to chatting with you more soon!

dpsutton21:12:28

is it possible to edit your email address without creating a new account? (no idea, but sounds possible-ish)

seancorfield21:12:14

Not as far as I know @dpsutton

seancorfield21:12:58

(Slack is designed for companies so I'm sure they wouldn't want folks switching company communications to a personal account)

dpsutton21:12:06

fair enough. slack logins aren't the best in the world. i have like 9 username/passwords in my password manager that at one point all were entitled "Slack" and took a while for me to disambiguate

seancorfield21:12:59

(and we can continue discussions re: Slack in #community-development if we need to, not in #beginners)

Tuan-Anh21:12:13

I'm actually trying edit my email address rightnow, as far as I know, that seems to be an option on slack

Tuan-Anh21:12:21

I'm having some trouble joining clojurian slack with my personal email. Do I need some sort of invitation to join?

seancorfield22:12:57

You should be able to go to http://clojurians.net and enter your personal email address and get an invite @tuananh.le

seancorfield22:12:05

I'm pretty sure you cannot edit/change your email address in Slack -- for security reasons since Slack is designed for companies and they would want the security of controlling email addresses used for access.

3
Calum Boal21:12:50

When writing clojure i find myself doing lots calls to map, reduce, filter, etc all in different functions. In a non-functional language i'd typically do all of these checks in one iteration of a loop. I'm concerned about performance regarding this approach, how much overhead does the actual iteration over sequences add?

Calum Boal21:12:36

For example, the way that i'm building a map in doc->candidates:

(ns the-great-escape.core
  (:require
   [clj-http.client :as client]
   [hickory.core :as html]
   [hickory.select :as s]
   [clojure.string :as string]
   [lambdaisland.uri :refer [uri]])
  (:gen-class))

(defn doc->hickory [doc]
  (-> (html/parse doc)
      (html/as-hickory)))

(defn fetch-and-parse-page [url]
  (-> (client/get url
                  {:cookie-policy :standard
                   :redirect-strategy :none})
      (:body)
      (doc->hickory)))

(defn extract-asset-tags [body]
  (s/select (s/or
             (s/attr :href)
             (s/attr :src))
            body))

(defn extract-href-urls [tags]
  (map #(get-in %1 [:attrs :href]) tags))

(defn extract-src-urls [tags]
  (map #(get-in %1 [:attrs :src]) tags))

(defn extract-asset-urls [tags]
  (->> (extract-href-urls tags)
       (filter #(not (nil? %1)))))

(defn parse-urls [urls]
  (map uri urls))

(defn local-asset? [base-domain {:keys [host]}]
  (or (nil? host) (= base-domain host)))

(defn filter-local-paths [base-domain parsed-urls]
    (->> (filter (partial local-asset? base-domain) parsed-urls)
         (map :path)
         (filter #(not (nil? %1)))
         ))

(defn url->parts-map [url]
  (let [parts (string/split url #"/")]
    {:dir (str "/" (second parts))
     :path (str "/" (string/join "/" (drop 2 parts)))}))

(defn get-unique-dirs [parts-map]
  (map #(first (val %1)) (group-by :dir parts-map)))

(defn filter-bad-traversals [parts-map]
  (filter #(and (not= (:dir %1) "/") (not= (:path %1) "/")) parts-map))

(defn build-original-url [base-url parts-map]
  (str (assoc base-url :path (str (:dir parts-map) (:path parts-map)))))

(defn build-traversal-url [base-url parts-map]
  (str (assoc base-url :path (str (:dir parts-map) ".." (:dir parts-map) (:path parts-map)))))

(defn request-and-hash [url]
  (println url)
  (-> (client/get url)
      (:body)
      (hash)))

(defn doc->candidates [base-domain doc]
  (->> (extract-asset-tags doc)
       (extract-asset-urls)
       (parse-urls)
       (filter-local-paths base-domain)
       (map url->parts-map)
       (get-unique-dirs)
       (filter-bad-traversals)))

phronmophobic22:12:58

if you're worried about performance, you can use the transducer version of all of those operations (map, filter, etc), but I wouldn't worry too much about it for most use cases

Calum Boal22:12:42

Ah cool will look into that. Not massively worried about perfomance as network io on the http requests will be the main bottleneck, but scanning 1 million+ hosts it adds up over time

Calum Boal22:12:53

Now to try out core.async

skykanin23:12:51

So I'm using the clj-http libraries async http get to try and dump the response into a core.async channel and then alter an atom called state based on that response and also return the response, but when I call this get-listings function all I get back is #object[cljs.core.async.impl.channels.ManyToManyChannel] and I'm not sure what I'm doing wrong

hiredman23:12:19

to start off with that code should throw an exception and refuse to compile

hiredman23:12:54

the use of >! in

(fn [response] (>! rep-chan response))
is not valid

hiredman23:12:46

so my guess is it did fail to compile, but you have some previous version of get-listings defined in your repl, and that is what you are calling

hiredman23:12:44

next, the result of an expression like (go ...) is always going to be a channel

skykanin23:12:55

ic, I guess I don't really need do use channels here if I just dump the http response into the atom in the callback function

hiredman23:12:15

I dunno, I mean, why don't you just write a little program that runs in a loop, pulling data from the web api, then doing something with it

skykanin23:12:06

I need the data to render some components so I've been using a reagent atom for that, but I thought that I could maybe just return the data directly by using core.async

hiredman23:12:50

ah, cljs.core* missed that

hiredman23:12:32

that maybe why the compiler didn't throw an error about that invalid use of >!, the cljs side of core.async needs some love

hiredman23:12:51

you must mean you are using cljs-http, not clj-http?

skykanin23:12:29

I was using cljs-http but wanted to switch to clj-http . Is it not supported on cljs?

hiredman23:12:14

if by clj-http you mean https://github.com/dakrone/clj-http the library which is a wrapper around the apache java http client, then I very much doubt it (although I haven't been paying too much attention to clj-http in recent years, so I suppose it is possible it somehow sprouted such a thing)

hiredman23:12:05

if you mean something else, then it is extremely tedious of someone to have used that same name for a cljs http client

skykanin23:12:21

no I meant the one you linked to, back to cljs-http lol