Closed goessner closed 1 year ago
In Type System for Function Expressions
(L-1473)
{{tbl-types}} defines the available types in terms of abstract instances, where
n
denotes a node,v
denotes a value, andnl
denotes a nodelist.
That 'n
' for node seems to be used nowhere else.
Example (L-1552)
$[?length(@.authors) >= 5]
What, if function length
returns Nothing
? Is Nothing >= 5
, is it a comparable?
Example (L-1581)
$[?count(@.*.author) >= 5]
What is the return type, if the NodesType
argument is Nothing
?
Nit (L-1650)
The "value" function extension provides a way to convert a instance of
NodesType
...
... 'an instance' ...
Consider
$[?value(@..angle) > 3.14]
What is the result, if the return value of value
is Nothing
?
Shouldn't I always guard this by
$[?count(@..angle) == 1 && value(@..angle) > 0]
I think, I always would.
If I, as a non-implementer of JSONPath, would like to register a function, say ...
nl
taking a NodesType
as single argument and returning an array of normalized pathes or Nothing
... I would need to know the implementation specific shape of NodesType
and Nothing
.
As a consequence of this only implementers can register (or implement already registered) functions, as long as they didn't document internal aspects of NodesType
and Nothing
.
If we do not want such a scenario, how could we achieve an implementation-independent interface (types) for functions?
In
Type System for Function Expressions
(L-1473){{tbl-types}} defines the available types in terms of abstract instances, where
n
denotes a node,v
denotes a value, andnl
denotes a nodelist.That '
n
' for node seems to be used nowhere else.
Yep, this is a remnant. Fixed in e6dc704
Example (L-1552)
$[?length(@.authors) >= 5]
What, if function
length
returnsNothing
? IsNothing >= 5
, is it a comparable?
length
Is declared as a ValueType, so it is well-typed as a comparable
.
Section Comparisons
says:
The comparison operators == and < are defined first and then these are used to define !=, <=, >, and >=.[¶](http://127.0.0.1:7999/#section-2.5.5.2.2-1)
Then it goes on to say:
When either side of a comparison results in an empty nodelist or Nothing:
a comparison using the operator == yields true if and only the other side also results in an empty nodelist or Nothing.
a comparison using the operator < yields false.
So ==
is false (5 is not Nothing), and <
also is false.
Finally, it says:
The comparison a >= b yields true if and only if b < a yields true or a == b yields true.[¶](http://127.0.0.1:7999/#section-2.5.5.2.2-8.4)
Since neither is the case, the answer is that the comparison is false.
Example (L-1581)
$[?count(@.*.author) >= 5]
What is the return type, if the
NodesType
argument isNothing
?
NodesType does not have Nothing as a special value; this would be an empty nodelist. Count
gives the number of nodes in the nodelist.
so it returns 0 on this case, as there is no (0) node in the nodelist.
Nit (L-1650)
The "value" function extension provides a way to convert a instance of
NodesType
...... 'an instance' ...
Fixed in ff5f2a3
Consider
$[?value(@..angle) > 3.14]
What is the result, if the return value of
value
isNothing
?
When either side of a comparison results in an empty nodelist or Nothing:
[...]
a comparison using the operator < yields false.
Shouldn't I always guard this by
$[?count(@..angle) == 1 && value(@..angle) > 0]
I think, I always would.
That is a matter of style, and I don't disagree with being explicit. value() still has to have a defined value as we don't have short-circuiting in JSONPath.
If I, as a non-implementer of JSONPath, would like to register a function, say ...
nl
taking aNodesType
as single argument and returning an array of normalized pathes orNothing
... I would need to know the implementation specific shape of
NodesType
andNothing
.
You can register it right away, but then you need to get the new function extension into implementations.
JSONPath does not provide a way to define your own functions, so indeed, you'll have to wait for implementers.
An expression language that allows to define functions in-language would be an interesting project, but probably going beyond what we can do here.
As a consequence of this only implementers can register (or implement already registered) functions,
No/Yes, see above.
as long as they didn't document internal aspects of
NodesType
andNothing
.
This type and this value are well-defined, so describing them in a registration should pose no problems.
If we do not want such a scenario, how could we achieve an implementation-independent interface (types) for functions?
I'm having a hard time imagining such an interface. It would need to be different for different platforms, and for different strategies for implementing JSONPath on such a platform. So it would, for all intents and purposes, be implementation dependent. Unless/Until we define the abovementioned powerful expression language.
nl
taking aNodesType
as single argument and returning an array of normalized pathes orNothing
Oh, and remember that we are still in the filter selector expression mechanism, so it is not clear that such a function extension would be particularly useful. Adding Projection/Transformations to JSONPath is another interesting project that goes beyond base.
@cabo : thanks for clarification of all ...
I believe the required changes were covered by https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base/pull/420. Please re-open if this is not the case.
JSONPath does not provide a way to define your own functions, so indeed, you'll have to wait for implementers.
JSON Path may not provide this, but the more user-friendly implementations likely will (mine does). So you can register your function, then go on to implement the function and plug it in.
Indeed, it should not be too hard to do this for any single implementation (my PoC implementation currently doesn't, because I didn't need to prove that particular concept :-), but it will). Defining a way to do this across implementations, in a "standard" way, is much harder.
Defining a way to do this across implementations, in a "standard" way, is much harder.
I don't think we need to define it. We can just state something like,
Implementations SHOULD provide a mechanism for the user to provide their own algorithms for function extensison
or some such. The wording isn't great.
We would need to be careful to not open the door for arbitrary custom functions (although implementations can still do that if they want; it just wouldn't be spec-sanctioned).
These questions/hurdles/nits came up while reading PR #420 and related issues/PR's carefully.