medley
medley copied to clipboard
Add assoc-in-some function
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))
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.
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.
The some->> example is missing one of the keys which is why it's shorter lol.
@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 :)
I updated the commit message
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
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 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