This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-30
Channels
- # babashka (44)
- # beginners (29)
- # calva (80)
- # cider (11)
- # clara (1)
- # clj-kondo (9)
- # clojure (80)
- # clojure-europe (21)
- # clojure-france (13)
- # clojure-nl (4)
- # clojure-spec (3)
- # clojure-uk (6)
- # clojurescript (72)
- # code-reviews (43)
- # cursive (11)
- # datomic (27)
- # events (13)
- # figwheel-main (12)
- # fulcro (27)
- # graalvm (1)
- # jackdaw (2)
- # kaocha (1)
- # malli (4)
- # meander (13)
- # nrepl (2)
- # pathom (8)
- # re-frame (4)
- # reagent (7)
- # reitit (9)
- # remote-jobs (1)
- # reveal (56)
- # ring-swagger (2)
- # sci (5)
- # shadow-cljs (20)
- # slack-help (2)
- # tools-deps (96)
- # vim (7)
- # xtdb (32)
hello all, is there any way to hook a function and insert a delay between all others functions inside it?
often when i’m using core.async, after restarting some processes or after letting them run for a while, I can’t see my log output anymore in my repl and can’t tell if my core.async processes are just not running or if the logs have just disappeared, is this a common problem and if so how do people deal with it or is it a sign of an underlying problem, too many go loops perhaps? When I start a fresh REPL, whether I run (println "TEST")
or (go (println "TEST"))
, I can see “TEST” in my repl, but after running for a while (println "TEST")
will show and (go (println "TEST"))
will not.
For long running processes consider using async/thread
. Sean's observation seems correct, and you can validate it by connecting with visualvm.
With larger applications it is too easy to run into core.async thread pool exhaustion. Depending on the app, this can manifest as a complete deadlock/hang. The advice of avoiding I/O (and too much computation) is good, but when using multiple libraries, one doesn't always control (or know) what they do.
One thing I also do is increase the size of the pool using -Dclojure.core.async.pool-size=128
as a command-line argument.
@jdkealy core.async
uses a small, fixed thread pool I believe so it's entirely possible you're overwhelming it, if I'm understanding you correctly.
I need help with macros.
I’d like to create a macro defnmy
similar to defn
but that creates a function whose name is transformed by a function supplied to the macro.
Example of usage:
(defnmy FOO clojure.string/lower-case [x]
(inc x))
It should create a function named foo
I was able to implement it using resolve
:
(defmacro defnmy [name fn args body]
(let [n (symbol ((resolve fn) name))]
`(defn ~n ~args ~body)))
Is there a way to avoid using resolve
?@viebel Why would you want to avoid resolve
?
1. I’d like the macro to work on self-hosted cljs 2. Understanding what macros can and cannot do
The macro is passed a bare symbol. You have to turn that into an actual function, in order to apply it to the symbol passed in. Not sure how else you would do that?
(I don't know anything about cljs so I don't know what restrictions it places on macros)
I guess I'd also ask why you'd want a macro that is passed both a symbol and the (symbol) name of a function that is applied to it? If you're passing both, why can't you just figure out what the function name should actually be? Is this part of some code generation thing?
(also, if you're going to imitate defn
what about docstrings and attr-maps etc?)
Yes, I am trying to make this library https://github.com/clj-commons/camel-snake-kebab self-host compatible and it has this defconversion
macro https://github.com/clj-commons/camel-snake-kebab/blob/master/src/camel_snake_kebab/internals/macros.clj#L21
Sorry, no idea.
I guess I wish cljs didn't have these limitations?
Fixing the cljs compiler seems like a better goal to me.
Ok. Trying on #clojurescript
why not eval
instead of resolve
? it will work with any function definition, it will resolve the var with symbols, and it should work on self-hosted
Hi, This is a question i did post on crux and ring. But the problem seems more related with deploying a war (lein ring uberwar) on tomcat. I have an init function that start a crux node but tomcat freeze once deployed. It seems to be a problem with threads but i am lost here. I wonder if someone has exeprienced this or can give me some advices ? Many thanks
SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [user-settings-webapp] created a ThreadLocal with key of type [java.lang.ThreadLocal](value [java.lang.ThreadLocal@8117ba6]) and a value of type [io.netty.util.internal.InternalThreadLocalMap](value [io.netty.util.internal.InternalThreadLocalMap@6684e4af]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
Is there any way to override a particular defmethod
in an external library? Or will I have to fork said library?
you can override it normally as you would do for your own codebase
(ns external)
(defmulti foo ...)
(defmethod foo :x ...)
;; your code
(ns my-code
(:require [external :as e]))
(defmethod e/foo :x ...)
Oh okay, thanks! I tried doing something like that but failed… I guess I just got confused somehow 🙂
@leonoel suggested above to replace (resolve sym)
by eval
(something like (eval `('var sym))``
https://clojurians.slack.com/archives/C03S1KBA2/p1596091177157900
And indeed that’s the way to do it in Self hosted Clojurescript as explained by @mfikes in https://clojurians.slack.com/archives/C03S1L9DN/p1596132644159300
Now my question is: is that acceptable to use eval
instead of resolve
in JVM Clojure for this use case?
@viebel If the function being passed is public, you can indeed further simplify as Leonoel suggested, and just evaluate the function symbol (with no worries about triggering private var access analyzer warnings)
(defmacro defnmy [name fn args & body]
(let [n (symbol ((eval fn) (str name)))]
`(defn ~n ~args ~@body)))
Indeed simpler.
The question remains: is that acceptable to use eval
in Clojure code when we could use resolve
instead?
Does clojure.spec work with string keys?
(s/conform (s/keys :req-un ["foo"]) {:bar 1}) => {:bar 1}
doc for (doc s/keys)
Creates and returns a map validating spec. :req and :opt are both
vectors of namespaced-qualified keywords. The validator will ensure
the :req keys are present. The :opt keys serve as documentation and
may be used by the generator.
:req-un
seems like something that only make sense with things that could be namespaced (and clearly strings cannot be)
@deadghost I am not 100% sure, but my hunch is that to spec a data structure with non-keyword keys, your best bet is to have a conversion function that results in keyword keys, and spec that
I don't see anything about specific keys that aren't keywords in the spec guide at least
(there 's map-of
to describe eg. map of string to int)
the attribute parts of spec do not work with string keys
keywordizing first is one option and probably the best if you're looking to lean on those aspects of spec
in some cases, you may be able to make do with map-of or by treating a tuple as an s/coll-of an s/or of various s/tuples describing key/value pairs
why this doesn’t work
(s/def ::quantity (s/and number? pos? (complement (some-fn Double/isInfinite Double/isNaN))))
Unable to find static field: isInfinite in class java.lang.Double
but this works
(s/def ::quantity (s/and number? pos? #(not (Double/isInfinite %)) #(not (Double/isNaN %))))
How to interop this correctly with some-fn
?
---
PS
(s/def ::quantity (s/and number? pos? (complement #{##Inf ##-Inf ##NaN})))
^ This is probably the nicer one. Does it?
some-fn
takes functions
you were passing it values
Java methods are not Clojure functions. Java methods can be called from Clojure programs using Java interop, but not used as arguments to functions like apply
or map
that expect Clojure functions.
#(Double/isInfinite %)
would be a fn
I think you can do this more simply with https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html#clojure.spec.alpha/double-in though
(s/def ::quantity (s/double-of :min 0.0 :infinite? false :NaN? false))
the Inf / NaN stuff are only double values so I'm assuming you want doubles. if you want multiple number types, well why? :)
Because all are valid for API request. Like it can be 3 peaces or 4,06 kg or 4 kg. The quantity field should be forgiven and not care about demand 1
or 1.0
as a value. At least this was an idea 🙂
but if I want ##Inf saxophones
(s/def ::foo (s/with-gen (s/and string? (complement clojure.string/blank?))
(partial gen/fmap (fn [_] (rand-nth ["foo" "bar"])) (s/gen string?))))
What is the best way to generate spec using only specified values like “foo”, “bar”, … ?but this will also accept only “foo” and “bar”. This is not what I want. I want it only to generate examples for tests.
class clojure.test.check.generators.Generator cannot be cast to class clojure.lang.IFn (clojure.test.check.generators.Generator is in unnamed module of loader clojure.lang.DynamicClassLoader @470f6965; clojure.lang.IFn is in unnamed module of loader ‘app’)
are folks generally using schema for rest apis in (for example) compojure? i thought it would be mostly spec by now, but most of the examples i find are using schema. is there a newer (well documented) way to build rest apis with clj these days? (i haven’t done it in a couple years, looking to get back into it)
(defn ?spec-problems [spec value]
(::s/problems (s/explain-data spec value)))
(defn spec-problems->errors [problems spec-messages]
(not-empty
(for [{:keys [pred in via val]} problems]
{:type :error
:code :validation
:message (some spec-messages (reverse via))
:cause {:pred pred
:in in
:val val}})))
(defn ?spec->response-problems [spec value spec-messages]
(spec-problems->errors (?spec-problems spec value) spec-messages))
This can be helpful(def spec-messages
(let [string-message "Has to be a string."]
{::code "Has to be a string."
::name string-message
::expiry-days "Has to be a positive integer."
::label-template string-message
::ingredients string-message
::countries-of-origin string-message
::quantity "Has to be a positive number."
::unit string-message
::lang "Has to be ISO 639-1 language code."}))
(defn ?body->spec-problems-response [request-body]
(s-utils/?spec->response-problems ::labels-orders request-body spec-messages))
if you have a map of data (say, an account) do you coerce to the result spec by hand? i thought compojure would coerce the output to the spec i provide
while it is not strict in topic https://clojure.wladyka.eu/posts/form-validation/ it shows how to turn spec into human readable things
(defn ->spec [shop]
(s-utils/map-coercion
{:shop/uuid uuid/as-uuid
:shop/config json/read-str}
shop))
(defn safe-coercion [f v]
(try (f v)
(catch java.lang.Exception e
v)))
(defn map-coercion [m-coercion m]
(reduce-kv
(fn [m k f]
(if (contains? m k)
(update m k (partial safe-coercion f))
m))
m m-coercion))
I have successfully used https://github.com/wilkerlucio/spec-coerce in APIs. Note that using spec for coercion is not considered particularly idiomatic/performant. I do think it can be "good enough" for a good while.
Probably the metosin
guys can provide the best solutions - check their repos: reitit, malli
https://github.com/metosin/spec-tools/blob/master/docs/01_coercion.md I found this in the metosin tools, which seems to be ok so far…