Skip to content

Singleton operator #196

Open
Open
@xogeny

Description

@xogeny

When I say "singleton" operator, I'm referring to the [] without a predicate expression inside that is seen in several examples (for example, this one).

If you look at that example, the expression in question is Phone[][type="mobile"].number and the expected result is ["077 7700 1234"] if the operator is present (and "077 7700 1234" without).

One thing to note about this operator is that it is relatively independent of position. For example, the following expressions all return the same expected result:

Phone[type="mobile"][].number
Phone[type="mobile"].number[]
$[].Phone[type="mobile"].number

This is problematic because the evaluation semantics of this operator are not like any other operators. For operators such as + or & we have a binary operator node and that node has operands that the operator applies to. We really don't have that with []. Instead, the [] operator modifies certain properties of its parent node and these modifications are independent of what type of node it is.

The reason I see this as a problem can be demonstrated by the last example expression Phone[type="mobile"].number[]. Note that the [] suppresses flattening of results. But it seems very odd that it should have the same impact if it appears after number than if it appears after Phone. There are several reasons this is odd. First, is that while processing a path an array is potentially created at each step of the process. A normal user probably assumes that the placement of the array has something to do with which arrays it applies to. But it turns out that it actually applies to the result of the whole path since it marks the result of the path expression and that marking is only considered at the end of processing a path or a name).

Another reason, by the way, for seeing this as a problem has to do with my old friend the block node. 😄. I say this because (Phone[type="mobile"].number)[] means that the [] is ignored (since it isn't being applied to a path. So it needs to be clearer that it is the path that this operator is impacting and that a block is actually interfering with the precedence of the operator (it can no longer be bound to a path if we inject the block).

So a few questions.

  • It seems that we can consider this to be effectively impacting (exclusively) the evaluation of a path. Is this correct? I don't think I'm missing anything, but I just want to make sure.
  • If so, should it be a semantic error to apply [] to a non-path? Currently, it isn't. The exerciser will accept an expression like (Phone[type="mobile"].number)[] or {"one": [1]}[] without issue even though the [] is meaningless in these contexts.
  • If so, wouldn't it be better to use a syntax that makes it clear it is position independent? I don't actually care about the syntax, but it seems like using it as a unary operation on the path is the correct way to consider its evaluation. So something like []Phone[type="mobile"].number or Phone[type="mobile"].number[] (exclusively at the end) does a better job of conveying the scope of the operator. If implemented in such a way, then you could use the presence of the operator to properly mark the path/name expression as preserving singleton results.

Comments?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions