-
Notifications
You must be signed in to change notification settings - Fork 150
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
CIP and Scenarios for precedence rules #502
Conversation
5417650
to
8363a11
Compare
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.
Thanks. Got some comments :)
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.
Thanks
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.
Great work on this! We have a few minor suggestions and questions, and then we found (what we believe) is one bigger problem. Let us know what you think.
Co-reviwed-by: Nadja Müller @nadja-muller
* https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=ListComprehension[List comprehensions] | ||
* https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=PatternComprehension[Pattern comprehensions] | ||
* https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=Reduce[Reduce operator] | ||
* quantifiers |
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.
Do you maybe want to expand on the definition of these? I'm assuming it's referring to All()
, Any()
, Single()
and None()
?
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.
Quantifiers do not have their own grammar production has they are not really referencable like the other things. I can
a. Just extend the text here a bit, or
b. Modify the grammar so that they have their own production
The latter is the bigger change, but I still lean towards it, because it is a bit of an oddity that the grammar does not separate the quantifiers out into their own production. Opinions?
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.
I don't have a strong opinion, as long as we clarify what those quantifiers are. For what it's worth, Neo4j does the latter.
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.
Done. Note that link does not work yet, since it always goes the master branch.
|Level |Group |Operators | ||
|
||
|12 | ||
|Atoms |
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.
Is ShortestPathPattern
missing from this table?
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.
Is MapProjection
not part of openCypher?
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.
Regarding map projections, that is a good question. Somethings were excluded back then. There is no trace of map projections in the grammar and the TCK, as far as I tell based on a quick look. However, the Cypher 9 Reference has them. So it is a mixed picture.
Shortest paths have a similarly mixed picture. The reference and the grammar have them as part of pattern in the match clause, the TCK does not have scenario on them. Shortest path in expressions, which is the bit relevant here, is non of the oC artifacts.
It is probably worth asking CLG about these two things.
* https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=PatternComprehension[Pattern comprehensions] | ||
* https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=Reduce[Reduce operator] | ||
* quantifiers | ||
* https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=RelationshipsPattern[Pattern predicates] |
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.
Is pattern predicates
the correct term?
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.
For me a naked pattern appearing as an expression is a pattern predicate. The oC grammar does not have an extra production for pattern predicates, because these have the same syntax as the RelationshipsPattern non-terminal. However, the RelationshipsPattern non-terminal is not only used for pattern predicates but also in pattern comprehensions. Hence, we can not rename the RelationshipsPattern non-terminal to pattern predicate.
In other words, when appearing as an atom a RelationshipsPattern is a (or plays the role of a) pattern predicate. Again, adding an extra production to the grammar would clarify this picture a bit.
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.
I see. I was more confused on the term "pattern predicates" because of GPMs "node pattern predicates" and "relationship pattern predicates".
Is a naked pattern appearing as an expression generally referred to as "pattern predicate" in oC? It's easy to mix up with the GPM predicates.
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.
Well, generally. Terminology evolves with understanding and with people. It is in far a more recent term that we, i.e. the CLG, took the decision that naked patterns in expressions should evaluate to a boolean (rather than a list of paths, as they used to). It was argued, that patterns in match are also understood as predicates. So pattern elsewhere in the language should also behave like predicates. In general, it something evaluates to boolean it is reasonable to call it a predicates.
Anyway, it may be good to encode this name in the oC grammar. I am happy to do that. It is a conclusion that is somewhat similar to the one we have to quantifiers. :-)
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.
Done. I have also updated CIP2015-05-13-EXISTS
to grammar refactorings (rendered view), which provides a clear introduction point of the term "pattern predicate" now. It used the term already before, but now it does so much more prominently.
|=== | ||
|Level |Group |Operators | ||
|
||
|12 |
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.
I think the levels are usually the other way around, where 1
has highest precedence (see e.g. C++ Operator Precedence).
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.
Depends who you ask (see, e.g. https://introcs.cs.princeton.edu/java/11precedence/ or https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table). It is likewise confusing to say the highest has the lowest number as it is confusing to have the highest level shown lowest in the table.
Probably for exactly this reason, many lists do not given any numbering at all. We can do the same here.
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.
Fair enough! I don't have a strong opinion, but I did find it convenient to have a level number to refer to when doing the reviewing. So I'd suggest keep it as is.
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.
As a minimal improvement, I have add a note before the table saying
The higher the level number the higher the precedence.
Hopefully that helps to avoid confusion.
.3+|10 | ||
|https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=StringOperatorExpression[String operators] (left-hand operand) | ||
| | ||
|
||
* Prefix predicate (and right-hand operand) | ||
* Suffix predicate (and right-hand operand) | ||
* Contains predicate (and right-hand operand) | ||
* Regular expression predicate | ||
|
||
|https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=ListOperatorExpression[List operators] (left-hand operand) | ||
| | ||
|
||
* List element containment predicate (and right-hand operand) | ||
* List element access | ||
* List slicing | ||
|
||
|https://raw.githack.com/openCypher/openCypher/master/tools/grammar-production-links/grammarLink.html?p=NullOperatorExpression[Null predicates] (left-hand operand) | ||
| | ||
|
||
* Null predicate | ||
* Not-null predicate |
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 level is very different from the Neo4j implementation. In Neo4j we basically have that:
- List operators
List element access
andList slicing
are part of level11
- List operator
List element containment predicate
go between5
and6
- Null predicates and string predicates go between
5
and6
So level 10
does not exist, and the elements in level 10
(excluding the list element access and slicing) constructs a new level between 5
and 6
in Neo4j.
The order (simplified) would be:
- atoms
- graph element operators, list element access and slicing
- arithmetic operators
- predicates (that's why we think list predicates and null predicates should go between
5
and6
) - boolean expressions
Looking at "what others do" (which you covered further down), it seems like e.g. Python has a similar distinction as Neo4j.
A couple of examples
Null predicate and arithmetic additive operators
RETURN null + null IS NULL
Above example evaluates to true
in Neo4j. With the precedence stated in this document, it would evaluate to null
(null + (null IS NULL) -> null + true -> null
).
List element containment predicate and arithmetic additive inverse
RETURN -1 IN [1]
Above evaluates to false
in Neo4j. With the precedence stated in this document, it would fail (since it would be something like -(1 IN [1]) -> -true
, which is nonsensical).
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.
It makes sense what you describe. As far as I can tell, openCypher has simply been under defined with regards to precedence. Since this CIP refers to the grammar wrt. the levels, it seems appropriate to adjust the grammar accordingly.
ac7391c
to
b8ff397
Compare
a37c25b
to
0f75ca7
Compare
0f75ca7
to
5ddb194
Compare
fa5a4f3
to
3a72741
Compare
collect((a <boolop> b <pred> c) <> ((a <boolop> b) <pred> c)) AS neq | ||
RETURN none(x IN eq WHERE NOT x) AND any(x IN neq WHERE x) AS result |
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.
I tried running this test in Neo4j and it fails on the following examples:
| pred | boolop |
| = | XOR |
| >= | OR |
| > | AND |
| <> | XOR |
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.
I have checked all four combinations. These operator pairings are indeed associative on truth values. I have commented them out and added scenarios that test the associativity in turn, i.e. test that indeed no precedence rules apply.
UNWIND [true, false, null] AS c | ||
WITH collect((a OR b XOR c) = (a OR (b XOR c))) AS eq, | ||
collect((a OR b XOR c) <> ((a OR b) XOR c)) AS neq | ||
RETURN none(x IN eq WHERE NOT x) AND any(x IN neq WHERE x) AS result |
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.
It's a matter of taste, but I find the double negation a bit confusing. This reads better to me:
RETURN none(x IN eq WHERE NOT x) AND any(x IN neq WHERE x) AS result | |
RETURN all(x IN eq WHERE x) AND any(x IN neq WHERE x) AS result |
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.
Agreed.
Co-authored-by: Gustav Hedengran <[email protected]>
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.
Massive work!
@@ -476,4 +517,4 @@ Feature: Precedence1 - On boolean values | |||
| boolop | | |||
| OR | | |||
| XOR | | |||
| AND | | |||
| AND | |
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.
Nitpicking, but there should actually be a newline terminating the file, right?
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.
Yes! Good catch. Thanks.
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.
Fixed.
Based on PR #522
This PR aims to add
<PatternPredicate> ::= <RelationshipsPattern>
for clearer distinction of<RelationshipsPattern>
appearing as an<Atom>
CIP2015-05-13-EXISTS
to grammar refactorings, (rendered view)