beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Chicão 2020-12-17T00:22:01.386Z

Hi how can I rewrite some function from an lib ?

2020-12-17T00:27:20.386100Z

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

Chicão 2020-12-17T00:28:08.386300Z

Yes, I do.

2020-12-17T00:28:42.386600Z

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

2020-12-17T00:28:58.386800Z

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

Chicão 2020-12-17T00:29:35.387Z

Thanks for help me

2020-12-17T00:29:44.387300Z

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.

2020-12-17T00:30:39.387500Z

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.

👍 2
roelof 2020-12-17T11:28:24.389300Z

Why do I get here a function instead of the result

roelof 2020-12-17T11:28:52.389700Z

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

(time splitSum)

2020-12-17T11:32:04.390200Z

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

2020-12-17T11:32:25.390600Z

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

☝️ 1
roelof 2020-12-17T11:41:40.391400Z

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))

roelof 2020-12-17T11:42:05.391700Z

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)

L T 2020-12-17T11:57:14.392100Z

[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" .

jumar 2020-12-17T12:04:10.392400Z

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?)

nmkip 2020-12-17T12:08:12.392700Z

(try)

nmkip 2020-12-17T12:08:24.392900Z

pop and catch arent inside the try function

jumar 2020-12-17T12:09:20.393200Z

Ah, I missed that 🙂

👍 1
L T 2020-12-17T12:22:09.393800Z

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

L T 2020-12-17T12:23:14.394Z

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

👍 1
2020-12-17T12:59:25.395200Z

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

2020-12-17T12:59:50.395900Z

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

2020-12-17T13:01:11.396700Z

Fireplace is working perfectly for clj files though

dharrigan 2020-12-17T13:40:53.397400Z

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

dharrigan 2020-12-17T13:41:02.397700Z

Lots of people there use vim + fireplace

2020-12-17T13:41:06.397900Z

ahh, thanks

dharrigan 2020-12-17T13:41:09.398100Z

np

Chicão 2020-12-17T14:38:48.399600Z

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?

roelof 2020-12-17T15:11:10.400200Z

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

R.A. Porter 2020-12-17T15:12:09.400400Z

You could use apply.

valerauko 2020-12-17T15:12:11.400600Z

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

roelof 2020-12-17T15:14:21.400800Z

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

roelof 2020-12-17T15:14:38.401Z

thanks for showing me this

alexmiller 2020-12-17T15:21:03.401200Z

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

alexmiller 2020-12-17T15:22:00.401400Z

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

roelof 2020-12-17T15:24:26.401600Z

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

valerauko 2020-12-17T15:56:53.402300Z

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?

2020-12-17T15:59:04.403800Z

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

Fpineda 2020-12-17T16:00:49.404900Z

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

dpsutton 2020-12-17T16:01:30.405500Z

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.

👍 1
valerauko 2020-12-17T16:01:42.405700Z

I use ! for mutating / impure stuff

👍 1
2020-12-17T16:01:50.405900Z

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

roelof 2020-12-17T16:02:00.406400Z

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

Fpineda 2020-12-17T16:02:06.406600Z

okay okay got it, thanks! 🙌

Célio 2020-12-17T16:53:56.407300Z

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.

roelof 2020-12-17T16:55:28.408200Z

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) 

roelof 2020-12-17T16:56:20.408800Z

but now atomSum is 0 instead of the right answer.

2020-12-17T17:03:32.409300Z

You have range on the wrong side of the (

octahedrion 2020-12-17T17:03:41.409500Z

derefthose futures too

roelof 2020-12-17T17:08:36.409600Z

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)))

2020-12-17T17:20:46.409800Z

that means that sum returned a delay, not a number

2020-12-17T17:21:45.410Z

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

2020-12-17T17:22:49.410200Z

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

2020-12-17T17:23:04.410400Z

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

roelof 2020-12-17T17:26:32.410600Z

that does the job

roelof 2020-12-17T17:26:37.410800Z

(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)

roelof 2020-12-17T17:26:53.411Z

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

2020-12-17T17:32:38.412600Z

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

roelof 2020-12-17T17:33:21.413400Z

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

roelof 2020-12-17T17:33:34.413800Z

this code is good clojure code ?

2020-12-17T17:33:51.414100Z

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

2020-12-17T17:35:31.415700Z

(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))

2020-12-17T17:35:57.416300Z

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

roelof 2020-12-17T17:36:07.416700Z

oke

roelof 2020-12-17T17:36:22.416900Z

im was trying to solve this one

roelof 2020-12-17T17:36:28.417100Z

; 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?

Joe 2020-12-17T17:36:30.417300Z

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)

2020-12-18T14:15:10.473600Z

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

2020-12-17T17:37:37.417500Z

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

dpsutton 2020-12-17T17:37:45.417800Z

(i misread sorry)

roelof 2020-12-17T17:39:29.418Z

yep

roelof 2020-12-17T17:39:39.418200Z

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)))

roelof 2020-12-17T17:39:57.418400Z

I have a 4 core machine so cores enough

roelof 2020-12-17T17:59:08.418700Z

so this is better ?

roelof 2020-12-17T18:00:59.418900Z

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))

roelof 2020-12-17T18:01:25.419100Z

but much faster then this one :

(time (sum3 0 1e7))

roelof 2020-12-17T18:01:56.419300Z

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

caumond 2020-12-17T18:43:42.419700Z

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 😁

roelof 2020-12-17T18:44:50.419900Z

I use now vs code with the calva plugin

caumond 2020-12-17T19:31:52.420100Z

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

caumond 2020-12-17T19:32:46.420300Z

start with inner expressions

caumond 2020-12-17T19:33:10.420500Z

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

roelof 2020-12-17T20:01:32.420700Z

thanks for the hints

rakyi 2020-12-17T20:23:50.420900Z

=> (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

👍 1
Joe 2020-12-17T20:54:37.422600Z

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

Tuan-Anh 2020-12-17T21:38:01.423500Z

Hello Clojurians!

Tuan-Anh 2020-12-17T21:38:54.424600Z

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)

alexmiller 2020-12-17T21:39:36.424800Z

welcome!

Tuan-Anh 2020-12-17T21:40:14.425300Z

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

Tuan-Anh 2020-12-17T21:40:18.425500Z

brb!

seancorfield 2020-12-17T21:43:04.426500Z

@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.

dpsutton 2020-12-17T21:43:28.427Z

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

seancorfield 2020-12-17T21:44:14.427300Z

Not as far as I know @dpsutton

seancorfield 2020-12-17T21:44:58.428600Z

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

dpsutton 2020-12-17T21:45:06.428800Z

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

seancorfield 2020-12-17T21:45:59.429300Z

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

Tuan-Anh 2020-12-17T21:46:49.429400Z

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

Tuan-Anh 2020-12-17T21:47:13.430Z

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

Tuan-Anh 2020-12-17T21:51:21.430900Z

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

Calum Boal 2020-12-17T21:58:50.432700Z

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 Boal 2020-12-17T21:59:36.433400Z

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)))

phronmophobic 2020-12-17T22:00:58.434500Z

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 Boal 2020-12-17T22:01:42.435500Z

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 Boal 2020-12-17T22:01:53.435800Z

Now to try out core.async

Tuan-Anh 2020-12-17T22:23:57.435900Z

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

seancorfield 2020-12-17T22:29:57.436100Z

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

seancorfield 2020-12-17T22:31:05.436400Z

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.

✅ 1
seancorfield 2020-12-17T22:33:29.436600Z

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

Tuan-Anh 2020-12-17T22:34:38.436900Z

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

2020-12-17T23:18:51.437400Z

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

2020-12-17T23:21:02.437900Z

oof

2020-12-17T23:21:19.438300Z

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

2020-12-17T23:21:54.438900Z

the use of >! in

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

2020-12-17T23:22:46.439600Z

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

2020-12-17T23:23:44.440300Z

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

2020-12-17T23:27:55.441100Z

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

2020-12-17T23:29:15.442600Z

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

2020-12-17T23:31:06.443400Z

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

2020-12-17T23:31:50.443800Z

ah, cljs.core* missed that

2020-12-17T23:32:32.444600Z

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

2020-12-17T23:33:51.444900Z

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

2020-12-17T23:34:29.445700Z

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

2020-12-17T23:36:14.447300Z

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)

2020-12-17T23:37:05.448400Z

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

2020-12-17T23:37:21.448700Z

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

dpsutton 2020-12-17T23:44:11.449200Z

https://github.com/r0man/cljs-http/blob/master/test/cljs_http/client_test.cljs has some examples of how to use it if you're interested