Fork me on GitHub
#clojure
<
2022-04-07
>
jumar10:04:17

I've been reading about print-dup a bit and I'm wondering about their relationship to tagged data literals and printing via pr/prn and reading back through read-string. To have a concrete example - https://github.com/clj-time/clj-time/commit/e5c9cce321e923464a3480ae04e4a43abdd4fc7e so it can be printed and read easily :

(pr-str (org.joda.time.DateTime.))
;;=> "#clj-time/date-time \"2022-04-07T09:35:13.158Z\""

(read-string "#clj-time/date-time \"2022-04-07T09:35:13.158Z\"")
;;=> #clj-time/date-time "2022-04-07T09:35:13.158Z"
However, print-dup is not defined for such objects:
(binding [*print-dup* true] (pr-str (org.joda.time.DateTime.)))
Execution error (IllegalArgumentException) at codescene-cloud-web.sign-up.routes/eval128869 (form-init6498231345551227843.clj:118).
No method in multimethod 'print-dup' for dispatch value: class org.joda.time.DateTime
It seems that https://github.com/clj-time/clj-time/commit/e5c9cce321e923464a3480ae04e4a43abdd4fc7e#diff-24500a457f4ccb44854b3f3c6b9f8f8a1b5259c61b52dc1f61b9e3440eb5cc7aR110-R112https://github.com/clj-time/clj-time/commit/e5c9cce321e923464a3480ae04e4a43abdd4fc7e#diff-24500a457f4ccb44854b3f3c6b9f8f8a1b5259c61b52dc1f61b9e3440eb5cc7aR110-R112. So I'm wondering what's the case of using one or the other or if I should always try implementing both of them. And/or if there's a different use case when print-dup might be handy. Here are some of the resources I looked at: • Can someone explains the difference between print-method and print-dup once and for all?https://groups.google.com/g/clojure/c/R-9Pwk3HcFkSerializing Clojure objects: https://groups.google.com/g/clojure/c/5wRBTPNu8qo [2008 discussion with a couple of comments from Rich Hickey]Clojure: Next Steps (Stuart Sierra) https://stuartsierra.com/download/2011-11-10-clojure-next-steps.pdf#clj-time/date-time is included in clj-time 0.15.0+https://github.com/clj-time/clj-time/commit/e5c9cce321e923464a3480ae04e4a43abdd4fc7e • time literals for java.time objects: https://github.com/henryw374/time-literals

Kris C13:04:23

Which one would you use (conditional add to map) and why: (merge {:a 1} (when true {:b 2})) or (into {:a 1} (when true {:b 2}))

p-himik13:04:22

I offer a third option:

(cond-> {:a 1}
  true (assoc :b 2))
(or merge instead of assoc if there's more than one item)

🎯 3
dpsutton13:04:08

In general i would use merge rather than into for this though

p-himik13:04:11

My IMHO on the above - merge is about merging maps, and that's exactly what you want. into is more generic, and in this particular case you don't benefit from it being that way.

Kris C13:04:39

ack, thanks

dpsutton13:04:19

Yeah. just semantically you want to merge two maps together. It has the merge rules you most likely want. And can take arbitrarily many maps which into can’t really do without combining the maps yourself in some manner

Lucas Jordan14:04:14

I am using datomic cloud. I have a list of eids, I want to pull all of them in one query. How do I do that?

Joshua Suskalo14:04:01

You might get more relevant responses in #datomic

👍 1
Joshua Suskalo15:04:57

So just how magic is the transducing arity of map? Like how does it make sense for there to be a transducer that takes multiple arguments per step? Is that something that only map can do? Or can other transducers do that too?

dpsutton15:04:35

I think reading the source of the transducer arity of map, filter and cat can be illustrative and remove the magic

Joshua Suskalo15:04:11

Yeah, I've read them, and it seems like there's just special magic about using sequence and map together.

Joshua Suskalo15:04:22

I don't see any particular reason why map in particular should be so magic, like you could conceivably do like (filter <) or something followed by a map that takes multiple items.

Alex Miller (Clojure team)15:04:35

map and sequence are the only paths into multi-source transducers

Joshua Suskalo15:04:49

was there a particular rationale as to why

(comp (filter <)
      (map vector))
couldn't be valid? Or is it just that there was no need/request for it?

ghadi15:04:00

note that there is no variadic non-transducer filter

Alex Miller (Clojure team)15:04:02

< doesn't take 1 vector though, it takes N args

Alex Miller (Clojure team)15:04:25

there is space here for future work. we haven't tried to do that work.

Ben Sless15:04:01

Some api for functions to find the correct arity when they compose?

Joshua Suskalo15:04:29

Well yeah, you would call it like (sequence xf [1 2 3] [4 5 6]) and the output would include each pair because the right one is always greater than the left.

Joshua Suskalo15:04:49

it's the same as the multi-source map transducer more or less

Joshua Suskalo15:04:28

The only thing that seems to be missing here is an allegorical arity of filter that takes multiple sequences, mostly because it's unclear how you could return the value without wrapping it into a vector or similar.

Joshua Suskalo15:04:05

and perhaps the wiring for allowing multiple sources to be maintained between steps in a transducer

2
Alex Miller (Clojure team)15:04:29

that wiring exists in clojure.lang.TransformerIterator

Alex Miller (Clojure team)15:04:08

it's really an api problem in applying the transducing function

ghadi15:04:33

symmetry or something being missing is not necessarily a strong motivating problem statement

Alex Miller (Clojure team)15:04:33

there is also some magic for map entries that probably conflicts with some of this

Joshua Suskalo15:04:53

Yeah, I'm not proposing effort be put into this, I have no problem this solves, I was just curious if there was specific thought put into why filter can't work similarly, just calling the wrapped reducing function with the extra arguments as with apply, which would allow it to work with the reducing function produced with map nicely.

Joshua Suskalo15:04:25

although, despite me not thinking it's worth putting significant effort into, it does seem pretty trivial:

(defn filter*
  [pred]
  (fn [rf]
    (fn
      ([] (rf))
      ([result] (rf result))
      ([result input]
       (if (pred input)
         (rf result input)
         result))
      ([result input & more]
       (if (apply pred input more)
         (apply rf result input more)
         result)))))
The only change between core filter's transducing arity and this one is the inclusion of an additional arity in the resulting reducing function

Alex Miller (Clojure team)15:04:36

transducers extend the history of deciding not to solve this generically with sequences :)

