-
Notifications
You must be signed in to change notification settings - Fork 12
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
Should equals
over null
or undefined
by specified, and if so, how?
#151
Comments
I vote 👍 to define My reasons for returning
I additionally want to remark that a runtime check of |
I'm for allowing optional and nullable values (also in WebIDL). If JS would not have Also losing errors is not an argument. If the term is a return value of a function which claims to not return |
I think we should either agree to define it in specific way or not include it in the spec at all #150 . Having it loosely defined seems to me as worst case scenario since implementer can't assume how the method with behave and will need to code more defensively. I think one might actually prefer in that case to rely on custom function checking equality which follows a specific contract. |
This comment has been minimized.
This comment has been minimized.
More votes? @blake-regalia? Others? |
I prefer strict APIs over a permissive APIs because it trivially catches a large fraction of the likely errors. The effort in debugging an invocation of a permissive API typically involves a debugger and lots of rewinding from the first noticed problem, while catching the same error in a strict API typically happens so quickly and immediately we don't notice it. The occasions where one would sensibly want to generalize the equals to include if (previousPoster && equals(previousPoster, currentPoster)) { /* mark as self-reply */ } With the permissive API, that can be shortened to: if (equals(previousPoster, currentPoster)) { /* mark as self-reply */ } but I believe that hides the intention of the code. |
@RubenVerborgh I think you are giving an unfair representation to the issue. First of all, the suggestion was never to require implementors to explicitly
I'm glad you brought this up. Actually, after a bit of digging I found perhaps the strongest precedent: >> buf.equals(otherBuffer) from node.js throws a TypeError. <<
Saying that this only guards against an extremely small number of cases is totally incorrect as null/undefined is 1000000x more likely than
'Null pointer mistakes' and variables that were not initialized are exactly what implementors want to prevent by raising an exception. Please let us do so. . Furthermore, you cannot argue for consistent behavior for all 'universal' cases and then surrender to not checking for
......
Consider thisAssume that // fill an array with terms and maybe some nulls
let a_terms = [
...functionThatYieldsTermsAndNulls(),
];
// test every pairwise combination
let nl_terms = a_terms.length;
for(let i_a=0; i_a<nl_terms; i_a++) {
for(let i_b=i_a+1; i_b<nl_terms; i_b++) {
// found a duplicate
if(a_terms[i_a].equals(a_terms[i_b])) {
console.log('found duplicate');
}
}
} If The point is that some of want to protect against |
This was definitely not my intention. I raised an open question regarding
You are suggesting unspec'ed. Unspec'ed means concretely that implementors have the freedom between returning 1)
None of us are making broken arguments on purpose. As I said, happy to be proven wrong. To your concrete point
Yes I can: |
Sorry I made a typo; should be |
I'm not sure why malformed |
It seems that those two come as mutually exclusive requirements which I see as motivation for #150 This way as libraries which want to rely only on what Mandating one of those mutually exclusive requirements in the spec, would prevent compliant factories to choose to implement it the other way. Taking the 👎 leave open in the spec would allow implementations to choose either way, but then it would put developers in the similar situation as not defining it at all, since they would need to either rely on a equality function which has clear contract matching their expectations, or ensure that all terms get produced by a specific factory. In that case not including it the spec feels a cleaner option. Given current vote counts on 👍 define in the spec, return false. What people voting this way can recommend for implementations which need different behavior but still want to comply with the spec? |
For instance, check for |
@blake-regalia About the If Node.js defines it different to ECMA, I would rather follow the examples from ECMA as our spec is about JS. Also I see it even as an argument for my |
I would happily agree if there were any examples from ECMA on objects (i.e., non-frozen values that inherit from
Empty and null are completely different. The
Anyways, it seems like we are split on this issue and nobody will be happy either way. As it stands, I cannot support |
You get the empty What I don't understand, if you want such strict typing for RDFJS, what about the rest of your code? How can A function returns a const term = functionReturnsOptionalTerm()
if (other.equals(term)) {
// you never reach that point with term === null
} Another function always returns a try {
const term = functionReturnsAlwaysTerm()
// you never reach that point with term === null...
if (other.equals(term)) {
}
} catch(err) {
// ...cause you will end up here
} I'm still curious in which cases accepting |
Thanks @bergos 🙂 , the point is not to try/catch, nobody is suggesting to write try/catch blocks for
const term = functionReturnsOptionalTerm()
// term may be null/undefined and i, the dev, *know* that is part of
// the return range for functionReturnsOptionalTerm; so i test for
// falsy before using it as a term anywhere
if (term && other.equals(term)) {
}
const term = functionReturnsAlwaysTerm();
// no need to test for falsy term since it is *assertable* that it
// should *never* return null/undefined. if an exception is raised here,
// then there is a *bug* with functionReturnsAlwaysTerm
if (other.equals(term)) {
} |
Thanks for explaining @blake-regalia. So in the end it's about priorities. For me it's more important to have null/empty feature than faulty code handling. Also what we are working on is a spec and not a law. You are free to work outside the spec. Maybe you can do it even like this:
Well documented in the readme, so everyone knows this is a custom feature. |
https://gitter.im/rdfjs/Representation-Task-Force?at=5c5e0715adf6cb0b2c87a986
I see he voted with 👀 but it does have slight preference on 🎉 |
// spec + throw error on null interface
const factory = require('my-factory')({ throwNull: true }) Instance created with this factory will not conform to the spec any more since when |
I'm aware of it. I'm not saying this should be used by a library, but if you want, you can do it in your app. Also you should be aware that you risk compatibility with other libraries. |
Based on 8 👍 , 3 🎉 and 3 👀 votes, we will allow How should we write it in the spec? Some details we have to clearify:
I prefer define it optional and nullable in WebIDL. Maybe explicit mention the falsy check is a good idea. |
That is possible; reason I explicitly wrote
We do not; the reference code has an optimization in there, which is not necessary to be spec'ed. |
I suggest reapplying the patch I removed from #142 : diff --git a/interface-spec.html b/interface-spec.html
index f0f7b01..5f4cc36 100644
--- a/interface-spec.html
+++ b/interface-spec.html
@@ -129,7 +129,7 @@
interface Term {
attribute string termType;
attribute string value;
- boolean equals(Term other);
+ boolean equals(optional Term? other);
};
</pre>
@@ -168,7 +168,7 @@
interface NamedNode : Term {
attribute string termType;
attribute string value;
- boolean equals(Term other);
+ boolean equals(optional Term? other);
};
</pre>
@@ -193,7 +193,7 @@
interface BlankNode : Term {
attribute string termType;
attribute string value;
- boolean equals(Term other);
+ boolean equals(optional Term? other);
};
</pre>
@@ -222,7 +222,7 @@
attribute string value;
attribute string language;
attribute NamedNode datatype;
- boolean equals(Term other);
+ boolean equals(optional Term? other);
};
</pre>
@@ -263,7 +263,7 @@
interface Variable : Term {
attribute string termType;
attribute string value;
- boolean equals(Term other);
+ boolean equals(optional Term? other);
};
</pre>
@@ -289,7 +289,7 @@
interface DefaultGraph : Term {
attribute string termType;
attribute string value;
- boolean equals(Term other);
+ boolean equals(optional Term? other);
};
</pre>
@@ -333,7 +333,7 @@
attribute Term predicate;
attribute Term object;
attribute Term graph;
- boolean equals(Quad other);
+ boolean equals(optional Quad? other);
};
</pre>
If we reopen #142 I'll do it |
That's ok for me, I just want to be sure we all agree on it and there is no need to change the reference code to make explicit comparisons against |
In #142, we were discussing whether
equals
should be defined overnull
andundefined
. Let's express opinions with arguments here. Please be clear and brief.Please vote with on this message:
The text was updated successfully, but these errors were encountered: