This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-22
Channels
- # beginners (104)
- # bitcoin (1)
- # boot (5)
- # clara (3)
- # cljs-dev (14)
- # cljsjs (5)
- # cljsrn (1)
- # clojure (242)
- # clojure-italy (17)
- # clojure-news (13)
- # clojure-norway (3)
- # clojure-russia (101)
- # clojure-spec (41)
- # clojure-uk (87)
- # clojurescript (38)
- # core-async (38)
- # cursive (6)
- # datomic (11)
- # defnpodcast (3)
- # docs (14)
- # editors (8)
- # events (1)
- # fulcro (7)
- # hoplon (25)
- # leiningen (4)
- # luminus (7)
- # off-topic (25)
- # onyx (1)
- # portkey (14)
- # random (1)
- # re-frame (7)
- # reagent (4)
- # rum (4)
- # schema (8)
- # shadow-cljs (257)
- # spacemacs (10)
- # specter (4)
- # unrepl (3)
- # yada (1)
Anyone suggest coding kata sized challenges (1-4 hours long) for those just starting clojure / clojurescript? Links to simple solutions a bonus. Would like to add some challenges to the Clojurebridge content we are updating. Thanks.
@jr0cket How about the usual katas, e.g. prime factors, bowling game, string calculator and so on?
Can't promise my solutions are idiomatic though, I used them to practice while learning, too.
Here are a few: Prime factors: https://gist.github.com/Vinai/a4d6c56e1a92f388edb72ffd30513733 String calculator: https://gist.github.com/Vinai/ca004731d8e1fb385bc238d997cdc3d3 Print diamond: https://gist.github.com/Vinai/8294a03975d1f67563b258636bbdbda7 Roman numerals: https://gist.github.com/Vinai/47c4d607567bab159781fd4c3c01e9bc Another fun one that takes a few hours is the ugly trivia legacy code refactoring kata: https://github.com/jbrains/trivia/tree/master/clojure In order of ascending complexity, I think those would be 1. Roman numerals 2. String calculator 3. Prime factors 4. Print diamond 5. Ugly trivia
@vinai thank you, most helpful
@seancorfield @schmee Here's the smallest example I could find that will reproduce the problem. I'm using Atom/Proto-Repl, When I evaluate the file, the Main Form is displayed. When I close the Main Form, it closes and I get the message "REPL Closed" in Porto-Repl. Then I have to restart Proto-Repl, and everything works fine again. (ns sherpa.main-form (:use [seesaw.core])) (def main-frame (frame :title "Main Form" :minimum-size [400 :by 200] :on-close :exit)) (-> main-frame show! pack!)
and if I run the code from a terminal REPL I get the following error when I close the window SocketException The transport's socket appears to have lost its connection to the nREPL server clojure.tools.nrepl.transport/bencode/fn--10199/fn--10200 (transport.clj:95) clojure.tools.nrepl.transport/bencode/fn--10199 (transport.clj:95) clojure.tools.nrepl.transport/fn-transport/fn--10171 (transport.clj:42) clojure.core/binding-conveyor-fn/fn--4676 (core.clj:1938) java.util.concurrent.FutureTask.run (FutureTask.java:266) java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617) java.lang.Thread.run (Thread.java:745) Bye for now!
so the moral is read the docs (lol) Note that :exit will cause the entire JVM to exit when the frame is closed, which may be reasonable for a standalone app, but probably isn't for use in the REPL. The default value is :hide
. Changed :on-close :exit to :hide and works fine. Then you can re-show the form with (show! main-form)
is it safe to think of Vectors as similar to Arrays? (coming from JavaScript world)
lol i’d just found that, actually. it seemed like it was pretty similar to an array, but wanted to check before I assumed
It is but it isn't held in contiguous memory like arrays in most languages, but that's not an issue performance wise. I find the community docs are very good too. https://clojuredocs.org/clojure.core/vector_q
cool, thanks for the info! lots of new stuff to learn, coming from a primarily PHP/Node mindset
I've done a lot of F# and a bit of Clojure over the last few years, I really like Clojure a lot. The .net / .netcore stuff is a mess right now.
Clojure / Clojurescript just seems to work easily and the community / conferences are great
@rcustodio I think it depends on what you want to do. core.async seems to be the choice of many though.
If you want to build some asynchronous application core.async is better. If you want to just spawn threads here and there java Threads are great.
I’m doing a service that will get some things in asynchronous and then work with the result
They use some form of threads from a thread-pool reserved for core.async. Probably at some level it will be Java threads, but I don't know.
@vinai @rcustodio https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj core.async delegates to the Executor framework, which uses java threads, which wrap system threads on most runtimes
(though, yes, the clj version of core.async will probably always use Threads and a threadpool of some sort)
what is not an implementation detail is that go blocks should be free of blocking operations
core.async uses a small pool of threads that are shared by all go blocks in a cooperative manner, the thread is kept until you use a channel to read or write, then another go block can use it
this is more than just an implementation detail - if you don't understand how it's working you can starve core.async easily, resulting in none of your go blocks executing at all
this is why you shouldn't do expensive tasks (including and especially blocking IO) inside core.async go blocks
@schmee coordinate between various asynchronous operations
the issue is that asynchronous coordination is a problem that often comes up when you are doing thing parallel, which gets people confused and they assume they can use go blocks for parallelism
which breaks things
I'll let someone else answer that
it's usually the simplest option, as long as you are starting a small number and don't need to do any interesting coordination
Hi... is atom the only way???
clojure
(defn- get-orders [items access-token]
(let [orders (atom {})]
(when (= (:status @items) 200)
(loop [orders-id (distinct (mapv #(:order_id %) (:body @items)))]
(swap! orders
assoc
(first orders-id)
'((ml-orders/get (first orders-id) access-token)
(ml-orders/get-feedback (first orders-id) access-token))))
@orders)))
why would that even need an atom? and why are you using loop with no recur?
OK - anyway, instead of swapping the atom, you can put the new value into the loop arg, and return the result from the loop
yeah this function raises a lot of questions... you definitely do not need an atom anyway. if the loop has a recur then you can just pass the new orders map into the recur
(defn- get-orders [items access-token]
(let [orders (atom {})]
(when (= (:status @items) 200)
(loop [orders-id (distinct (mapv #(:order_id %) (:body @items)))]
(when orders-id
(swap! orders
assoc
(first orders-id)
'((ml-orders/get (first orders-id) access-token)
(ml-orders/get-feedback (first orders-id) access-token)))
(recur (rest orders-id))))
@orders)))
that's why you return it
so (when orders-id ...)
becomes (if-not orders-id orders ...)
- returning the orders instead of building up the value
also, (recur (rest ...)) indicates that your code could be improved by using reduce instead of loop
that way clojure does the sequence tracking for you, and the orders are the value returned from your reducing function
if you are consuming a collection in order, reduce is better than loop, period
it's even faster
that's fine
map doesn't return a hash-map though, it returns a lazy-seq
if you are OK with returning a lazy-seq instead, and you want to process the input lazily, sure, map works
(defn- get-orders [items access-token]
(when (= (:status @items) 200)
(mapv #(hash-map :order (ml-orders/get % access-token)
:feedback (ml-orders/get-feedback % access-token))
(distinct (mapv #(:order_id %) (:body @items))))))
something like thissure - but if you are using mapv, that means you don't want it to be lazy and it might make more sense to use reduce (or into with a map transducer) to create your hash-map
also, how is this items atom being used?
oh - I see (:status @items) - is that accessing a future then?
@mjcleary almost definitely because it's lazy and you're only realising the first thunk
(take 1 (repeatedly #(println "whoa")))
whoa
=> (nil)
(take 2 (repeatedly #(println "whoa")))
whoa
whoa
=> (nil nil)
(take 3 (repeatedly #(println "whoa")))
whoa
whoa
whoa
Read number from console, then perform function that also reads from console that many times
there's lots of different ways you could do this. I think the most intention revealing would be
(dotimes [_time-num (Integer/parseInt (read-line))]
(check-weights (read-line)))
but, repeatedly would also work. using (dorun (repeatedly (Integer/parseInt (read-line)) #(check-weights (read-line))))
or (take (Integer/parseInt (read-line)) (repeatedly #(check-weights (read-line))))
or (nth (repeatedly #(check-weights (read-line))) (Integer/parseInt (read-line)))