Maybe a real quick question
lein ring isn't calling my configurator
:ring {:handler some.ns/handler
:init some.ns/init
:adapter {:configurator some.ns/configurator}
:open-browser? false
:stacktrace? false
:auto-reload? false
:port 3000
it is definitely using jetty
ring 1.8
I've also tried the :configurator key flat
@emccue Given that :adapter
is pure data and is passed directly to the run-jetty
function, I don't see how you can pass a configurator function -- there's no way to resolve a symbol to code.
I think what happens here is that you end up passing the symbol some.ns/configurator
into the adapter and that ends up being "called" on the server object -- and ('sym :x)
is going to work as a lookup and give you nil
.
thats a mild headache
since ~some.ns/configurator also doesn't want to work
Because you can't pass a function into Lein's evaluation.
You can only use ~
to evaluate things that can be serialized: strings, numbers, data structures.
My advice: don't use lein-ring
. Start the server yourself and then you have full control over it.
Even back when I was still using Leiningen (years ago now), I never used lein-ring
for dealing with servers: it just wasn't worth the additional complexity in my view.
I'm trying to benchmark a slow function using criterium, but I want to reduce the sample count a bit or it'll take hours. I've tried
(binding [crit/*sample-count* 10]
(crit/bench
...expr..))
and
(crit/bench
...expr..
:samples 10)
but neither seem to work, what am I missing?Anybody familar with dtype-next / tech.v3.datatype.functional?
Hi! I work on an old project with clj-time
I donβt understand why this (t/to-time-zone (t/now) (t/time-zone-for-id "America/New_York"))
return the UTC date-time and not the right date timezoned. Someone has already had the problem?
which version clj-time you are using ?
[clj-time "0.15.2"]
is there a way to put a transducer on a returned channel?
particularly I'd like to combine core.async/timeout
with a transducer
pipe
?
If you run above code in repl, what is the output ?
It is a bit verbose but I don't see a fn that would create the "derived" channel for you
=> (t/to-time-zone (t/now) (t/time-zone-for-id "America/New_York")) #object[org.joda.time.DateTime 0x7d6955a "2021-03-23T09:31:20.371-04:00"]
I got this
#clj-time/date-time "2021-03-23T13:35:12.899Z"
I am also using [clj-time "0.15.2"]
(require '[clj-time.core :as t])
=> (t/to-time-zone (t/now) (t/time-zone-for-id "America/New_York")) #object[org.joda.time.DateTime 0x4238423f "2021-03-23T09:38:17.871-04:00"]
:thinking_face:
What is output of this ?
user> (java.time.ZonedDateTime/ofInstant (java.time.Instant/now) (java.time.ZoneId/of "America/New_York")) #object[java.time.ZonedDateTime 0xba90dd6 "2021-03-23T09:42:55.125283-04:00[America/New_York]"]
Good output #object[java.time.ZonedDateTime 0x22e1075 "2021-03-23T09:44:00.907-04:00[America/New_York]"]
(require '[clj-time.local :as l])
(l/local-now)
Are you getting correct local time ?I got the UTC date
I can help you π. What is up?
I read @dpsuttonβs https://dev.to/dpsutton/exploring-the-core-cache-api-57al article again and was somewhat scared to use core.cache (never have, but I remember a peer using it in a past job... again it was tricky)
Wondering if it would make sense to implement clojure.lang.IAtom backed by core.cache? That way one would use clojure.core/swap!
and have the nuances abstracted away. Anyone has tried that?
I believe there was some discussion around this (@seancorfield) and the recommendation is to use the wrappers
i consider the cache protocol to be private and people should only ever use wrapped/through or wrapped/through-cache
Is there as strong difference between wrapped/lookup-or-miss
and wrapped/through-cache
?
(I observed that the former uses the non-wrapped through-cache
so it might be a 'superset' of the functionality?)
I tried to understand the difference but sadly in the repo wrapped/through-cache
has no unit tests and a worse docstring than wrapped/lookup-or-miss
so I'm confused about what the wrapped/through-cache
fn actually does
ah good point. i think that's the one that can prevent needless spinning under contention
i'd do some experiements. spin up 30 threads hitting your cache and count the number of times something is computed
i think there was something like that in that article
Yeah I got that impression from the article and source I expect contention to be low/irrelevant so probably I'll sleep calmer with max 10 attempts
Curious, you include clojure.core.cache.wrapped/evict
under the 'footgun' category
But wanting to immediately overwrite a key with a different new value seems a quite extremely common use case? (`lookup-or-miss`/`through-cache` doesn't appear to help here, not without waiting for the cache entry to naturally expire)
Maybe the mistake is mine for thinking of these caches as atoms (as opposed to things that can have disparate implementations)?
i think you really shouldn't call evict yourself. the cache has strategies to call evict. but i suppose if you wanted to override you could
yes I suppose that eviction is essential to all these caches, they have to perform eviction sooner or later :)
but I suspect depending on the use case, waiting an indeterminate amount of time (or having dropped writes) is not what one wants.
OTOH, I suppose that if one used evict
recklessly one could increase contention or get nil reads
(btw I'm just testing out my own knowledge, and not really questioning anything)
Wasn't there a discussion in clojure q&a or clojureverse? or was I dreaming π
maybe it was here
Is there a way to rewrite this and avoid an anonymous function? (filter #(= (:type %) "sha1"))
(filter (comp #{"sha1"} :type))
common idiom. up to you if you think its more clear. once you see it a bunch it is but whether it is "better" is pretty 50:50 to me
It is no shorter, but slower π
Depends. #{"sha1"}
is compiled just once as a constant and barely has a noticeable difference vs. =
#{x}
creates a set in runtime. Set creation is somewhat slow
I think there is nothing wrong with (filter #(= (:type %) "sha1"))
, the intent is clear and much easier to read than (filter (comp #{"sha1"} :type))
(at least for me)
Why would you want to avoid having an anonymous function there in the first place?
If you just mean having #(...)
(after all, comp
also creates an anonymous function), then you can simply use the more verbose (fn [x] ...)
syntax.
FWIW, personally I would write it as #(-> % :type (= "sha1"))
. Or as the initial variant - doesn't really matter.
#(
is ugly but pointfree is harder to understand
I have seen a (fn-> :type (= "sha1"))
macro in some projects
pretty futile to try finding an objective truth for these :)
https://lambdaisland.com/blog/2019-12-06-advent-of-parens-6-a-small-idiom can used further evidence that some (reputed) people like the idiom
performance is objective though, so when in doubt I wouldn't use #{x}
as a predicate
If the key didnβt shadow a built-in, I find (filter (fn [{:keys [type]}] (= type "sha1")))
most readable
(defn sha1? [hashing-procedure]
(= (:type hashing-procedure) "sha1"))
...
(filter sha1?)
or
Yeahβ¦I do not know, I do not feel it deserves to be a function that can be reused
There are only a few characters to save unless you go for a separate function
t=>t.type === 'sha1"
that's really it, not worth spending more time on it I gues
(let [sha1? (fn [hashing-procedure]
(= (:type hashing-procedure) "sha1"))]
(filter sha1?))
giving it a name and giving it a place in a namespace are seperate
just pointing out that naming the function and typing the extra characters has some benefit
hence why python is structured to only allow that way
What do you mean? It does have lambda
.
It's just that it's impossible to not return something from it.
Or have more than one expression
Ah, right. Tuples to the rescue. :)
Can't do statements even with tuples
They say it's because of parsing issues but somehow Haskell has multiline lambdas
But with lambdas you don't needs statements - anything it still computable. :) Albeit absolutely impractical.
And they have been adding expression variants of statements little by little (`[x + 1 for x in xs]`, foo if bar else baz
, foo := bar
) π
I'm so happy that I have stopped almost all involvement with Python right before they introduced the walrus operator.
What? Pascal forever!
Kernighan disagrees. :P
Such a controversial operator https://mail.python.org/pipermail/python-committers/2018-July/005664.html
> Now that PEP 572 is done, I don't ever want to have to fight so hard for a > PEP and find that so many people despise my decisions.
does anyone have any experience with Tomcat not being able to run a Luminus uberwar with an error of ClassNotFoundException for ServletContextlistener? I found a SO post with the same error, but none of the responses seem to have helped.
I'd start by inspecting the uberwar and verifying whether that class exists there
there is a file called servlet-api.jar in tomcat's /lib folder, but there isn't anything with that name inside the war. Would that mean uberwar isn't including it? I tried creating a new project with "lein new luminus ... +uberwar +servlet", but I got the same error
Python doesn't improve the lambda specifically because of a deliberate design choice to make people name their functions
hence the helpers in operator and whatnot
I don't have much expertise in these area, sorry. I just hinted that uberwars should be inspectable
If a stock lein new luminus ... +uberwar +servlet
app doesn't work out of the box, that would seem a good thing to report as a github issue
Okay, I just logged the issue with lein-uberwar
(maybe use https://clojure.org in the topic?)
is there an example anyone has off hand of what the defn
params list as attr-map?
is used for?
ins)user=> (defn foo "a function" {:has-arbitrary-meta true} [])
#'user/foo
(ins)user=> (meta #'foo)
{:arglists ([]), :doc "a function", :has-arbitrary-meta true, :line 1, :column 1, :file "NO_SOURCE_PATH", :name foo, :ns #object[clojure.lang.Namespace 0x72458efc "user"]}
it gets merged to metadata
I see
it's one of the N ways to attach metadata to a function's var
the docstring mentions this as well:
> Same as (def name (fn [params* ] exprs*)) or (def
> name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
> to the var metadata.
also the spec calls it meta in the spec definition: :meta (? map?)
. But i agree it is a bit hard to parse that that's what's happening.
only tenuously related, I'm reminded of this trick
(ins)user=> (defn bar {:macro true} [_ _ form] (reverse form))
#'user/bar
(ins)user=> (bar (1 1 +))
2
macros without defmacro
i guess .setMacro
sets that metadata and extends the signature for &form
and &env
?
that sounds like what it would need to do
which got me thinking about making point-free macros, or something approaching it at least
(cmd)user=> (defn as-macro [f] (fn [& args] (apply f (drop 2 args))))
#'user/as-macro
(cmd)user=> (def baz (as-macro reverse))
#'user/baz
(cmd)user=> (alter-meta! #'baz assoc :macro true)
{:line 1, :column 1, :file "NO_SOURCE_PATH", :name baz, :ns #object[clojure.lang.Namespace 0x72458efc "user"], :macro true}
(cmd)user=> (baz (1 1 +))
2
@dpsutton bingo https://github.com/clojure/clojure/blob/cbb3fdf787a00d3c1443794b97ed7fe4bef8e888/src/jvm/clojure/lang/Var.java#L243
it only does the metadata part, something else must add the invisible args
oh, there's a binding in defmacro's body called "add-implicit-args"
That makes a lot of sense