Assignments with let
XQuery, like XPath and XSLT, is a declarative language. What that means in practice is a little more nebulous. One way of thinking about it is that in a declarative language, after an item is defined within a given scope (such as a program block or function), the item can't be redefined within that scope. For instance, the following code is illegal in a declarative language:
summa = 0; while (a in (1,3,6,4,7)){ summa=summa+a; } print(summa);
What causes the problem is that the variable summa changes its value within the same context. For many programmers, the idea that you can't use an accumulator like this might seem counterintuitive, but it turns out that placing one restriction on your code can significantly reduce errors when both developing and deploying code.
A declarative language can perform the same type of operation, but it works on the assumption of a generalized context. In essence, you are creating a buffer to which you're adding content, and although you can control what goes into that buffer, after the buffered content is created, you can't go in and change that bufferyou can only create other buffers from that one. That's why certain operations, such as summation, require specialized functions:
let $summa := sum((1,3,6,4,7))
The let statement in XQuery defines a function that has a constant value. This might seem like a way of saying a variable, but in fact, after the function is defined, it can't be redefined. Thus,
let $summa := sum((1,3,6,4,7)) let $summa := $summa + 6
is illegal in XQuery, because you are attempting to redefine the variable $summa.
You can use the let operator in conjunction with XPath to create a reference to a sequence. For instance, in the characters.xml file, you could create a sequence of female characters and assign it to the variable $femaleChars as follows:
let $femaleChars := document('characters.xml')//character[@gender = 'Female']
You could then retrieve the second female character by using the sequence notations discussed in Chapter 2:
let $secondFemaleChar := $femaleChars(2)