This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-30
Channels
- # adventofcode (3)
- # announcements (4)
- # babashka (42)
- # beginners (56)
- # biff (23)
- # cider (8)
- # clj-yaml (2)
- # cljdoc (16)
- # clojure (83)
- # clojure-europe (52)
- # clojure-nl (3)
- # clojure-norway (4)
- # clojure-sweden (2)
- # clojure-uk (2)
- # clojurebridge (1)
- # clojurescript (2)
- # cloverage (1)
- # cursive (11)
- # data-oriented-programming (1)
- # deps-new (2)
- # dev-tooling (2)
- # emacs (3)
- # etaoin (4)
- # events (5)
- # fulcro (5)
- # gratitude (3)
- # java (3)
- # jobs (1)
- # jobs-discuss (1)
- # joyride (33)
- # malli (16)
- # music (1)
- # nbb (1)
- # nrepl (4)
- # nyc (1)
- # off-topic (25)
- # pathom (8)
- # re-frame (1)
- # reitit (7)
- # remote-jobs (2)
- # shadow-cljs (6)
- # tools-deps (9)
I want to call constructor of a Java class conditionally. If the branch is never reach, I don’t want JVM to load the class. What’s the best way to accomplish that?
Maybe try putting the (import ...)
call inside the conditional branch?
Hey everyone,
I’m trying to write a macro that reifies java.util.function.Consumer
with type hints. Whenever I try to use it, clojure still prints reflection warning messages and the method (`.record`) could not be found in the runtime:
(defmacro as-callback
[callback-fn long?]
(let [result (gensym "result")
meta-result (with-meta result {:tag (if long?
ObservableLongMeasurement
ObservableDoubleMeasurement)})]
`(reify Consumer
(accept [_# ~result]
(let [{:keys [value# attributes#]} (~callback-fn)]
(.record ~meta-result
value#
(otel.attributes/->attributes attributes#)))))))
Metadata is needed because an object in the result
variable implements both interfaces and has an overloaded .record
method with the same amount of arguments but different types.
Approach with two simple functions works without any warnings:
(defn long-callback
[callback-fn]
(reify Consumer
(accept [_ result]
(let [{:keys [value attributes]} (callback-fn)]
(.record ^ObservableLongMeasurement result
value
(otel.attributes/->attributes attributes))))))
(defn double-callback
[callback-fn]
(reify Consumer
(accept [_ result]
(let [{:keys [value attributes]} (callback-fn)]
(.record ^ObservableDoubleMeasurement result
value
(otel.attributes/->attributes attributes))))))
(defn as-callback
[callback-fn long?]
(if long?
(long-callback callback-fn)
(double-callback callback-fn)))
Not sure what happens, what I am missing? macroexpand clearly shows that the method call has metadata (checked using (set! *print-meta* true)
)answering to myself - :tag
should be a fully qualified symbol, e.g. {:tag 'io.opentelemetry.api.metrics.ObservableLongMeasurement}
, kudos to @U07FP7QJ0
nil is just a value. there is no reason to treat it differently imho
the rationale is: collections are heterogeneous collections of values and everything composes
(but admittedly nils in sets are rarely helpful)
It has been useful for me. For example let us say you have a vector of maps, and you want to check all of the distinct values for some key, and not all of the maps have the key.
If it wasn't possible to have nil in those sets it would just be completely bizarre and arbitrary
the problem with nil
(or false
) in sets is that containment checks return a logically false value both when the nil/false is found and when they are not found
@U08JKUHA9 i would use (every? key coll-of-maps)
Is that if you just want to use the set as a function directly and not use the contains?
function?
That doesn't do the same thing though, you are assuming my intention but that wasn't it
yes (remove my-set items)
etc
I am happy to know that there are use-cases where nil in set is useful.
I often do something like this
(empty? (set (map :d [{:a 1 :b 2} {:a 3} {:a 4 :b 5}])))
and when I forgot (filter identity ...)
it usually leads to some bug 🙂
Too late now of course, but I wonder if having the IFn implementation of set be like contains?
would be more useful than the current version where it returns itself?
or (every? #(contains? % :d) [{:a 1 :b 2} {:a 3} {:a 4 :b 5}])
to avoid set creation
Yeah.
I guess something like
(defn rebind [^clojure.lang.Var v f]
(let [old (.getRawRoot v)]
(.bindRoot v (f old))))
once I saw this gist https://gist.github.com/gfredericks/7143494 which probably later was extracted to a lib https://github.com/mourjo/dynamic-redef
That is a pretty solution.
@U5H74UNSF your rebind
is basically what with-redefs
also does, it's equally non-thread-safe (but should be good for testing purposes)
Can anyone think of a good reason that resolving aliases in custom tagged literals would be a bad idea? Context: Currently, tags are dispatched by their literal symbol, without resolving aliases, so this won't work:
(require '[my.long.namespace.name :as mlnn])
(set! *data-readers* {' mlnn/my-tag-reader}) ; or the equivalent in data_readers.clj
#mlnn/my-tag [:some :data :here]
It's possible, in principle, to make this work by binding *default-data-reader-fn*
to a function which resolves aliases and looks up the result in *data-readers*
. I'm tinkering with writing such a function, alongside some other tools for working with data readers. But the fact that alias resolution isn't supported natively makes me wonder whether that's a deliberate omission, and whether there's some good reason this shouldn't happen that I'm not seeing.why do you need this?
aliases are specific to the namespace context you are in. tagged literals can potentially be read from any namespace. so those two things seem at odds to me.
There are a few libraries that include a data_readers.clj
file. Because the Clojure documentation requires this, they are generally namespaced – but because nobody wants to work with excessively long names, these namespaces are generally extremely short, often one common word. To make up an imaginary example, if someone wrote an HTML library that uses readers, under common conventions their tags might be things like #html/element
. Personally, I'm not a fan of short namespaces like this – I think there's a high risk of collision, which feels particularly uncomfy for things that are loaded automatically whenever they're present on the classpath.
I'm noodling on the idea that improving the ergonomics of working with more deeply qualified namespaces on tags may make it feel a little safer to bundle readers into libraries. To answer your question, this isn't really something I need, but more of an experiment.
To me, it feels pretty natural to declare a namespace alias at the top of my file and then use that alias in reader tags throughout. I'd even say it's counterintuitive (subjectively, to me) that this doesn't work. I'm having trouble seeing where the tension would be in this functionality.
so you're talking about the qualifier on the tags, not on the impl
Correct. When defined – whether in a data_readers.clj file, or by binding the dynamic var – they'd still be fully qualified. But resolution would become sensitive to the aliases that are in effect in the context where they're read.
Not in principle different (...I think) from how vars in namespaces are always in themselves fully qualified, but may be referred to through aliases
I think the issue is with when these things are resolved. tagged literals are resolved at read time. the reader does have access to the current context namespace aliases (via the mechanism for resolving autoresolved kws), but that raises the bar for some kinds of tooling. symbols are resolved at compile or eval time (so later).
Ah hm, I didn't realize symbols weren't resolved at read time. Possibly the prototypes I've been playing with won't work as soon as I move out of the REPL.
I think there is some tension here with the goal of tagged literals too, which is to NOT tie tags necessarily to implementation details (the data_readers file is the binding mechanism there)
Actually wait, I did realize that :thinking_face: I'm mixing myself up by thinking of syntax-quotes, which do (I think?) resolve at compile time
er, read time
What in this ties the tags to implementation details? I'm thinking of this analogously to :as-alias
, where it's just a way to declare a shorthand which may or may not relate to a namespace where any actual code lives.
In practice it may even be used mostly with as-alias
I don't know, I think this needs problem clarification before getting to this level
Fair enough, thanks for sharing your perspective. My immediate goal here is to build a prototype I can play with to see how it feels and what problems may arise. If it seems fine and I release it into the wild, I'll definitely make sure the README is festooned with warnings that the usage patterns it enables are experimental and may have undiscovered design issues.
Hi folks, does anybody here know a bit of the internals of juji/editscript? I have got a conundrum/question around it
I have two structures that are quite different, say [{:a 2 :b: 3}]
and [{:foo "bar"}]
- I see the diff sometimes having the :-
(remove), sometimes only having :r
in it.
I am not sure if I am doing something wrong or the diff is not deterministic...but the :-
is very nice when you want to post-process the diff and, say, remove entities from the database
right, thank you that's a good correction of wording
I hope the issue is clear enough though
they may differ among different version of editscript, for we may tweak the algo sometimes
it is unpredictable which one it will use, for the slight change in data may lead it to a different path
I have noticed that if I increase the number of keys in the items above, say {:a 2 :c 3 :d 4 :e 5...
the algo becomes less and less likely to detect a deletion
yeah I think I noticed the same, thank you for confirming
the human eys’s sense of the size is not the same as the algo’s. The algo count size by number of nodes, so [] is a node itself, it counts
the original editscript many version ago count the size more like human, but i find that not our use case
right, I think that's throwing me off, if I had a set maybe the deletion detection would be more consistent?
basically I need a way to detect a deletion no matter the input size
editscript is not for human looking at the diff, it’s for machines, so it should be more like memory consumption
yeah, the issue is not in me reading the edit script, it is more to consistently detect deletions
ok sounds good, I will open one
I think it would make sense to configure it /cc @U03219RPYTS @U01PAJR4N69 (my colleagues)
is it currently configurable?
ok sounds good, thank you for your help - will open an issue to track this