This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-10
Channels
- # announcements (3)
- # babashka (3)
- # beginners (83)
- # calva (1)
- # cider (19)
- # clojure (131)
- # clojure-austin (4)
- # clojure-dev (3)
- # clojure-europe (49)
- # clojure-greece (2)
- # clojure-italy (8)
- # clojure-losangeles (18)
- # clojure-nl (14)
- # clojure-poland (1)
- # clojure-uk (65)
- # clojurescript (28)
- # core-async (7)
- # core-logic (3)
- # cursive (2)
- # data-science (1)
- # datomic (98)
- # defnpodcast (1)
- # figwheel-main (6)
- # fulcro (95)
- # graphql (5)
- # hoplon (7)
- # kaocha (1)
- # lein-figwheel (6)
- # luminus (1)
- # nyc (1)
- # off-topic (21)
- # pedestal (1)
- # quil (8)
- # re-frame (15)
- # reagent (106)
- # reitit (15)
- # shadow-cljs (158)
- # sim-testing (1)
- # spacemacs (17)
- # sql (25)
you can write a macro that does something "on the fly" but given it's a macro, the fly is the time that the macro is expanded, which is part of compiling the code
which means you can compile new code as part of your algorithm (aka eval
) or find something else equivalent to what the macro does
expect other devs to be very suspicious of code that uses eval
also probably worth mentioning that RH has talked about the utility of late binding / dynamic extension, in the form of using multimethods or protocols instead of case / cond / match macros; if you do this his way the problem solves itself (but you lose the pretty match macro)
@emccue useful is decent https://github.com/clj-commons/useful
it's actively maintained, and doesn't have a huge dep tree
also the quality of the code itself is well above the average baseline for clojure libs last I checked
this might be a clue https://github.com/clj-commons/useful/blob/master/build-docs.sh - it uses a gh-pages branch of the repo via codox
"lein doc" builds the doc files
here's the branch they propagate via that script: https://github.com/clj-commons/useful/tree/gh-pages - I assume there's an index file
I wonder if there's a way to treat all that html as a website - not through github itself it seems
you could check out the code, and switch to that branch, and browse locally I guess
@U051SS2EU Thanks
@emccue I think map-keys
and map-vals
are under consideration for core at some point (maybe 1.11)? I think I read that somewhere.
yes, or at least map-vals, although probably not under that name
If you are using CLI/`deps.edn` and want those functions with no deps, use https://gist.github.com/seancorfield/6e8dd10799e9cc7527da5510c739e52f
(yes, you can have a multi-file gist as a git dependency in deps.edn
! Isn't that cool?)
that would do what?
http://clojure.github.io/test.check/clojure.test.check.generators.html -- no such function?
test.check generators are designed to be the only source of novelty in generated values (not arbitrary other functions) - this has several purposes. First, it allows the generator to use the same seed and generate the identical values. Second, it allows the generator to control how values are "shrunk" in the case of a failure to a simpler failing value.
@emccue Depending on what you're trying to do, I suspect you want fmap
over a known set of values?
There's a shuffle
generator. So maybe fmap first
over that?
(defn random-tile
"Generates a random tile"
[]
(let [shuffled-ports (shuffle tile-ports)
pairs (mapcat (juxt vec (comp vec reverse))
(partition 2 shuffled-ports))]
(into {} pairs)))
(def tile-generator
(gen/fmap
(fn [shuffled-ports]
(let [pairs (mapcat (juxt vec (comp vec reverse))
(partition 2 shuffled-ports))]
(into {} pairs)))
(gen/shuffle tile-ports)))
(defn random-tile
"Generates a random tile"
[]
(gen/sample tile-generator 1))
if you can enumerate all possible tiles, I would just use (s/gen the-set-of-tiles)
since all of the specs know how to generate already, it's often much easier to build a simple spec, and use its generator
or use (s/gen (s/tuple ...)) then gen/fmap or gen/bind over that
Hello! I want to 1. extract a thing (a person) from a collection, 2. verify that it exists and passes a test (`:alive`), 3. bind it for future use. Is there a better way to do this (extraction + test yet returning the thing, not the boolean result of the test fn) then
(if-let [jon ((fn [person] (when (:alive person) person))
(get people :jon))]
jon)
? Thank you!
I could also (if-let [[jon] (filter :alive
[(get people :jon)]
jon)
but it feels wrong to have to wrap and unwrap [] to do thisdestructuring inside if-let doesn't work like you expect
It doesn't? Could you be so kind and explain? Thank you!
user=> (if-let [[x] []] [:yes x] :no)
[:yes nil]
the if-let uses the truthy branch if the entire input is truthy (`[]` is truthy here) and doesn't care if the actual binding is nil
closer matching your example:
user=> (if-let [[x] (filter even? [1 3 5])] [:yes x] :no)
[:yes nil]
Thanks!
You could do
(when (get-in people [:jon :alive])
(get people :jon))
Well, the goal is to only get
once.
(let [jon (get people :jon)]
(when (and jon (:alive jon))
jon))
I am using it only once here 🙃In all seriousness, I feel like we are complecting checking whether a particular person is alive, with getting them from a collection here. Maybe the filter is a separate step in a collection operation.
(-> (filter #(:alive (val %)) people)
(keep [:jon :jim :jack :jones]))
I guess I will go with if inside let. I'd prefer less nesting but there seems to be no nice way. Yes, I'm doing two things but in my mind it is one - "give me thing X that satisfies condition C"
(when-let [jon (some->> people
(filter (fn [[person-name {:keys [alive]}]]
(and alive
(= :jon person-name))))
(first)
(second))]
jon)
Not much different from the other suggestions, and no closer to what you want, I guess. 😕
If I have an instance of a class, and I'd like that instance to extend a protocol without affecting all instances, is that possible?
Why not close over your instance with a reify
, does this thing also need to behave as your original instance, in all other contexts?
The problem with external extension or extension via metadata is, if the instance at hand already implements the protocol via deftype
or defrecord
, then we cannot override it with metadata or extend
. The only way to override that is via reify
.
As yuhan pointed out, this is the order in which Protocol implementations are searched:
Protocol implementations are checked first for direct definitions (defrecord, deftype, reify), then metadata definitions, then external extensions (extend, extend-type, extend-protocol).
If the class of the instance at hand doesn't already implement the protocol, I wonder why you care if your extension applies for all instances. Is this in library code or application code?
I'd like it to behave like the original instance. This would be in library code, and I don't think a library can claim ownership of the class in this case. It's an integration library.
You probably could via metadata if the protocol supports it: https://clojure.org/reference/protocols#_extend_via_metadata
Is it possible to make alias in deps that enables other aliases. So for instance if I have a tool like Cloverage which is run through alias cloverage, I'd like to always run it with dev and test alias enabled
not sure the best channel to ask this in, but is anyone interacting with stripe from their clojure project? looks like stripe-clojure listed under “other” on the stripe site hasn’t been touched in ~5years
https://github.com/clojurewerkz/elephant seems far more active than that, and from good source (clojurewerkz)
@U06BE1L6T that realization kind of dawned on me while i was taking my dog outside later that morning. look at their curl examples and just use clj-http. that’s what i’m using for other services i’m interacting with as well. thanks!
(defprotocol Bird
(fly* [_]))
(defprotocol ToBird
(to-bird [_]))
(defn fly [birdlike]
(if (satisfies? Bird birdlike)
(fly* birdlike)
(fly* (to-bird birdlike))))
which would let the user override it - with the downside of overriding your definition
wouldn't that be simpler as a multimethod with to-bird baked into the bird impl?
@emccue I don't think so, because another library could also soft claim this object type leading to a conflict.
(defn make-your-datasource [existing]
(let [impl (reify DataSource ...)]
(do (extend-type (type impl) ...)
impl))))
oh I missed that, and that's weird
@emccue consider something like component/integrant. You may start
by just calling (.connect)
or you might do (.connect) (.migrate)
or any other number of things. Maybe if you're returning a data source for mysql, you need some specific contextual setup.
I'd make a new class (eg. proxy) that delegates to your instance for everything
it sounds like this is an attempt to work around the general wisdom for protocols of "only extend a protocol to a type if you own the type or the protocol", the idea being "ok, even if I don't own the type, I own this instance of the type, so I want to extend the protocol to just this instance"
(defprotocol A (a [_]))
(extend-type java.util.List
A
(a [_] 1))
(extend-type java.util.ArrayList
A
(a [_] 2))
(a (java.util.ArrayList.))
(a (java.util.LinkedList.))
Seems like the protocol is at the wrong layer - wrap the datasource in a map and extend by metadata
I think a proxy that delegates to your instance is cleaner - it's a singleton instance of a class by design, or you can make a new type if you need multiple instances
its a connection to a thing - its probably being used, not inspected or passed over the wire
> Seems like the protocol is at the wrong layer - wrap the datasource in a map and extend by metadata This is pretty much what I was thinking. Eschewing the protocol altogether though. Just use a map and define the "methods" as key->var references.
I think it's an intrinsically place-oriented problem so a good solution will be place-oriented
Extension by metadata is a relatively new thing, but making a defrecord/deftype will definitely work