Skip to content
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

Sequence Decomposition #1144

Closed
rhdunn opened this issue Apr 12, 2024 · 6 comments
Closed

Sequence Decomposition #1144

rhdunn opened this issue Apr 12, 2024 · 6 comments
Labels
Enhancement A change or improvement to an existing feature XPath An issue related to XPath

Comments

@rhdunn
Copy link
Contributor

rhdunn commented Apr 12, 2024

This proposal allows sequences to be decomposed and assigned to separate variables in a single declaration within a for or let expression binding.

Given a sequence such as (1, 2, 3), the values within that sequence cannot easily be extracted. With the current version of XPath and XQuery, they need to be assigned to a temporary variable first. For example:

let $result := get-camera-point()
let $x := $result[1]
let $y := $result[2]
let $z := $result[3]
return "(" || $x || "," || $y || "," || $z || ")"

This proposal would allow this to be written more concisely as:

let ($x, $y, $z) := get-camera-point()
return "(" || $x || "," || $y || "," || $z || ")"

These are equivalent in this proposal, except that $result is not a statically known variable binding in the sequence decomposition let clause.

Note: The older syntax in XPath-NG was:

let $(x, y, z) := get-camera-point()
return "(" || $x || "," || $y || "," || $z || ")"

For each variable declaration in the sequence decomposition at index N, and $expr being the result of the for/let expression, then $expr[N] is the value bound to the variable declaration as a new variable binding. If the value does not exist, an empty sequence is bound to the variable.

A sequence decomposition can be used in any for or let clause binding to decompose the items in a sequence. If the type of the for or let clause binding expression is not a sequence, an err:XPTY0004 error is raised.

Assigning the rest of a sequence

It can be useful to only extract part of a sequence or array (e.g. the heading of a table), and store the rest of the items in another variable. For example:

let $(heading, rows ...) := fn:parse-csv("test.csv")

If there are no items remaining in the sequence the result is an empty sequence.

Influences

Tuple decomposition is found in various languages such as Python, Scala, and C#. These languages also have support for tuple types.

Python has support for specifying that a variable is assigned the remaining values in the tuple.

Use Cases

There are many cases where fixed size sequences may be used such as points, complex and rational numbers, sin/cos, and mul/div. This makes extracting data from these simpler, and may also be used to aid readability by assigning descriptive names to each of the items in the sequence.

Examples

Extracting values from a sequence:

declare function sincos($angle as xs:double?) {
    math:sin($angle), math:cos($angle)
};

let $angle := math:pi()
let ($sin, $cos) := sincos($angle)
return $sin || "," || $cos
@rhdunn rhdunn added XPath An issue related to XPath Enhancement A change or improvement to an existing feature labels Apr 12, 2024
@ChristianGruen
Copy link
Contributor

I like this proposal a lot. Isn’t it similar to the existing #37?

@rhdunn
Copy link
Contributor Author

rhdunn commented Apr 12, 2024

Ah yes, I was trying to look for that. Should I close these and update that discussion then?

@ChristianGruen
Copy link
Contributor

Ah yes, I was trying to look for that. Should I close these and update that discussion then?

As you like (in #31 (comment), I referenced your issue, but without adding further notes).

@rhdunn
Copy link
Contributor Author

rhdunn commented Apr 12, 2024

Duplicate of #37.

@rhdunn rhdunn closed this as completed Apr 12, 2024
@michaelhkay
Copy link
Contributor

My only reservation on this is that it endorses the idea of using a sequence as a tuple, which I'm not sure is something we want to encourage. In our own functions we always use maps/records for this kind of data structure, and personally I would encourage users to do the same.

@ChristianGruen
Copy link
Contributor

My only reservation on this is that it endorses the idea of using a sequence as a tuple, which I'm not sure is something we want to encourage.

I think it’s very helpful for head/tail operations. It’s easier to write…

let ($head, $tail) := $sequence

.…than to build a structure in advance that wraps the head and tail into a record.

From the pedagogical point of view, I would let users decide: If decomposition will be used more often than records in practice, it rather tells us that the syntax of the latter should be improved/simplified in XPath 4.1/5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement A change or improvement to an existing feature XPath An issue related to XPath
Projects
None yet
Development

No branches or pull requests

3 participants