This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # adventofcode (174)
- # announcements (5)
- # aws (9)
- # babashka (17)
- # beginners (259)
- # boot-dev (1)
- # calva (6)
- # cider (19)
- # circleci (7)
- # clj-kondo (9)
- # cljfx (51)
- # cljs-dev (4)
- # clojure (83)
- # clojure-australia (2)
- # clojure-dev (9)
- # clojure-europe (78)
- # clojure-nl (3)
- # clojure-spec (4)
- # clojure-switzerland (1)
- # clojure-uk (18)
- # clojurescript (22)
- # conjure (17)
- # cursive (17)
- # data-science (1)
- # datomic (15)
- # defnpodcast (1)
- # events (2)
- # fulcro (39)
- # graalvm (16)
- # graphql (1)
- # kaocha (5)
- # lambdaisland (11)
- # malli (6)
- # meander (1)
- # off-topic (26)
- # pathom (10)
- # re-frame (10)
- # reitit (6)
- # rewrite-clj (7)
- # sci (3)
- # shadow-cljs (28)
- # sql (12)
- # test-check (10)
- # tools-deps (31)
Hello everybody, Clojure noob here. I have been kicked off 4Clojure Android app and can't login to my user anymore, however credentials are correct and he browser access goes smooth as usual. Has anyone experienced the same behaviour? Thanks sincerely in advance!
oke, and another problem
(defn isPrime? [n known] (loop [cnt (dec (count known)) acc ] (if (< cnt 0) (not (any? acc)) (recur (dec cnt) (concat acc [(zero? (mod n (nth known cnt)))]))))) (defn my_primes "my version to print out primes to a certain number" [limit] (map #(isPrime? % ) (range 2 .. limit )) )
; Syntax error compiling at (chapter4.clj:32:26). ; Can't take value of a macro: #'clojure.core/..
You don't need the
.. in your range function, and in fact
.. means something else in Clojure
and there is another error. I was hoping on seeing all the prime-numbers but I see now a collection of false 😢
I would say test your
isPrime? function first and make sure it returns
true when you give it a prime number and
nil) when you give it a non-prime number.
I tried that one also but then I see a empty collection. So I assume my isPrime is wrong.
what do you think of my solutions . I did only study the 4 first chapters of the Clojure from the ground up site
The code looks good overall. A couple style points: you are using
partial correctly, but there was a discussion recently about using
(partial foo) versus using
#(foo %) and a lot of folks favor using
#(foo %) in most cases because it’s more versatile and also slightly more efficient. Also it’s idiomatic to use shorter names like
pred instead of spelling out
predicate (though I favor using longer, more explicit names personally, except for really common terms like
so If I understand you well I could change this
(partial divisible? n) to
#(divisible? n) ?
It’s actually the same number of parens in a lot of cases, it’s just that the first paren comes to the left of the function name instead of to the right.
I hope i once learn as much clojure I can make a website with it and solved the difficult challenges of Advent of Code or exercism
Macros can be really hard to wrap your head around, but honestly I've been using Clojure for years and years, and I've written maybe 3 macros total (not counting "let's write a macro!" exercises)
Using the threading macros, find how many numbers from 0 to 9999 are palindromes: identical when written forwards and backwards. 121 is a palindrome, as is 7447 and 5, but not 12 or 953. Write a macro id which takes a function and a list of args: (id f a b c), and returns an expression which calls that function with the given args: (f a b c). Write a macro log which uses a var, logging-enabled, to determine whether or not to print an expression to the console at compile time. If logging-enabled is false, (log :hi) should macroexpand to nil. If logging-enabled is true, (log :hi) should macroexpand to (prn :hi). Why would you want to do this check during compilation, instead of when running the program? What might you lose?
Yeah most of the time a good function is all you ever need. Plus you can't pass a macro around like you can a function.
Two of those require you to write your own macro; the first one just wants you to use some of the built-in macros.
we see tomorrow. I hope I can ask for help here if needed or for a review. I hope I will not ask for help too much but the error messages are for me not always clear and as I said im totally new in Clojure so I think I need a lot of help to learn it wel
Yeah, the error messages are a sore spot but they're getting better, and after a while you kind of get to recognize patterns of "Oh, I got this kind of error message, I should check, that"
sorry I mean this one :
Write a macro id which takes a function and a list of args: (id f a b c), and returns an expression which calls that function with the given args: (f a b c).
You’ll need to add some macro-specific syntax to that so that it doesn’t just execute
(fun a b c) when you call it, but that’s actually a good start: you’ve written out what you want the end result to be when your macro executes, and now you just have to convert it into the body of an actual macro.
hmm, the only thing I can find it to change it into this :
(defmacro id [fun a b c]
(fun a b c)``
You’re short a
) at the end, but once you add that, try running in your REPL with
(macroexpand '(id foo a b c))
on both I see this in repl
clj::chapter4=> (chapter4/fun chapter4/a chapter4/b chapter4/c)
For the second one you should see
(+ 1 2 3), (possibly with the clojure namespace attached to the
+ symbol). So there’s something not quite right with your macro.
you are currently putting a literal symbol a b c in the expanded code
gives now with :
(defmacro id [fun a b c] `(fun ~a ~b ~c))
(macroexpand '(id + 1 2 3))
If you want a challenge, you could try to modify your
id macro so that it takes zero or more arguments.
Do you have a reference/tutorial for
defmacro? It should show you the list of unquote symbols.
I onu have this page : https://aphyr.com/posts/305-clojure-from-the-ground-up-macros
a macro is literally just a function that takes code (as a data structure) and returns replacement code (as a data structure)
args is a seq (1 2 3) so you're almost there. how do you prepend something to a list?
(defmacro id [fun & args] (cons fun args)) ;; order is different
people often think that macros are this special thing in clojure that needs syntax-quote and vice versa, but macros are literally just functions, and syntax-quote is literally just a templating syntax for data
Time to make a lot of notes and take a break. Tomorrow further on this for me unknown territory
(source when) or
(source and) for a couple good examples to study
a good exercise is also to forget about
defmacro and just implement normal functions with
defn , and just invoke the function with quoted arguments manually (e.g.
(foo 'bar '1 '[1 2 3]) instead of
(foo bar 1 [1 2 3]))
then to turn
foo into a macro you just need to remove the quotes from the invocation and replace
you might need to
(use 'clojure.repl) if you're not in user namespace
and I have to learn a framework if I want to make websites and learn how to store something in a database
It took me a few months to get really comfortable with Clojure, but that was back before Slack and also I was new to the whole “functional programming” thing.
I tried to start using Clojure when it was really new, but the lack of leiningen, etc., at the time made it too painful to be productive, and gave it up for a couple of years. Then came back to it when the tooling was much improved.
I had been using Ocaml quite a bit before Clojure, so same here regarding the functional aspect.
I love re-frame, but yeah react does have a few quirks, and also cljs isn’t 100% identical to clj, so there’s bits that may bite the unwary. I’m working full time doing clj+cljs+re-frame tho, so there’s more than plenty enough to get a decent web app up and running.
im thinking if and when I got to that point to make a website which uses the Rijksmuseaum api . where someone sees a page and in the same time the images are downloaded and they replace the placeholders
Hmm, I’ve done that in straight JS back in the day, never tried to do in cljs :thinking_face:
is there then a big difference in cjs and reframe. The way the clojurefarm is teaching us clojure is using reframe
Re-frame is a library that uses CLJS. It’s not part of Clojure or CLJS, it’s just popular.
Basically, React exists in the world of JS, and someone wrote a CLJS library named “reagent” to make it easier to use React in CLJS, and then someone else wrote a library named “re-frame” on top of reagent.
first this "book", then the brave book and then 4 clojure and then I think things like reframe i have to learn
maybe I come tomorrow or later back to see how to solve this one :
Advanced) Using the rationalize function, write a macro exact which rewrites any use of +, -, *, or / to force the use of ratios instead of floating-point numbers. (* 2452.45 100) returns 245244.99999999997, but (exact (* 2452.45 100)) should return 245245N
Greetings! Can't find an elegant way to do a partial flatten, by which I mean a function that accepts any nesting of sequences and returns a sequence of the innermost sequences ; e.g.
(partial-flatten [[[1 2]] [[[3 4]]]]) => ([1 2] [3 4].
Could a kind puzzle-inclined person help me out?
but I only want to flatten n levels, I only want to flatten when the lists don't contain x, etc
in general flatten get used when you write a program of the form 1. do some stuff that builds up some nested list 2. flatten things out
but while step #1 is a generally steeped in context, by the time you get to step #2 the context has been thrown away, so determining how and where to flatten has to be done all over again
while if you just applied concat here and there while doing #1, you had the context right there to easily make the decisions
Fair point. In this instance, the nesting comes from using (for) in a (loop ...) which ends up nesting the results arbitrarily - or rather, in an input dependent, yet useless way.
It would be indeed better not to use flatten-but-x to solve this. OTOH, using
for [ ... :let ... :when ... ] is super terse and expressive.
for example, if you have
(for [i (f x)] i) and
(f x) returns a lists of lists then do
(for [i (f x) ii i] ii)
it's more like
(defn f [a prefix] (comment omitted termination code)) (for [n (magic a)] (f (drop n a) (conj prefix (first a))))). (magic) returns a small number.
that will concat one level of lists for every recursive call, so in your base case you may need to add a second layer of lists if your lists is meant to be a list of lists
the recursive call chain ends up being exactly the context information you would need to recover in your "flatten, but..."
I followed your instructions and that made it work. I don't understand how or why it works tho
for is a combination of a lot of difference sequence functions, include map and mapcat
(for [x xs y ys] [x y]) => ([x0 y0] [x0 y1] .. [x0 yN] [x1 y0] .. [xN yN]) - cartesian product I believe
any for that doesn't use any of the keyword stuff (:when, :while, etc) can be transformed into an expression of nested mapcats around an inner map, you can do the keyword stuff to you just have to sprinkle in some calls to filter and take-while
(macroexpand '(for [x xs y ys] [x y])) is significantly harder to grok thank your explanations 🙂
you could do it with either tree-seq (save only colls that don't contain colls) or postwalk (concat any colls that only contain colls)
is there a easy way to make this work :
(ns chapter5) (defn schedule "Using the control flow constructs we've learned, write a schedule function which, given an hour of the day, returns what you'll be doing at that time. (schedule 18), for me, returns :dinner." [my-time] (cond (<= "0:00" my-time "07.00") :sleeping (== "07:00" my-time) :breakfast (<= "07:01" my-time "12:00") :work (= "12:00" my-time) :lunch (<= "12:01" my-time "18:00") :more-work (<= "18:01" my-time "19:00") :dinner (<= "19:01" my-time "23:59") :watching-tv ))
this is so far the best date-time api i've ever worked with. so if you want to do it right (like how you would do it in a real-world project), i would suggest taking a look at this api.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/LocalTime.html#parse(java.lang.CharSequence) would be right method to call.
(java.time.LocalTime/parse "07:00") #object[java.time.LocalTime 0x2b87581 "07:00"] (str *1) "07:00"
just as an example, for the first clause in your
(def midnight (java.time.LocalTime/MIDNIGHT)) #'user/midnight (def breakfast-time (java.time.LocalTime/parse "07:00")) #'user/morning (def my-time (java.time.LocalTime/parse "06:30")) #'user/my-time (and (.isAfter my-time midnight) (.isBefore my-time breakfast-time)) true
oke I was trying another idea but get errors
(ns chapter5) (defn parse-time "Parse a string to a time object" [time-string] (java.time.LocalTime/parse time-string)) (defn schedule "Using the control flow constructs we've learned, write a schedule function which, given an hour of the day, returns what you'll be doing at that time. (schedule 18), for me, returns :dinner." [my-time] (cond (<= (parse-time "00:00") (parse-time(str my-time)) (parse-time "07:00") ) :sleeping )) (schedule "03:00")
; Execution error (ClassCastException) at chapter5/schedule (form-init11789170975546566471.clj:9). ; class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')
rule of thumb for when dealing with time: don't roll your own solutions because time is hard. 😉
Right now I only have studied the first 5 chapters of the "Clojure from the ground up " tutorial
I find java time tricky to work with, I think for this particular exercise I’d convert the numeric input to a string
@roelof take a look at the
compare function. For just this limited set of string comparisons, it should be adequate.
Why not just represent time of day in minutes as a number? No need to introduce string comparisons here
(defn time-as-minutes [hour minute] (+ minute (* 60 hour)) (defn schedule [my-time-in-minutes] (cond (<= (time-as-minutes 0 0) my-time-in-minutes (time-as-minutes 7 0)) :sleeping ;; add the rest of the cases ))
for a given pair of times, you'd want the first compare to return positive or zero, and the second compare to return negative or zero
If you wanted to use the built-in (jvm) time library, perhaps this might be suitable...
(ns foo (:import [java.time LocalTime])) (defn parse [my-time] (LocalTime/parse my-time)) (def breakfast (parse "07:00")) (def midday (parse "12:00")) (def nearly-dinner (parse "18:00")) (def dinner (parse "19:00")) (def late-night (parse "23:59")) (defn schedule "Using the control flow constructs we've learned, write a schedule function which, given an hour of the day, returns what you'll be doing at that time. (schedule 18), for me, returns :dinner." [my-time] (let [my-time' (parse my-time)] (cond (.isBefore my-time' breakfast) :sleeping (= my-time' breakfast) :breakfast (.isBefore my-time' midday) :work (= my-time' midday) :lunch (.isBefore my-time' nearly-dinner) :more-work (.isBefore my-time' dinner) :dinner (.isBefore my-time' late-night) :watching-tv))) (schedule "06:00") (schedule "07:00") (schedule "11:00") (schedule "12:00") (schedule "15:00") (schedule "18:00") (schedule "19:30") (schedule "00:00")
why do I get this error:
(ns chapter5 (:import [java.time LocalTime])) (defn parse [my-time] (LocalTime/parse my-time)) (def breakfast (parse "07:00")) (def midday (parse "12:00")) (def nearly-dinner (parse "18:00")) (def dinner (parse "19:00")) (def late-night (parse "23:59")) (defn schedule "Using the control flow constructs we've learned, write a schedule function which, given an hour of the day, returns what you'll be doing at that time. (schedule 18), for me, returns :dinner." [my-time] let [my-time' (parse my-time)] (cond (.isBefore my-time' breakfast) :sleeping )) (schedule "03:00")
unresolved symbol my-time'
now another one :
Could not locate chapter4__init.class, chapter4.clj or chapter4.cljc on classpath.
I feel like you are not the first person here with this same error, wonder if maybe whatever repo you're using is not set up well
but it's saying exactly the problem - you're trying to load chapter4 ns but it's not on your classpath. presumably you have the file so it's something with the config of the classpath
As @alexmiller mentions, this problem shows up now and then. Might be a problematic project template, but also might be a Ux issue with Calva.
this is my repo so far : https://github.com/RoelofWobben/Learning_in_public
your classpath is by default "src" so requiring
chapter4 will look for
src/chapter4.clj but that file is located at
the namespace needs to be
ground-up.chapter4 or the file can be moved out of the ground_up directory to just
src or you can add
src/ground_up onto your classpath and leave the namespaces alone
I did this because the next step in the course is the brave book and I do not want two chapter 3 in the repo