medley icon indicating copy to clipboard operation
medley copied to clipboard

Add assoc-in-some function

Open erikcc02 opened this issue 2 years ago • 8 comments

Description:

This Pull Request adds the assoc-in-some function to the repository, complementing the existing assoc-some function. The assoc-in-some function was implemented to make it possible to associate values in nested associative structures, as long as the value is not null (nil).

Motivation:

The assoc-some function currently supports conditional binding on a single map level, allowing you to bind a value to a key only if that value is not null. However, this functionality is limited to top-level map structures and does not cover associations in nested structures such as maps within maps.

The new assoc-in-some function aims to fill this gap by allowing conditional associations at any level of a nested associative structure, such as maps within maps, vectors within maps, etc.

By providing a convenient way to perform conditional associations on nested structures, the assoc-in-some function simplifies code. It improves the readability of programs that deal with complex, nested data.

Example of use:

(def data {:user {:name "John" :email "[email protected]"}
           :preferences {:theme "dark" :notifications true}})

;; If the email is not null, it will be associated with the user
(def updated-data (assoc-in-some data [:user :email] "[email protected]"))

;; If the theme value is not null, it will be associated with the theme preference
(def updated-data (assoc-in-some data [:preferences :theme] "light"))

;; If the value passed is null, the original structure will be kept
(def updated-data (assoc-in-some data [:user :name] nil))

erikcc02 avatar Aug 07 '23 13:08 erikcc02

I'm on the fence about this. Could you give some reasons why using update and update-in are not sufficient?

(update data :user assoc-some :name nil)
(assoc-in-some data [:user :name] nil)

(update-in data [:account :user] assoc-some :name nil)
(assoc-in-some data [:account :user :name] nil)

Also, what are your thoughts regarding assoc-in-some vs. assoc-some-in?

Finally, can you change the commit message to Add assoc-in-some function for consistency with the commit log.

weavejester avatar Aug 07 '23 14:08 weavejester

Actually, see: https://github.com/weavejester/medley/pull/72#issuecomment-1447318586. I'm thinking the same reasoning applies here:

(some->> v (assoc-in data [:account :name]))
(assoc-in-some data [:account :user :name] v)

Given that this function would require more characters than the existing idiomatic solution, I'm inclined to close this for the same reasons as last time.

weavejester avatar Aug 07 '23 14:08 weavejester

The some->> example is missing one of the keys which is why it's shorter lol.

NoahTheDuke avatar Aug 07 '23 14:08 NoahTheDuke

@weavejester So, like https://github.com/weavejester/medley/pull/72#issuecomment-1448217787, I was also under the impression that separating this into a new helper function makes writing clearer.

When a person uses the assoc-some function, soon comes the need to have an assoc-in-some, maybe that's why other people also made this suggestion.

But I don't see any problems using update either :)

erikcc02 avatar Aug 07 '23 14:08 erikcc02

I updated the commit message

erikcc02 avatar Aug 07 '23 14:08 erikcc02

Also, what are your thoughts regarding assoc-in-some vs. assoc-some-in?

Looking at the Clojure documentation, some functions end with -in, but I like assoc-in-some because, in my opinion, it is more in line with the assoc-in function, just adding -some to the end

erikcc02 avatar Aug 07 '23 14:08 erikcc02

The some->> example is missing one of the keys which is why it's shorter lol.

Whoops!!

(some->> v (assoc-in data [:account :user :name]))
(assoc-in-some data [:account :user :name] v)

So I guess it's 5 characters shorter.

weavejester avatar Aug 07 '23 15:08 weavejester

@weavejester I was seeing that this function exists in another clojure lib: clojure-lsp https://cljdoc.org/d/com.github.clojure-lsp/clojure-lsp/2023.04.19-12.43.29/api/clojure-lsp.shared#assoc-in-some

I think having assoc-some and assoc-in-some in this library standardizes this kind of action well rather than using assoc-some and update or defining this function in your local project as a helper

erikcc02 avatar Aug 09 '23 12:08 erikcc02