👍 1
Alex Miller (Clojure team)15:04:26

but at some point something may put pressure on this and then we'll figure it out :)

vlaaad19:04:13

Was there an article somewhere about different strategies for adapting one protocol to another?

Alex Miller (Clojure team)20:04:05

I have some stuff in Clojure Applied about it

Alex Miller (Clojure team)20:04:41

there are a bunch of strategies with tradeoffs, the best answer is to not do it at all :)

Alex Miller (Clojure team)20:04:54

but probably the next best is to use functions wrapping protocols as an opportunity to adapt/reroute

Alex Miller (Clojure team)20:04:44

(defprotocol P1 (m1 [_]))
(defprotocol P2 (m2 [_]))

(defn pm1 [o] ;; wrapper for P1/m1
  (if (satisfies? P2 o) ;; detect as needed
    (m2 o)              ;; adapt as needed
    (m1 o)))            ;; fall back to P1

Alex Miller (Clojure team)20:04:23

and beyond that is using extensions to Object mostly

macrobartfast19:04:45

I’m getting back into dev and Clojure/Script. I’m pretty sure I’m into a lot of ineffective anti-patterns in how I’m approaching developing (and always have been, I’m sure). Basic concepts aside (which I definitely need to keep working on) I don’t think I’m working with the repl correctly. I think a set of eyes would immediately identify some major missteps in how I’m going about things. I am wondering if anyone might be willing to look over my approach via Zoom screenshare for any amount of time (even just 10 minutes would be probably really helpful)… I’m camera shy so would just be my editor and voice, probably, and I don’t expect any more than that from you; you wouldn’t even need to share anything from your side. I seem to be addicted to Emacs and Cider but I’m not at all against trying other editors. I know that other editors are quite capable now… I’m still addicted to the fast Emacs bindings. I mention this because I’m also interested in Emacs workflows if anyone has that set up I’d love to learn. The proper thing is for me to post problems and I try my best, but I think what I might be missing at times is the amazing amount one can get if one is in an office where a coworker can notice ridiculous things I’m doing and point them out. These are things I can’t properly ask about since I’m unaware of them. I’m getting into front and back end dev and would be happy if anyone looked at any part of that. I could and will go to live events but I’m taking care of the ailing folks right now so a bit unable to do that, in case you’re wondering why I’m reaching out here. Mentioning this in #cider too, but open to any editor approach. Feel free to DM me here if this would be something you’d be up for… and thanks for the time reading this!

magnars20:04:39

I always found it interesting watching other people code and see their workflows as well. Which is one reason I started creating some video series with live coding. While most are in Norwegian, one is in english here: http://www.parens-of-the-dead.com Maybe that could be of interest? It shows off some cool Emacs and CIDER/refactor-clj tricks.

❤️ 2
apt21:04:36

https://clojure.org/guides/repl/introduction this guide is quite good if you rely too much on cider stuff and want to know stuff under the hoods, maybe consider using something simpler like inf-clojure or simply stop using most cider keybindings

macrobartfast00:04:19

Great help! 🙂 Can’t wait to look at parens-of-the-dead… and also inf-clojure (though Cider has been pretty good so far).

jumar03:04:23

If you are already familiar with Emacs + Cider, or even “addicted” I don't see a reason why you should jump onto something else. It's a very powerful combo. Perhaps I can find 20 minutes next week if you are interested.

🎯 1
macrobartfast07:04:24

I would be more than grateful! And yes, a bit addicted… or maybe it’s just that by the time I actually think “time to code” my fingers have already opened Emacs as a reflex. Which is basically the same thing for most the key bindings I know in there. 🙂

macrobartfast19:04:51

I’m open to other thoughts for getting unstuck, btw!

marciol22:04:56

Hey, I'm trying to bind a Java class to a var, so that I can inject it in a function, but for some reason I'm not having success. What I'm doing:

(def my-class MyClass)
(. my-class someStaticMethod) ;; it doesn't work
(. MyClass someStaticMethod) ;; it works
Anyone can help to shed light on what is the current issue with these attempts?

Joshua Suskalo22:04:31

Maybe I'm wrong, but I think the . special operator doesn't evaluate the first argument normally? Like if the symbol doesn't resolve to a class, it will try to call the symbol someStaticMethod as if it were an instance method on the type of the value referred to by my-class, and the type of that is Class, and there's no instance method someStaticMethod on Class.

marciol22:04:02

Exactly what is happening

Joshua Suskalo22:04:04

if you want to call a static method from a class that's held as a value, then you should use the reflection API directly.

Nundrum22:04:43

You might want to check #interop where I have been struggling with this sort of thing repeatedly 😅