When I eval (s/exercise-fn
insert-cookie)` , it works, there are no errors. However, when I try to "fix" insert-cookie
by changing :limit
to ::limit
at 38:7 , and try running exercise-fn
again, I get this cryptic error:
; Error printing return value (NullPointerException) at java.util.Objects/requireNonNull (Objects.java:247).
; temporal
This is my code:I just realised that the error lies not in exercise-fn but in my insert-cookie fn, there's something wrong with the (::limit options)
cond branch body, but I cannot figure out what
@tahaahmedrasheedpk Given that you are passing in unqualified keys and your function deals with unqualified keys, I think your ::cookie-options
spec needs :opt-un
instead of :opt
Same with ::name-value-pair
-- you're using :req
which is for qualified keywords. You want :req-un
.
I'm doing the opposite; I want to change the keywords in insert-cookie to their qualified variants
But when I try doing that I get the error
Show the code that actually errors then, so we can help (but I suspect I know what the error is).
When you change to ::limit
you also need to change the destructuring on keys.
(let [{::keys [limit]} options]
<-- so you get the ::
version
Yep did that too
In you main
ns, the ::
auto-resolves to :main/
as a qualifier. Your destructuring can either be {::keys [limit]}
as above or {:main/keys [limit]}
or {:keys [main/limit]}
(defn insert-cookie
[headers name value options]
(->>
(cond-> ()
(::limit options) (conj (let [{:keys [::limit]} options]
(if (integer? limit)
(str "Max-Age=" limit)
(str "Expires=" (.format DateTimeFormatter/RFC_1123_DATE_TIME limit)))))
(::domain options) (conj (str "Domain=" (::domain options)))
(::path options) (conj (str "Path=" (::path options)))
(::secure options) (conj "Secure")
(::httpOnly options) (conj "HttpOnly")
(::sameSite options) (conj (::sameSite options))
true (conj (str name "=" value)))
(clojure.string/join "; ")
(hash-map :name "Set-Cookie" :value)
(conj headers)))
Here's what I have rnNo, that's not what I posted.
{::keys [limit]}
They're equivalent (I think)
https://clojure.org/guides/destructuring#_namespaced_keywords
Yeah, actually that does work -- I've never used that syntax (in ten years!) so I had to check in the REPL.
O.O interesting
I think I found the problem, just a sec
When you exercise
it, you get tagged output from ::limit
so it is not valid input to insert-cookie
(but you're not showing us code that would do that).
So what you're passing to do .format
would be [:n 550000]
(or [:t #inst ...]
)
So, the issue was that the inst?
generator produced java.util.Date's (instead of java.time.instant's), which my function couldn't handle
Here's the fixed code:
(defn insert-cookie
[headers name value options]
(->>
(cond-> ()
(::limit options) (conj (let [{:keys [::limit]} options]
(if (integer? limit)
(str "Max-Age=" limit)
(cond->>
limit
(instance? java.util.Date limit) (.toInstant)
true (.format (.withZone
DateTimeFormatter/RFC_1123_DATE_TIME
(ZoneId/of "GMT")))
true (str "Expires=")))))
(::domain options) (conj (str "Domain=" (::domain options)))
(::path options) (conj (str "Path=" (::path options)))
(::secure options) (conj "Secure")
(::httpOnly options) (conj "HttpOnly")
(::sameSite options) (conj (::sameSite options))
true (conj (str name "=" value)))
(clojure.string/join "; ")
(hash-map ::name "Set-Cookie" ::value)
(conj headers)))
Oh, wow, that was a subtle one... yeah, I hadn't even noticed that... Dates are hard 😞 I'd love everything to be Java Time but the reality is a nightmare mix of java.util.Date
(and the java.sql.*
variants) and Java Time and sometimes Joda Time 😞
What are templates you consider useful for creating projects (CLI, Leiningen or Boot)? I am interested in highlighting useful templates for beginners and experience clojure developers alike in the books and videos I create for Practicalli. I typically use the basic templates, such as app and lib that come with the clj-new project. However for creating simple websites I use figwheel-main (https://clojurebridgelondon.github.io/ and http://Practical.li websites). I have found templates useful to learn from without specifically using them to create projects, such as the https://luminusweb.com/. Do you use https://clj-templates.com/ to find a template or perhaps an internet search? Do you create your own templates, e.g. define a common starting point for all projects for your team. Perhaps you take the https://www.juxt.land/edge/ approach of cloning a base project repository. Please reply as a thread so I can follow or post a comment at Clojureverse https://clojureverse.org/t/what-project-templates-do-you-find-useful/6652 Thank you
Some templates I have found useful include https://github.com/bhauman/figwheel-template for building landing pages, eg. for ClojureBridge London and http://Practical.li https://github.com/metosin/compojure-api for quickly creating an API with Swagger and Schema (I havent found a Reitit equivalent of compojure-api yet)
Hi @tahaahmedrasheedpk - been scanning through here. re:java.time and libraries, not sure if anyone's mentioned https://github.com/henryw374/time-literals, which provides literals for java.time - e.g.
#time/instant "2018-07-25T07:10:05.861Z"
also, I think sticking to the java.time api (rather than a wrapper) is a good idea especially if you're just learning it, but IMO cljc.java-time gives a better experience of that https://github.com/henryw374/cljc.java-time#-but-i-just-develop-on-the-jvm-onlyI worked for several hours trying to figure out why a very simple function was not returning the same thing within the program as I get at the repl. I had trouble sleeping because it didn't make sense. Today when I restarted the program it worked perfectly. I think one of my memoized functions what not being called. but some other function (not the memoized ones, but one which it calls) had been edited after the value was memoized. What's the lesson learned?
I have a collection of data structures all of the same Record with several keyword fields. Some of the records are accessed seldomly. There is a particular field whose value is expensive to compute. I'd like to compute it only the first time it is needed, if at all. Thereafter, I'd like that value used for subsequent accesses to the field. Is there some mechanism for this? Or do I need to invent this myself?
take a look at https://clojuredocs.org/clojure.core/delay
@jimka.issy as already answered, delay
can be used, but memoize
is also particularly handy for caching function results
Can memoize be used for caching local function results?
@jimka.issy Yes, (let [f (fn [x] x) f (memoize f)] ...)
Are there any examples out there that integrate a clojure backend with AWS Cognito? My searches didn't bring anything up
Hi folks.. is it possible (i know it is but not sure how) have a plugin/drop-in architecture?:
Mi idea is to be able to add a command
to my bot by just adding the corresponding files into the corresponding namespace under discord-bot.commands
where the command have to at least implent the handler
function.
Then "somehow" (this is the tricky part) import all of the discord-bot.commands.*
into the core
and call the handler
function of each one.
How can that import be implemented?
Do you want the import happen at compile time or while the application is running?
I think I did something similar a while ago. It involved using https://clojuredocs.org/clojure.core/all-ns to get the relevant namespaces. From there, use https://clojuredocs.org/clojure.core/ns-resolve to get the var holding each handler
fn. Then call it 🙂
does the cache prevent the local function from getting GC'ed ?
not really, since the state of that function is also local. but note that arguments that are used for memoization will be stored in an atom, so as long the memoized function lives, the arguments don't get GC-ed
this actually bit me in clj-kondo since I had a global memoized function, so all the args that were passed to it, lived forever
Does anyone know if there is either a way to make IntelliJ Cursive not format comments, or make cljfmt format comments? We have cljfmt as our formatter shared across the team, Cursive format seems slightly different but normally if it changes something it gets undone when I run cljfmt. Unfortunately Curisve also likes formatting comments and cljfmt doesn't touch these meaning any changes the Cursive formatter makes, sticks and causes a lot of noise in PRs.
Metabase has a fairly mature implemenation: https://github.com/metabase/metabase/blob/master/src/metabase/plugins.clj
How do I run something repeatedly? for instance: (repeatedly-run 100 (say-this "hello")
. I noticed that there is a repeatedly
, but the function called can't take an argument?
I have a thread running in the background that takes in 2 inputs from a queue and produces an output. Is there any way that I can store the latest inputs/outputs somewhere and print them in the repl when I want to check what it's doing?
I've tried an atom but it just blocks
atoms never block
can you post an example of your code @joao.galrito?
i suppose its the main thread that's blocking
yea it was the main thread that was blocking, because I was running the function directly from the REPL
if i do (thread (my-fn)) now I can read the atom in the REPL
You can create a new function with your argument enclosed. Also it will return a lazy sequence, so if you're doing it for side-effects you should add a doall. This should work: (doall (repeatedly 100 #(println "hello")))
(defn repeatedly-with-args [f & args] (repeatedly 100 #(apply f args))
thanks @regen for the doall
tip!
@joao.galrito Thanks for that. I am trying to benchmark some code I wrote with time
. I noticed that using time
with repeatedl-with-args
will output the time first, and then return all the results 100 times below it. This makes it hard to see the benchmark. is there a way to suppress the return output? or maybe put the timed benchmark below the return?
you can just return nil from the repeatedly-with-args
hi, I need to subtract 3 hours from a date, may someone can help?
(t/minus (java.util.Date.) (t/hours 3))
maybe use Calendar
?
(doto (Calendar/getInstance) (.add Calendar/WEEK_OF_YEAR -2))
ty
don’t use either java.util.Date
or java.util.Calendar
unless you have to for legacy reasons, new code should use java.time
(-> (Instant/now) (.minus 3 ChronoUnit/HOURS))
sucks that you can't add/subtract months with java.time though
you can, you need to use LocalDateTime
or ZonedDateTime
instead of Instant
the docs here clarify how different classes are used: https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html
@joao.galrito how do i do that? do i wrap the body of repeatedly-with-args
in a do
call?
dotimes
For benchmarking there is a library that does a bit more than runs code n times: https://github.com/hugoduncan/criterium
@vlaaad I tried dotimes
but it doesn't seem to work if i ignore the argument binding (since I'm not going to use it)
@vlaaad also, I may have misunderstood your dotimes
comment: was that a reference to my question to @joao.galrito above?
that was a reply to your initial question 🙂
ahh, got it. thanks!
but for benchmarking you should use criterium, not measuring execution times...
what's not working with dotimes btw?
I see, I wanted some quick way to measure functions in clojure.core as part of my learning process. I thought time
might be good because it was built in
time is good but too basic 🙂
for quick measuring should be fine, I guess
; dotimes requires exactly 2 forms in binding vector
i get that error message. I assume its because i don't put anything in the arguments vector
should i put some throwaway values to make dotimes work?
time
gives me problems because I would like to run things 1000 times to get a proper average, but it has been quite difficult to wrap a function to repeat itself many times to feed to time
(dotimes [_ 100] (say-this "hello"))
yeah, you should have a name for local variable, it's common to use _
for unneeded stuff
That works! Thanks @vlaaad! I'll give criterium a try as well!
np 🙂
i thought the current best practice was to use java.time
what @schmee said 🙂
Thanks Folks will check that
Build time
I got this serialized json array a:3:{s:1:"a";i:1;s:1:"b";i:2;s:1:"c";i:3;}
how would I parse this in Clojure?
@slack.jcpsantiago are you getting that from a PHP/Laravel API?
doesn't look like json.. is it bencode?
I’m pretty sure I came across that when writing an integration with an API implemented in PHP.
that format, I mean
it’s possible, I got it from a CSV file in which one column has these serialized arrays. I think it’s PHP but I’m not sure
In which case, I used this library https://code.google.com/archive/p/serialized-php-parser/
Got you with the ultimate clojure date hack.
(let [le-now (.format
(java.text.SimpleDateFormat. "yyyyMMddHHmmss")
(new java.util.Date))
n-hours-ago (.format
(java.text.SimpleDateFormat. "yyyyMMddHHmmss")
(new java.util.Date
(- (System/currentTimeMillis) (* 3 60 60 1000))))]
(println "now: " le-now)
(println "3 hrs ago: " n-hours-ago))