This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-12-12
Channels
- # adventofcode (78)
- # announcements (5)
- # babashka (22)
- # beginners (230)
- # calva (18)
- # cider (26)
- # clj-kondo (1)
- # cljs-dev (1)
- # clojure (14)
- # clojure-austin (1)
- # clojure-dev (3)
- # clojure-europe (30)
- # clojure-switzerland (1)
- # clojure-uk (26)
- # clojurescript (33)
- # conjure (2)
- # cursive (2)
- # data-science (1)
- # datomic (9)
- # docker (1)
- # emacs (8)
- # events (4)
- # fulcro (64)
- # lambdaisland (3)
- # luminus (1)
- # off-topic (3)
- # pathom (6)
- # portal (1)
- # programming-beginners (5)
- # shadow-cljs (22)
- # tools-deps (8)
- # xtdb (4)
To count the number of vowels in string. This is the first version.
(defn count-vowels [input]
(let [vowels [\a \e \i \o \u]]
(->>
(for [x (char-array (clojure.string/lower-case input))]
(some #{x} vowels))
(filter some?)
(count))))
Can it be done better ?What do you experts find of this solutions ? https://github.com/RoelofWobben/Learning_in_public/blob/main/ground_up/src/ground_up/chapter5.clj
Depends on your OS. brew upgrade clj-kondo for macOS, linux, might have to reinstall
Any built-in function for this?
(defn repeat-reduce [f acc n]
(reduce (fn [acc _] (f acc)) acc (range n)))
user=> (defn sum [start end] (reduce + (range start end)))
user=> (time (sum 0 1e7))
"Elapsed time: 1001.295323 msecs"
49999995000000
Use delay to compute this sum lazily; show that it takes no time to return the delay, but roughly 1 second to deref.
So the answer will be (defn sum [start end] (delay (reduce *(range start end)))
?i'm failing to initial an atom using a validator,
(defn shape [M] .....impl.....)
(defn dim-2? [M]
(= (count (shape M)) 2))
(def price-matrix (atom [] :validator dim-2?))
(defn set-pricing-rules! [M]
(swap! price-matrix into M))
=> Syntax error (IllegalStateException) compiling at (kata01.clj:15:19).
Invalid reference state
but when changing to another validator, i.e: vector?
it compiles, how could it make sense?false
right!
yep, guess I'm misusing atom here
basically i'd like to initial a 2dim matrix,
something like that:
[[1 2 3]
......]
(def price-matrix
; Item Price Special Price
[["A" 50 #(* (/ % 3) 130)]
["B" 30 #(* (/ % 2) 45)]
["C" 20 identity]
["D" 15 identity]])
do that then. (atom [] :validator dim-2?)
is saying start an atom and reject values which don't conform to dim-2?
. And the initial value you give it []
does not conform to the validator function
basically i'd like to set each row of the "price-matrix" (cons it) to the initial atom
(def price-matrix
;; Item Price Special Price
(atom [["A" 50 #(* (/ % 3) 130)]
["B" 30 #(* (/ % 2) 45)]
["C" 20 identity]
["D" 15 identity]]
:validator dim-2?))
i'm not following the confusion. maybe update dim-2? to allow for empty vectors as empty 2-dimensional vectors?
changing the initial atom to [[]] would work as expected,
so basically i'm good, just need to define the swap! correctly now
: ) ty
ser=> (defn sum [start end] (reduce + (range start end)))
user=> (time (sum 0 1e7))
"Elapsed time: 1001.295323 msecs"
49999995000000
Use delay to compute this sum lazily; show that it takes no time to return the delay, but roughly 1 second to deref.
So the answer will be (defn sum [start end] (delay (reduce *(range start end)))
 ?
Wanted to be sure I understand state well on clojure ?ClojureFarm says you can learn clojure, reframe and databses in 35 days but I think its'too fast
to understand things and try to solve the challenges from this page : https://aphyr.com/posts/306-clojure-from-the-ground-up-state
what is wrong here :
; Execution error (ClassCastException) at ground-up.chapter6/eval13962 (form-init13914588690575444785.clj:16).
; class ground_up.chapter6$sum cannot be cast to class java.util.concurrent.Future (ground_up.chapter6$sum is in unnamed module of loader clojure.lang.DynamicClassLoader @58b8d871; java.util.concurrent.Future is in module java.base of loader 'bootstrap')
code :
(defn sum [start end] (delay (reduce + (range start end))))
(sum 0 1e7)
(time(deref sum))
You are not calling the function sum
but you are trying to deref the function itself.
hmm, was looking at this example
user=> (def later (delay (prn "Adding") (+ 1 2)))
#'user/later
user=> later
#<Delay@2dd31aac: :pending>
user=> (deref later)
"Adding"
3
later
is not a function there.
@borkdude what is then the right way to tell how long the calculating of the sum takes as the challenge ask me to do
; Use delay to compute this sum lazily; show that it takes no time to return the
; delay, but roughly 1 second to deref.
(time (deref (sum 0 1e7)))
Or something like
(def later (sum 0 1e7))
(time (deref later))
Your sum
is a function that returns a delayed expression
tomorrow or Monday time for this one :
We can do the computation in a new thread directly, using (.start (Thread. (fn [] (sum 0 1e7)))âbut this simply runs the (sum) function and discards the results. Use a promise to hand the result back out of the thread. Use this technique to write your own version of the future macro.
user=> (defn sum [start end] (delay (reduce + (range start end))))
#'user/sum
user-> (time (sum 0 1e7))
"Elapsed time: 0.2965 msecs"
#object[clojure.lang.Delay 0x847f3e7 {:status :pending, :val nil}]
user=> (time (deref (sum 0 1e7)))
"Elapsed time: 156.6201 msecs"
49999995000000
user=>
I see these numbers
clj::ground_up.chapter6=>
"Elapsed time: 0.0385 msecs"
#<Delay@1c7ac1a6: :not-delivered>
clj::ground_up.chapter6=>
"Elapsed time: 848.3458 msecs"
A Microsoft Surface 3 laptop đ
GN all and tomorrow a nice challenge where I already said I have to think how the future macro should look like
How to solve this one error: ; Wrong number of args (1) passed to: ground-up.chapter6/future code:
; We can do the computation in a new thread directly, using (.start (Thread.
; (fn [] (sum 0 1e7)))âbut this simply runs the (sum) function and discards the
; results. Use a promise to hand the result back out of the thread. Use this
; technique to write your own version of the future macro.
(defn sum2 [start end] promise)
(defmacro future[start end]
'(reduce + (range start end))
)
(def answer (future (sum2 0 1e7)))
one macro writing trick is to put all the logic in a regular function. the regular function makes it easier to test:
(defn sum2 [start end] promise)
(defn future* [start end]
'(reduce + (range start end)))
(defmacro future[start end]
(future* start end))
repl> (future* 0 100)
;; (reduce + (range start end))
you can see that start
and end
are being used literally, instead of as variables@U0EGWJE3E how would you go about diagnosing this error? What is the error telling you?
The error is telling me I have that the future has only 1 argument and I give more @dpsutton
you can also use macroexpand-1
similarly:
repl> (macroexpand-1 '(future 0 100))
;; (reduce + (range start end))
i'm not sure what that means. you defined future as requiring two arguments and then supplied it with only one. the error said "wrong number of args (1) passed to future
and what I mean is how to pass this promise
(defn sum2 [start end] promise)
in the macroif I do :
(defn sum2 [start end] promise)
(defmacro future[start end]
'(reduce + (range start end))
)
(def answer (future 0 1e7))
(defn sum2 [start end] promise)
(defmacro future*[start end]
'(reduce + (range start end))
)
(def calc (deliver sum2 future*))
errror :
`
; Can't take value of a macro: #'ground_up.chapter6/future*
i kind of agree that their explanation is confusing
I would split up the task into two parts: 1. write a non macro version 2. write the macro
(defn sum2 [start end] promise)
(defmacro future*[start end]
'(reduce + (range start end))
)
(def calc (deliver sum2 (future 0 1e7)))
error:
; Unable to resolve symbol: start in this context
that is I think easy
(defn sum2 [start end] promise)
(defn future*[start end]
'(reduce + (range start end))
)
(def calc (future* 0 1e7)
here's an example of how to use promise since it doesn't seem to be explained:
;; promise example
;;
;; create a promise
> (def my-promise (promise))
;; start a new thread
;; the new thread will set the value of my-promise to 42
> (.start (Thread. (fn []
(deliver my-promise 42))))
;; nil
;; access the value of my-promise
;; this will block the dereferencing thread until a value is
;; delivered to my-promise
> @my-promise
;; 42
you create a promise with (promise)
and then you can set its value in any thread using deliver
in my example, I'm simply setting the value of my-promise
to 42 with (deliver my-promise 42)
the goal is to recreate the behavior of future
. i'm not sure the provided explanation of what future
does is explained clearly. maybe it's worth breaking down what future
's behavior is
can you outline what future
's desired behavior is?
from future
's doc string:
Takes a body of expressions and yields a future object that will
invoke the body in another thread, and will cache the result and
return it on all subsequent calls to deref/@
so crucially: 1. it does the work in a separate thread 2. it doesn't directly return the value, it returns an object that can be dereferenced to obtain the value
in clojure @
, will deref the result
deref
also works
I'm not sure what your current code looks like, but I didn't see where you started a new thread
ah ok. promise
should probably be something like (promise)
promise
is a function that must be called to create a new promise
ie. promise
vs (promise)
(def sum2 promise)
vs (def sum2 (promise))
what does deliver
do?
clojure.core/deliver
[promise val]
Added in 1.1
Delivers the supplied value to the promise,...
@U0EGWJE3E You need to pay more attention to parens. You are not calling deliver
because you have no parens around it.
deliver
accepts two arguments, the promise and a single value
oke, changed the code to this :
(def sum2 (promise))
(defn future*[start end]
(deliver sum2 0 1e7))
No, deliver
takes two arguments.
You gave it three.
No, you can only deliver a single value.
(def sum2 (promise))
(defn future* [start end]
(deliver sum2 (reduce + (range start end))))
sweet. does *future now implement all of futureâs desired behavior?
are you sure?
You can try this stuff out in the REPL piece by piece:
user=> (def p (promise))
#'user/p
user=> (deliver p 0)
#object[clojure.core$promise$reify__8501 0x220c9a63 {:status :ready, :val 0}]
user=> (deliver p 1e7)
nil
user=> @p
0
user=>
what about the threading requirement?
also, iâm pretty confident in recommending that you find a different tutorial to work through. unfortunately, iâm not sure what a good getting started tutorial might be
yep, the course im now doing is telling met that doing the clojur from the ground up is a good starting point. But I see that on almost every challenge I need help to solve the challenges
@U0EGWJE3E You've been trying to learn Clojure on and off for a long time now. Remind me which books you've tried to work through?
Well, then you are very restricted on material: "Brave and True" and "Ground Up" are pretty much the only free ones I know out there.
I learned originally from a course I paid $200 for, and I bought books.
i canât actually remember how i learned clojure. I didnât buy any books
oke,, Thanks both so far for the help. Time to think about how to go on on my clojure way or know that clojure is not for me
My first two were Joy of Clojure and Clojure in Action. Then I bought Clojure Programming. Since then I've bought almost every single Clojure book out there đ
what kind of things would you like to build?
@U0EGWJE3E Given how you've struggled with the basics of Clojure each time you've tried, it is possible that Clojure may not be your thing...
sometimes there are good resources for specific use cases
there are some really good resources for building web sites
I was just talking with someone who was trying to learn Forth and finding that they just couldn't "get it" when they actually tried to build stuff, even though they'd read books and liked the idea of the language...
Im thinking thenabout a gallery or much later a crm for a volunteer organisation with some member , invoice part
@U7RJTCH6J web sites? What sort of resources? I can't imagine anything being suitable given the conversation thread above...
@seancorfield that is why I said I have to think bout how and if I want to go on learning clojure
itâs not clojure, but iâve heard good things about the âlearn X the hard wayâ series, https://shop.learncodethehardway.org I think their ruby edition is freely available
I think Haskell is much, much harder than Clojure...
And Rust is also much, much harder than Clojure.
Hi guys, I want to try hexagonal architecture. I don't find good reference for that. How am I suppose to ?
Maybe another way to ask is "how do you implement port / adapter pattern in clojure?"
@caumond It's mostly just about layers and making sure the dependencies only go in one direction. In Clojure you mostly want to have a pure functional core and have your side-effect-y stuff at the edges.
Some folks will suggest using protocols to mirror interfaces but I don't think that's necessarily a good way to go (if you only have one implementation of a protocol, you might just as well use plain functions).
@caumond you might find this interesting https://polylith.gitbook.io/polylith/ as a way to have some formal structure between components and layers.
ok, pure functional seems more appealing, I didn't know polylith but I'll try to do the simple way, with layers and their dependency well managed
Hi - I'm going through https://clojure.org/guides/deps_and_cli to try out deps.edn, I've gone literally through the steps in the "Writing a program" section. It's just a "hello world" world program that also prints the current timestamp. I'm getting this error instead:
:~/hello-world$ clj -X hello/run
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
-X (No such file or directory)
Full report at:
/tmp/clojure-6673920467411785967.edn
:~/hello-world$
@chepprey You have an old version of the CLI installed. Upgrade to the latest.
See clojure -Sdescribe
to see what you've got installed.
(I'm on 1.10.1.763 but that's a prerelease -- 1.10.1.754 is the latest, see https://clojure.org/releases/tools )
I have a map like this
{:ship [0 0] :waypoint [10 1]}
I pass it to a function and destructure it
(defn move2 [{:keys [ship waypoint] :as acc} [inst distance]]
(let [[waypoint-x waypoint-y] waypoint]
;; do stuff.
))
Can I destructure the keys and waypoint-x
and waypoint-y
in the argument destructuring, rather than destructuring int he arg list AND the let ?@qmstuart Like this:
user=> (let [{[x y] :waypoint} {:waypoint [10 1]}] (println 'x x 'y y))
x 10 y 1
You can use that destructuring in the function argument instead. let
was just easier in the REPL.
btw, is your talk on repl driven development going to be available on youtube or elsewhere afterwards?
After the London event, yes, both versions will be posted online.
I figure with the two very different timezones, more folks can be there "live".