Safer equivalence testing for IPersistentCollection implementation#1
Open
siefca wants to merge 1 commit into
Open
Safer equivalence testing for IPersistentCollection implementation#1siefca wants to merge 1 commit into
siefca wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I hit the issue when trying to use lazy maps as values of an underlying map of FIFO Cache (provided by
clojure.core.cache). After callingclojure.core.cache.wrapped/lookup-or-missto add a lazy map as (missing) value associated with some cache key, it was always added in realized form.After debugging I've found that the issue was a part of code where
clojure.core/=was called to compare a valuev(holding a lazy map) with a special value signalizing expiration:::expired. By default the=function usesclojure.lang.Util/equivto compare two objects andequivcallsclojure.lang.Util/pcequivwhen at least one of the compared objects implementsclojure.lang.IPersistentCollection. Then,pcequivpicks one of the objects implementingIPersistentCollectionand calls.equivon it with other object's value passed as an argument.As a result comparing lazy map with any value (like keyword, symbol or a number) causes full realization of delayed values. It is ok for comparing with other collections but when it comes to obviously non-matching objects (not collections), causes unexpected side-effects. Comparing a value with a keyword is common practice to handle special cases and therefore we should expect more scenarios like that.
Until Clojure will be changed to resolve the issue (see CLJ-1375) and/or
=will be replaced byidentical?incore.cache, it would be helpful to apply a workaround (the additional testing is very cheap operation).See also: