https://github.com/RutledgePaulV/missing/blob/develop/src/missing/core.clj#L291-L304
https://github.com/RutledgePaulV/missing/blob/develop/src/missing/core.clj#L270-L284
it sort of depends on the class. if there's an interface for it you can use java proxies to maintain the interface while adding additional stuff.
or if you can do a delegate pattern
delegate example to add metadata to an InputStream: https://github.com/RutledgePaulV/kube-api/blob/master/kube-api-core/src/kube_api/core/http.clj#L10-L25
Fellow clojurians, can anyone run this snippet
(let [zdt (ZonedDateTime/of (LocalDateTime/of 2020 12 31 0 0) (ZoneId/of "America/New_York"))
f (DateTimeFormatter/ofPattern "YYYY-MM-dd")]
(.format zdt f))
and say what it outputs? I’m getting “2021-12-31” on JDK10 and 11 for some reason
UPDATE: ok, solved. It’s just my formatting mistake.
– Y is for week-based-year
– y is for era year
So yyyy and all worksPlease add the imports for anyone too lazy to figure those out
Hello, after working on bots in ruby, for the past few months I've been working on a Slack bot in clojure, using the latest Slack events API & interaction API, clojure's async capabilities and other good stuff it provides help and command completion via back-and-forth with users for prompting values in the form of buttons/datepickers/etc. It allows you to define steps to generate an output with pedestal-backed interceptors. Registering a command looks like this:
A more complex command looks like this (with parameters and prompting):
I'm wondering now if it could be useful to others, and if I should try and release a library out of it Mind you, I'm new to Clojure and the code is probably not idiomatic, I could use some help in the process
Anyone have any luck installing Clojure CLI tools via HomeBrew on an Apple Silicon machine? Fails for me when trying to build an aarch64 OpenJDK. I’d like it to skip that step, but didn’t have any luck telling it to just ignore the dep (it goes looking for it even though it didn’t pull it in as a dep).
Is there a way to redefine a function that is called inside the function I want to test? Say function A calls B which calls an external API. I want to override B to return something so I can test A without having to call the API
the best choice is to parameterize, second best is to not use any threads and use with-redefs
parameterizing could mean taking an implementation of some protocol as an argument, and using a test-implementation in your test, or just taking a function to call as part of the argument list
this combines nicely with things like stuartsierra/component or integrant that do state management as well
(nb I mention not using threads explicitly because with-redefs is not thread safe)
Thanks!
there's also the in-between choice of using a dynamic var plus binding
to override - at least that's thread safe
Did you use the Clojure tap?
brew install clojure/tools/clojure
`
Or
brew install clojure
Those formulas declare java as a dep differently, not actually sure either will work
Where does it make the most sense to put your protocol definitions, supposing you have lots of them? You can put them all in a core namespace, but doesn’t this complect the core namespace? You can put them in lots of separate namespaces according to a separation of needs, but doesn’t this obfuscate their existence somewhat? And won’t it potentially result in many unclear requires?
Lots of separate namespaces according to a separation of needs; and these be in the private api; separate public api with plain functions that calls into them. Or so the mailing list says... https://groups.google.com/g/clojure/c/YwhOGCWquIM/m/bLC1YYGxe8MJ
this is part of why I hate the name "core" - the top level ns shouldn't contain the protocol definitions as they belong at the bottom of the require tree, and the top level ns belongs... at the top
then the top level definitions combine implementations of the protocols with functions calling protocol methods
there are plenty of clojure devs who avoid private definition, that's an implementation detail here
I’ve always wondered about that, too. I always put them in a separate namespace, so the implementation namespaces can require them, and the core api has functions calling the protocol methods, and requires the implementation namespaces so they get compiled. But is there an easier way?
I'd say that simply sharing it cannot hurt! there's nothing wrong with a tentative or 'playground' repo you might find specific help or perhaps some a kind code review over #pedestal
I need a few more large, java-heavy oss clj projects to try a certain tool on. e.g. Crux, Metabase. suggestions? :)
Not sure if they're java-heavy enough but: https://github.com/pallet/pallet (for an old one) https://github.com/riemann/riemann
bet they are transitively java-heavy at the very least ;p thanks!
hello! 👋 Can anyone help me understand why this code works the way it does?
(get 5 :foo) ; => nil
The documentation for get
indicates that a map should be provided, but if you provide any non-map data structure it still works without throwing an exception. I attempted to look at the source for get
but found that its definition was seemingly recursive and somehow bottoms out in clojure.lang.RT.a little more poking around in clojure.lang.RT yielded this section which I believe contains the answer I’m looking for https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L758-L793
so uh.. thanks for letting me rubber duck in here 😅
as that code shows, it works with anything that is ILookup, but also anything getFrom can handle
so it works on built in types clojure doesn't redefine:
)user=> (get "hello" 1)
\e
One caution (that @noisesmith refers to) is to never directly expose a protocol to the outside world. Do it via a function that then calls the protocol method. That way, you can change the protocol without impacting external callers. This way also helps if you need to later add any pre- or post-processing. If the protocol is only ever used internally, by namespaces you control, then the above is not needed.
it turns out that getFrom is quite permissive and returns nil instead of erroring on absurd input
a silly consequence of this is that any usage of get
can be replaced with (get get get get)
(even recursively, of course)
thank you for the additional detail! Normally I never would have tried to feed get
non-map input but the example in chapter 5 of clojure for the brave and true incidentally processes a map where an integer gets fed into get
and I was really surprised that it just worked
yeah, it can be the source of strange deeper bugs
see for example
user=> (get (atom {:a 0}) :a)
nil
oops! forgot to derefyikes that would be a pain to debug. Any idea what the rationale is for get
returning nil
instead of throwing an exception? I suppose it’s better to be permissive so that dynamic usage of get
doesn’t blow up in the wild maybe?
We've talked about writing this up to add it to the FAQ on http://clojure.org since it seems to trip every new Clojure developer up at least once, and there isn't currently a single place we can point folks to, by way of explanation.
Part of it is consistency: you can always call get
on something without an exception -- you just get nil
back if the "key" isn't found in the "collection". (get {:a 1} :b)
returns nil
, (get {:a 1} :b :c)
returns :c
(the "not found" arity). This is consistent with (coll :b)
returning nil
and (coll :b :c)
returning :c
-- since some collections can act as functions and look their argument up in themselves -- and also with (:b coll)
and (:b coll :c)
which is because keywords can also act as functions and look themselves up in their argument.
Returning nil
for "not found" (or the supplied "not found" value) means that you can omit a lot of special case checking and validation on the "coll" argument in all of this and know that if you get non-`nil` (or you don't get the "not found" value) then the "coll" does indeed contain the key and your code can continue. All other cases just reduce to nil
-punning without needing exception handling.
If you want an exception for non-collection arguments, you can check for the presence of the key with contains?
first: (contains? 5 :foo)
throws an exception.
There's also nth
-- compare against get
behavior:
dev=> (get [1 2 3 4] 10)
nil
dev=> (nth [1 2 3 4] 10)
Execution error (IndexOutOfBoundsException) at dev/eval10311 (dev.clj:1).
null
dev=> (nth 5 10)
Execution error (UnsupportedOperationException) at dev/eval10315 (dev.clj:1).
nth not supported on this type: Long
dev=>
Is that helpful background/motivation @mike973?
that is very helpful, thank you for taking the time to explain that. It’s also a good reminder that I should go and read up on nil-punning. I have a cursory understanding of it but this situation has certainly shed some more light on the topic
@dorab This is mostly about implementing the Datafy protocol for a bunch of different Java 0bjects.
^^ I wonder if you answers are still the same? @noisesmith @claudius.nicolae
in that case you aren't defining any new protocols, right?
@noisesmith no, I guess not. By definitions I meant function definitions (as opposed to calling a function).
one thing I've done for this is to require without a vector when requiring a namespace for its protocol extensions
most style guides say to never use require without the vector though
(ns my.ns
(:require extend.foo.to.bar
extend.foo.to.baz
[code.i.call.directly :as directly]))
the require is happening for a side effect (the fact that something gets extended by that ns)
so none of the require features that you'd use a vector for actually make sense
Thanks @alexmiller, the tap worked