Closed glyn closed 1 year ago
@glyn can you please explain your objection to the conversions? I think they're perfectly clear. (I'm biased as I wrote it.) But you seem opposed to the idea of them rather than how they're specified.
Type conversions are a necessary mechanic for comparisons. I haven't seen a language that doesn't employ conversions in some way.
Even Javascript, a notoriously loosely typed language, has them. Consider "42" == 42
. Javascript allows you to do this, and it will return true, but under the hood it's still doing a type conversion. Whether it attempts to convert the string to a number or the number to a string, it MUST do some kind of conversion on one or both of the values before comparing the values in order for this to return true.
I'd like to explore this by expressing @.a && @.b == 42
functionally, without "conversion" language.
x == y
is replaced with equals(x, y)
, which takes two ValueType
parameters and returns LogicalType
.x && y
is replace with both(x, y)
, which takes two LogicalType
parameters and returns LogicalType
.Thus, we would write the expression functionally as
both(@.a, equals(@.b, 42))
Except we have a type mismatch because @.a
and @.b
are NodesType
, so these functions are not receiving the right types of parameters.
To fix this, we'll need LogicalType
and ValueType
from those NodesType
s, so let's introduce new functions (as @cabo suggested in https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base/issues/404#issuecomment-1440291255):
value(x)
takes a NodesType
and returns a ValueType
.logical(x)
takes a NodesType
and returns a LogicalType
.Now we can write the functional version as
both(logical(@.a), equals(value(@.b), 42))
All of the types align, and this can be executed.
Now, let's remove the first two functions to get back to the expression syntax:
logical(@.a) && value(@.b) == 42
All of the types align, and this can still be evaluated.
Now, the really interesting part is that we can infer from the context of the original expression that @.a
needs to be wrapped by logical()
and @.b
needs to be wrapped in value()
because @.a
and @.b
are not the right type for those locations in the expression.
Therefore we can say that the logical()
and value()
functions can be called implicitly, allowing us to remove the function calls from the syntax, giving us back the original expression:
@.a && @.b == 42
I (and I suspect most developers) would call logical()
and value()
"conversion functions," but if you want to specify what's going on as I've laid out above, I'm okay with that. Instead of implicit conversions, we have implicit function calls. I'd argue that conversions are more common and therefore easier to understand.
Don't call it "logical()", but call it "exists()" -- this is a very specific function that we just have decided to make the default conversion.
Don't call it "logical()", but call it "exists()" -- this is a very specific function that we just have decided to make the default conversion.
"exists" doesn't convey what's happening. Maybe "nodeExists" or "isNotEmpty" or "containsNode," but not just "exists." An empty nodelist "exists."
Secondly, while "logical" may not be appropriate for the spec, it does help to explain what's really happening.
"exists" doesn't convey what's happening.
Neither do length, count, match or search, or pretty much any other function name that I have found in a programming language. You just learn these things.
Maybe "nodeExists" or "isNotEmpty" or "containsNode," but not just "exists." An empty nodelist "exists."
I maintain that "exists" is the best way to name this function.
My point is that this is not a "conversion", but an actual processing function, that we just happen to have made implicit in the non-function grammar and therefore may have wanted to mirror on the function side.
This is in contrast to "value", which is very much a conversion, just unpacking something (and checking that this is deterministic).
Neither do length, count, match or search
I think these convey what they're doing better than exists
. But I'm not going to be fussy on naming.
My point remains that implicit conversions (or function calls if you prefer) do occur, even if we don't think they do.
I am going to wait for #404 to be addressed before progressing this issue (as the solution to #404 may affect the type conversions required).
I am going to wait for #404 to be addressed before progressing this issue (as the solution to #404 may affect the type conversions required).
Nope, you can't. I already claimed in that issue that this issue needed to be resolved first. I win 😆.
I marked this has-PR because #410, if it is the way we want to go, would resolve this issue.
It seems like we are going to need type conversions in some shape or form, even if we don't call them that. Closing.
I intend to attempt to build on the merge of #403 with an editorial change (i.e. no syntactic or semantic impact) to avoid the use of type conversion language. The aim is to make the spec clearer, but we can judge the success of that once I've made the attempt.
See https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base/pull/403#pullrequestreview-1308453021 and the following short thread for context.