Fork me on GitHub
#clojure
<
2022-05-09
>
jaju02:05:13

I understand that defrecord follows the equals/hashCode semantics of java.util.Map and works very well when one wants keyword keys. And that there is no way to override equals - but I am in a situation where using the convenience of defrecord will be great, but with a slightly modified equals (would like to ignore one of the keys in this case). What’d be a good way to approach this? (Maybe there is a totally different way of solving the problem at hand, but am keeping that aside because the above seems like an interesting thing to understand too)

phronmophobic02:05:20

There are a couple techniques, but it would be helpful to know why you want a slightly modified equals. Using a slightly modified equals can introduce unintended complexity down the road. A little more info about the use case might shed some light on some alternatives.

potetm02:05:15

yeah, my initial response is do

(defn my-special-equals [a b]
  (= (dissoc a :foo)
     (dissoc b :foo)))

jaju03:05:02

I’m using a sorted-set where each entry has a counter that needs updating. I’d like the counter to not take part in the equality so that it becomes easy to replace. (Needs to be tracked until the counter goes to zero).

jaju03:05:09

@U07S8JGF7 - the equals needs to override Object.equals for it to work - unable to supply my own for defrecord as there apparently isn’t a way to.

phronmophobic03:05:47

I'm still not totally sure what you're trying to do, but https://clojuredocs.org/clojure.core/sorted-set-by might be a better fit.

phronmophobic03:05:50

Another alternative is to put the data without the counter in the sorted set and keep the a map of item to counter separately

jaju03:05:26

Using sorted-set-by doesn’t help with the overriding equals - so, two items with different values for the counter attribute are distinct entries. My current version is in fact the item->counter map - but doesn’t feel like a natural split. Does the work but dealing with [k v] vectors or updating maps is 😢

phronmophobic03:05:05

what's the issue with updating maps?

phronmophobic03:05:38

Overriding equals isn't easy to do because it's rarely (if ever) a good idea, but it's hard to provide more specific advice without knowing more about the use case.

jaju03:05:59

There’s no issue with updating maps - but having a set and not splitting the item into item+counter would have been preferable. Guess there’s not much I can do using default facilities. That’s okay…

phronmophobic04:05:00

There are other options, but it's hard to recommend anything without knowing more about your use case.

jaju04:05:35

I mentioned this above, trying to remove the domain

I'm using a sorted-set where each entry has a counter that needs updating. I'd like the counter to not take part in the equality so that it becomes easy to replace. (Needs to be tracked until the counter goes to zero).
It’s a priority queue but each cycle can possibly only partially satisfy an item (tracked by the counter) - so, the item needs to stay until the counter goes to zero.

Max04:05:46

If your item is nonprimitive you can put the counter in meta

phronmophobic04:05:20

> trying to remove the domain That's the important bit. If you've already decided on an algorithm and particular data structures, then it's hard to recommend another algorithm or data structure that might be more idiomatic for your use case.

ryan echternacht03:05:25

I have trouble writing branching code that looks idiomatic. A good example is when the imperative version would look something like

let obj = someComplexObj

if (some condition not based on obj) {
  do 5-6 things to obj
} 

someFunc (obj)
I normally do this with something like
(let [obj (if outsideCondition
               (-> obj assoc assoc update assoc update upate)
               obj)]
^ but that feels awful when I write it. What do y'all use? (`cond->` comes to mind, but I find myself rarely reaching for it -- maybe I should?) Any tips?

seancorfield03:05:33

Refactor the "do 5-6 things" into a separate function?

potetm03:05:05

It’s pretty rare that I encounter anything remotely like this.

potetm03:05:14

Do you have an example?

seancorfield03:05:24

Then it becomes:

(cond-> some-complex-obj
  outside-condition (do-stuff)
  :then (some-func))

dgb2307:05:07

I recently asked a question with a code snippet that didn’t feel right in the code review channel. It turned out it was more of a structure/layering issue than a idioms issue. Might be what seancorfield might be hinting at as well. At this place you want to talk about control and make that clear. While there is some code upstream that does the data things. At the control site it’s about mechanism and coordination, at the data site it’s about integrity/invariants/domain logic, which doesn’t need to know the who, when, why. Communicating back and forth between them seems perfectly reasonable though, that’s just coordination.

Noah Bogart11:05:26

(Fancy meeting you here!) this sounds like you have two separate starting points: 1) is the obj and 2) is obj plus condition-dependent modifications. I’d say move both starting points to functions and then call one or the other based on the condition.

Chris Lavigne15:05:12

Hi Guys ! I'm looking for a clojure candidate in France for my startup which provides a full remote job position. Does someone is looking for an opportunity ? Thanks by advance

p-himik15:05:28

This message should be moved to #remote-jobs

dpsutton15:05:32

his Chris. Do you mind deleting this and then posting in the #jobs and #remote-jobs channels?

dpsutton15:05:50

(NB: including more information in your job posting will greatly increase your chances of finding a great candidate)

devn19:05:43

is this new?

devn19:05:27

i’m sort of watching pulumi from the sidelines and hoping to use it instead of CDK or pure cloudformation, but whenever i go looking at what’s supported, there’s something missing that i want

devn19:05:56

ah i see now that this is a preview

Noah Bogart20:05:03

type hinting question: I'm using the AmazonAWS java library, and i'm creating an AWSKMSClient like this: (let [client (.build (doto (AWSKMSClientBuilder/standard) (.setRegion "us-east-1")))] ... (.decrypt client request)), which throws a reflection warning on the decrypt call. This goes away if I type hint the binding: [^AWSKMSClient client (.build ...)] Is the hint needed because .build is a generic method on the builder's super class?

devn03:05:20

Hm, I’m not an expert on hints, but my gut would be that it doesn’t have to do with the superclass but instead that the ambiguity lies with .decrypt on a built object. Given how many ways there are to produce a client, perhaps decrypt is ambiguous on the kind of client.

devn03:05:17

I imagine that the same hint of ^AWSKMSClient on client within the .decrypt expression achieves the same result, yes?

Noah Bogart20:06:11

finally getting a chance to use the cognitect aws-api! it's cool as heck. I'm interested to know how all of the packages and sdks are generated. is that in the repo or is that internal?

kolstae21:06:31

It's sweet but I don't know how it's generated

👍 1
devn21:06:14

It's generated from big json definitions of the APIs

👍 1
devn21:06:34

which aws has in their repos iirc

Noah Bogart21:06:38

ah okay, cool. thanks