This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-11-30
Channels
- # beginners (126)
- # boot (2)
- # cider (6)
- # cljs-dev (46)
- # cljsjs (8)
- # clojure (122)
- # clojure-greece (57)
- # clojure-italy (6)
- # clojure-poland (3)
- # clojure-russia (2)
- # clojure-serbia (5)
- # clojure-spec (26)
- # clojure-uk (99)
- # clojurescript (39)
- # cursive (15)
- # datascript (7)
- # datomic (21)
- # dirac (7)
- # duct (1)
- # emacs (19)
- # fulcro (58)
- # garden (4)
- # graphql (15)
- # hoplon (2)
- # immutant (1)
- # instaparse (3)
- # jobs (5)
- # juxt (15)
- # klipse (4)
- # leiningen (2)
- # lumo (52)
- # off-topic (8)
- # om (27)
- # onyx (22)
- # other-languages (3)
- # portkey (2)
- # protorepl (2)
- # re-frame (7)
- # reagent (7)
- # ring (11)
- # rum (7)
- # shadow-cljs (114)
- # spacemacs (20)
- # specter (16)
- # test-check (5)
- # timbre (1)
- # unrepl (43)
- # yada (17)
Is there some built in function or middleware to add no-cache headers for a ring app? a search didn't find anything
Well.. it is sending them now in FF and chrome. not Edge. So guess ignore this unless someone has some valuable info I should be aware of. Thanks!
Ok, so I read it wrong. Apparently ff and chrome send nocache headers in the request. IE does not. So i'll have to add the response headers to force it not to cache. So back to my original question. Any ring middleware for this yet? I'll keep looking, then make my own.
@stvnmllr2 It doesn't seem like it warrants middleware for that? Are you saying you want all requests to respond with nocache headers? That's a one-line function... a middleware library would be overkill.
Thanks. I guess I'm still new enough that I'm missing something. I figured it was only one function to add the headers. But I have a ton of api endpoints in my compojure api. And I don't want to wrap each in a call to a function right? Would not middleware be the way to deal with this in one place?
But middleware is just a function. And adding a cache control header is a single call inside that function. Easy to write. Not worth being a library unless it has a bunch of "knobs and dials" for configuration.
OH! because middleware has to be a library right? So I'd just use a function somewhere in here I think. (have to look up how again)
(def app-routes
(routes
(-> #'home-routes
(wrap-routes middleware/wrap-csrf)
(wrap-routes middleware/wrap-formats))
(-> #'service-routes
(wrap-routes middleware/wrap-auth))
(route/not-found
(:body
(error-page {:status 404
:title "page not found"})))))
Wait, i might have been thinking of leiningen tasks needing to be a library. But yeah, I can just write a function and plug it into that service-routes form and think i'll be good. thx
I previously asked about middleware for not caching my rest api. @seancorfield was nice enough to reply with some info. I guess I assumed this was called middleware. But since it doesn't exist, I will share here. Even though I guess most everyone may have this. Or is there some other great way to deal with IE?
(defn wrap-no-cache
[handler]
(fn [request]
(-> (handler request)
(header "Pragma" "no-cache")
(header "Cache-Control" "no-cache, no-store, must-revalidate")
(header "Expires" "0"))))
That looks reasonable to me.
It's all functions, all the way down 🙂
ring.util.response/header
or ring.util.response/update-header
is all you need, unless I'm misunderstanding your question?
This SO answer seems to be fairly comprehensive in terms of what headers to actually set https://stackoverflow.com/questions/49547/how-to-control-web-page-caching-across-all-browsers
When I start a REPL, how come it doesn't already know the functions from my code? I'm starting it in the same directory as the source code.
If you want the lein repl to load a namespace by default add this to your project.clj :repl-options {:init-ns user}
where user is the name of the namespace you want it to load
I can't remember the flags off the top of my head, but the default namespace for a boot trigger repl is boot.user
Is there any existed "search engine" library for Clojure? I want to build a simple meta search engine which combine some search engines like Google, Bing etc results.
I did a search on http://clojars.org, only find one related library called "web-search", but it only use Google. I wish to create a meta search engine which combines difference sources results.
What is idiomatic Clojure for the pattern “decorate a collection, find the max decorated value, return the original value”? So for example, I have a vector [:a :b :c :d]
and a function f
so that (mapv f [:a :b :c :d])
yields [6 9 8 7]
. I want to combine those together so that I get :b
.
@schmee Thanks, I’ve seen that and even tried it but for some reason never realized that’s what it’s doing 🙂
haha, there are a lot of function that do a lot of things in clojure, it’s not easy to keep track of them all 😄
OK, another question; how can I produce a lazy sequence in the same style as Python’s generators? i.e., yield a value, do some computation, yield another, and so on?
Reference: I’m working on past AoC problems, and as part of one I have to generate list of length N of non-negative numbers that must add up to K. For N=2, K=10, I can do: (for [i (range 11) j (range 11) :when (= 10 (+ i j))] [i j])
- but how I can do it for the general case for arbitrary N? Write a macro?
@orestis A macro doesn't help you if you don't know the parameter at compile time. You'll need to use a different approach
it crosses function boundaries, and also thread boundaries
in general, it’s preferable to rewrite code to abstract out things that you will need to redefine, rather than using with-redefs
or with-redefs-fn
because those functions cause global mutations on a vm wide basis which can lead to really weird and hard to fix problems
it’s a lesser problem with tests, but eg. if you ever want to run tests in parallel, it’s still a good idea to avoid those things
not to mention, abstracting out the modular things you would want to redefine is probably better design in most cases anyway
Hello, I’m having problems running clojure.spec. When I do (s/def ::key val?)
it fails to compile with this error:
Caused by: java.lang.IllegalStateException: Attempting to call unbound fn: #'clojure.core/ident?
@orestis for generation: look at iterate
and some of the collection transformations e.g. filter
@rauh @ghadi Thanks. I guess with python I was used to “this is the next value, throw it over the wall”. Now I have to think a bit more 😉
clojure tends to favor functional transformations over potentially irregular control flow
I previously asked about middleware for not caching my rest api. @seancorfield was nice enough to reply with some info. I guess I assumed this was called middleware. But since it doesn't exist, I will share here. Even though I guess most everyone may have this. Or is there some other great way to deal with IE?
(defn wrap-no-cache
[handler]
(fn [request]
(-> (handler request)
(header "Pragma" "no-cache")
(header "Cache-Control" "no-cache, no-store, must-revalidate")
(header "Expires" "0"))))
@stvnmllr2 you could consider alternatively
(update (handler request) :headers
assoc
"Pragma" "no-cache"
"Cache-Control" "no-cache, no-store, must-revalidate"
"Expires" "0")
- it does the same thing, but more directly / readably IMHOI actually find the code with explicit calls to header
more readable in terms of intent. YMMV.
(defn headers [& kvs] (fn [response] (apply update response :headers assoc kvs))
Hey all, would love some feedback on these palindrome functions and tests. 🙂
Is the "brute-force" one better because it's shorter, or is the other one better because it's more efficient (and is it actually more efficient)?
That link won't even open in my browser (and it's a really ugly link to paste into chat). Can you put the code in a Gist and provide the link to that instead? That way folks can comment on it, fork it, etc.
@derpocious I bet the most performant thing would use (-> s (StringBuilder.) (.reverse) (str))
oh, I should have seen that, thanks
yep, cljs
Here's a gist link: https://gist.github.com/JimTheMan/c62b226ec2bfee1fd5caa21837c899e4
@derpocious some things to try - comparing (seq s) to (reverse s) is less code, and likely faster than making a string in order to compare it, if you care about performance use let blocks to bind computations instead of doing them twice, clojure doesn’t optimize that sort of thing automatically
(also using a let instead of doing ops inline twice is more readable, and will rarely be less performant)
true, good points!
Bear in mind that (let [s ""] (= (seq s) (reverse s)))
is false which seems wrong to me...
oh that’s weird
So I think you might want (= (seq s) (seq (reverse s)))
so that an empty string (and nil
) are both considered palindromes.
@seancorfield good catch, I did not expect that!
(seq "")
=> nil
if we extended IReversible to String (which I bet is totally doable) then we’d likely get near optimum performance out of the seq / seq reverse method
as it is, it appears cljs currently does an eager reduce to reverse a string into a sequence, which is potentially wasteful for this task
though seq on String is reversible, so in this case (= (seq s) (seq (reverse (seq s))))
could potentially perform better? I’d just test it if criterium existed for cljs heh
… oh I should try this some time https://github.com/michalmarczyk/criterium/tree/cljs
excellent catch @seancorfield !
@noisesmith for me, (= (seq s) (seq (reverse s))))
is still returning false when s is empty string
(ins)dev:cljs.user=> (= (seq "") (seq (reverse "")))
true
sorry, it's failing for me on palindrome-nil
we wanted (isPalindrome nil) to return false
oh - then you need an extra check for that, I didn’t see that expectation
but then you are back to the first error - “” not being a palindrome
^ right
this what I have now, only failing on the nil
@derpocious the easy thing might be (and (string? %) …)
hmm how would you use that?
(and (string? s) (= (seq s) (seq (reverse s))))
or, if all you care about is the nil case, and not eg. lists of strings, just (and s ...)
ah ok, so then any time you pass a non-string into it then it just automatically returns false
right
I think that works. 🙂
And I found out how to use "run-all-tests" too!
(ins)dev:cljs.user=> (time (dotimes [_ 1000] (= (seq "hello") (seq (reverse "hello")))))
"Elapsed time: 9.400000 msecs"
nil
(ins)dev:cljs.user=> (time (dotimes [_ 1000] (= (seq "hello") (seq (reverse (seq "hello"))))))
"Elapsed time: 6.090000 msecs"
nil
the js JIT makes the numbers change (I think that’s what’s doing it) but with repeated usage the second seems to stay faster
quite counterintuitive
(mind-blown)
it’s about the IReversible thing - it allows short-circuiting instead of eagerly building a list
(I think)
interesting...
Well here's my code now. Is it so beautiful? 🙂
yeah, for a counted / associative input, it can be lazy it looks like https://github.com/clojure/clojurescript/blob/d45012273029bd5df3973ea716394f368e1c44cc/src/main/cljs/cljs/core.cljs#L1701
I would argue that nil
is a palindrome in the same way that (and)
is true
.
But if you want it to return true only for strings, why not (and (string? s) (= (seq s) (seq (reverse s))))
?
That was (palindrome? [])
is also false...
(I don't think anyone has mentioned yet that is-something
is not very idiomatic Clojure -- something?
is better)
Hah, the conversation moved on and @noisesmith already said the same (re string?
)! That'll teach me to scroll back and read everything properly! 🙂
yeah, I never understood why some functions ended in a question mark. Does is always take the place of "is"?
it means the result of calling it is a boolean
?
indicates a predicate (that returns true
or false
specifically).
If a function returns just truthy/falsey, then you wouldn't have a ?
(in general -- based on several discussions I've seen on the Clojure mailing list over the years).
ok, that makes sense. So if I just name a function "palindrome?" it would be clear to people that it takes an input and returns true or false whether or not the input is a palindrome?
(defn palindrome? "Returns true or false depending upon whether input is a palindrome. Nil is not considered a palindrome" [s] ...)
@dpsutton "Returns true for a string that is a palindrome. Returns false for all other arguments."
🙂
but @derpocious I'm a big fan of docstrings and well named functions. palindrome?
does indicate to me that it returns true or false as we have discussed. And Sean's message there would clear up any corner issues I might have. Then there's always the source
true, great tips. Thanks a lot guys!
Hi, is there a good Clojure idioms page to know all idioms commonly used (I mean no just random 5 of them but most of them)?
https://github.com/bbatsov/clojure-style-guide, not all idioms, but definitely more than 5
It's tough to give an example of every idiom. It's more about what you are trying to do and whether your code is written in an idiomatic way, I think.
Thanks @smith.adriane, @derpocious! 🙂