-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8247402: Documentation for Map::compute contains confusing implementation requirements #714
8247402: Documentation for Map::compute contains confusing implementation requirements #714
Conversation
👋 Welcome back johnlinp! A progress list of the required criteria for merging this PR into |
Webrevs
|
Hi Jon, Can you explain what this change is about: e.g. something like:
because now I am confused. I believe what you are trying to do is what I have written above. Can you confirm? And are you going to withdraw #451 now? best regards, |
/csr |
@dfuch has indicated that a compatibility and specification (CSR) request is needed for this pull request. |
@dfuch May I ask how can I create a CSR? I checked https://wiki.openjdk.java.net/display/csr/CSR+FAQs and it says:
However, I don't have an account at https://bugs.openjdk.java.net/ yet. Therefore, I don't see the "More" button on https://bugs.openjdk.java.net/browse/JDK-8247402. Could you please tell me how do I proceed? Thank you. |
@johnlinp This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@johnlinp, you cannot create a CSR by yourself at the moment. Someone else will have to do that for you. Might as well be me. So here's my proposal: come up with the meat, then I'll help you with the paperwork. For starters, have a look at existing CSRs (you don't need a JBS account for that). For example, https://bugs.openjdk.java.net/issues/?jql=issuetype%3DCSR%20and%20Subcomponent%3Djava.util%3Acollections%20 Fill in an informal CSR template inline in this thread, and we'll proceed from that point. Is that okay? |
@pavelrappo Thank you for your kind help and great proposal. I'll write up a draft CSR in this thread. |
@pavelrappo Please see my proposed CSR below. Thank you. Map::compute should have a clearer implementation requirement.Summaryjava.util.Map::compute should have a clearer implementation requirement in its documentation. ProblemThe documentation of the implementation requirements for Map::compute has the following problems:
SolutionRewrite the documentation of Map::compute to match its default implementation. Specificationdiff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java
index b1de34b42a5..c3118a90581 100644
--- a/src/java.base/share/classes/java/util/Map.java
+++ b/src/java.base/share/classes/java/util/Map.java
@@ -1113,17 +1113,12 @@ public interface Map<K, V> {
* <pre> {@code
* V oldValue = map.get(key);
* V newValue = remappingFunction.apply(key, oldValue);
- * if (oldValue != null) {
- * if (newValue != null)
- * map.put(key, newValue);
- * else
- * map.remove(key);
- * } else {
- * if (newValue != null)
- * map.put(key, newValue);
- * else
- * return null;
+ * if (newValue != null) {
+ * map.put(key, newValue);
+ * } else if (oldValue != null) {
+ * map.remove(key);
* }
+ * return newValue;
* }</pre>
*
* <p>The default implementation makes no guarantees about detecting if the |
The proposed CSR has a few problems that we need to resolve.
|
I read my previous reply and realized that it is confusing and contains a factual error; so let me straighten it out in this new reply rather than edit that previous one.
Now, here's what I should have said in my previous reply. If the CSR intends to solve (2) then both the proposed pseudo-code and the Problem section must be updated; otherwise the Solution section must be updated. Put differently, either fix the diff and add one more item to that problem list, or change the solution. Otherwise the solution does not match the problem leaving the CSR in a contradictory state. I hope this all makes sense now. |
Let me clarify something. The "documented behavior" is actually the API specification, the contract that applies to Map.compute and all its implementations. The pseudo-code is part of the "implementation requirements" section, whose primary responsibility is to specify what the default implementation actually does. (Of course, that implementation should also conform to the API spec.) We've established that the pseudo-code -- either the existing or proposed version -- differs from the default implementation's actual behavior. It's thus failed its primary responsibility, and therefore that's the problem that needs to be fixed. I think it's pointless to clean up the pseudo-code if the result is still incorrect. |
@stuart-marks I thought about it before reading your reply. And since I hadn't come to a definite conclusion, I worded my response to @johnlinp as a choice. Although in this particular case it's easy to fix the discrepancy, I think it raises a general question which applies to all (pseudo-) code snippets in normative parts of API specifications: What is the required level of fidelity particular (pseudo-) code has to have? It's such a huge topic for discussion, that I don't even know where to begin; certainly, not in this PR thread. Perhaps we should start a dedicated (non-RFR/PR) thread on one of the OpenJDK mailing lists to host that discussion. |
@johnlinp In any case, you'd also need to update the surrounding prose; we need to remove this: |
It's potentially a large discussion, one that could be had in the context of my JEP draft http://openjdk.java.net/jeps/8068562 . However, speaking practically, it's possible to focus the discussion fairly concisely: the main responsibility of the In this case, a null-value-tolerating Map implementation needs to know that the default implementation calls |
So in this case - fixing the specification to match the default implementation seems to be the right call - as existing implementations that do not override are more probably depending on the current default behavior. |
Thank you all for giving me great advice. Sounds like the conclusion is to update the documentation to match the default implementation. I'll update this PR and propose a new CSR accordingly. |
…tion requirements
d058e79
to
d16a35b
Compare
@pavelrappo Please see my updated CSR below. Thanks. Map::compute should have the implementation requirement match its default implementationSummaryThe implementation requirement of Map::compute does not match its default implementation. Besides, it has some other minor issues. We should fix it. ProblemThe documentation of the implementation requirements for Map::compute has the following problems:
SolutionRewrite the documentation of Map::compute to match its default implementation and solve the above mentioned problems. Specificationdiff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java
index b1de34b42a5..b30e3979259 100644
--- a/src/java.base/share/classes/java/util/Map.java
+++ b/src/java.base/share/classes/java/util/Map.java
@@ -1107,23 +1107,17 @@ public interface Map<K, V> {
*
* @implSpec
* The default implementation is equivalent to performing the following
- * steps for this {@code map}, then returning the current value or
- * {@code null} if absent:
+ * steps for this {@code map}:
*
* <pre> {@code
* V oldValue = map.get(key);
* V newValue = remappingFunction.apply(key, oldValue);
- * if (oldValue != null) {
- * if (newValue != null)
- * map.put(key, newValue);
- * else
- * map.remove(key);
- * } else {
- * if (newValue != null)
- * map.put(key, newValue);
- * else
- * return null;
+ * if (newValue != null) {
+ * map.put(key, newValue);
+ * } else if (oldValue != null || map.containsKey(key)) {
+ * map.remove(key);
* }
+ * return newValue;
* }</pre>
*
* <p>The default implementation makes no guarantees about detecting if the |
@johnlinp, thanks for updating the CSR draft; it is much better now. @stuart-marks, I think we could further improve this snippet. This
I don't think we should include an optimization into the specification unless that optimization also improves readability. Is this the case here? Could this be better?
|
I would even go as far as to rewrite that snippet like this:
This rewrite is possible thanks to the following properties of
In particular, (2) covers To me, this rewrite reads better; however, I understand that readability is subjective and that snippets used in |
@pavelrappo The intended effect of the revised snippet is sensible, but again I note that it differs from the actual default implementation. Specifically: if the map does not contain the key and newValue is null, the default implementation currently does nothing, whereas the revised snippet calls |
The current snippet proposed by @johnlinp does seem to have the same behavior as the default implementation; I would avoid trying to "optimize" this. However, it does express the conditions and return value somewhat differently from the way the default implementation does. I think those differences are not significant to subclasses and are mostly stylistic. The original |
Although we should really have a conversation on code snippets in API specifications, this thread is not the place for that. However, I will minimally comment on some of what you've just said.
Perhaps there's some confusion. If anything my comment #2 was proposing to remove an optimization carried over from the default implementation. |
|
Hello github - this is my first ever comment. The javadoc specs for the various compute methods in all the Map classes should be maintained consistently and holistically. Sorry for not having done so years ago. Pavel is thinking about code snippets for all of OpenJDK today, while I have been thinking about code snippets in jsr166. jsr166 code snippets have a consistent style that should also be used for Map.java, but we've had a mild case of maintainer style divergence. |
@dfuch, @stuart-marks, and @Martin-Buchholz: thanks for reviewing the CSR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me.
@johnlinp This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 247 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@pavelrappo, @Martin-Buchholz) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
/sponsor |
@pavelrappo The change author (@johnlinp) must issue an |
Thank you all for the review and discussion. This is my first time contributing code in jdk, and it's a really nice experience. |
/integrate |
/sponsor |
@pavelrappo @johnlinp Since your change was applied there have been 247 commits pushed to the
Your commit was automatically rebased without conflicts. Pushed as commit 37dc675. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
This is from the mailing list: http://mail.openjdk.java.net/pipermail/core-libs-dev/2020-June/067190.html
Progress
Testing
Issue
Download
$ git fetch https://git.openjdk.java.net/jdk pull/714/head:pull/714
$ git checkout pull/714
Progress
Issue
Reviewers
Download
$ git fetch https://git.openjdk.java.net/jdk pull/714/head:pull/714
$ git checkout pull/714