tags:

views:

57

answers:

5

Hello,

I'm a little bit confused concerning variable updates in XQuery: On [1] it says:

Variables can't be updated. This means you can't write something like let $x := $x+1. This rule might seem very strange if you're expecting XQuery to behave in the same way as procedural languages such as JavaScript. But XQuery isn't that kind of language, it's a declarative language and works at a higher level. There are no rules about the order in which different expressions are executed (which means that the little yellow triangle that shows the current execution point in the Stylus Studio XQuery debugger and XSLT debugger can sometimes behave in surprising ways), and this means that constructs whose result would depend on order of execution (like variable assignment) are banned.

I'm wondering if there is really no way to reliable update a variable? Maybe I'm just to used to those things in other languages, but I can't really imagine / believe it ;-)

[1] http://www.stylusstudio.com/xquery_flwor.html, second paragraph below the screenshots of the chapter "L is for LET"

UPDATE: I have to add a question to this: Shouldn't it be possible to update an existing variable in an if statement because in this case the order of execution is clear? I guess you just aren't allowed to use something like $x = $x+1 in a loop?

A: 

No, you can't update a variable. If you can't rely on the order of execution, how would doing so make sense anyways?

Of course, even without updatable variables, you can do pretty much everything, including "loops" with incrementing variables, using a recursive function. Whether this is efficient or a good idea is another story. I once implemented sqrt() in XSLT (which also has non-updatable variables) using a recursive template...

Matti Virkkunen
Well, you are right, it really doesn't make sense in this case ;-)
stefan.at.wpf
+1  A: 

You are describing immutability, a feature of functional languages. It's true; once a variable is set to a value, it cannot be set to something else.

Immutability has many benefits. In particular, concurrent programming is made much easier.

In the case of loops, what happens is that a new variable is created each time through the loop, replacing the original one. So immutability still holds. This is explained in detail in the article you linked:

Isn't there a variable being updated when you write something like the following?

for $v in //video
let $x := xs:int($v/runtime) * xdt:dayTimeDuration("PT1M")
return concat($v/title, ": ", 
      hours-from-duration($x), " hour(s) ",
      minutes-from-duration($x), " minutes")

(This query shows the running time of each video. It first converts the stored value from a string to an integer, then multiplies it by one minute (PT1M) to get the running time as a duration, so that it can extract the hours and minutes components of the duration. Try it.)

Here the variable $x has a different value each time around the XQuery for loop. This feels a bit like an update. Technically though, each time round the for loop you're creating a new variable with a new value, rather than assigning a new value to the old variable.

Robert Harvey
Thanks, guess I didn't realize that this is just not a procedural language but a funcitonal one.
stefan.at.wpf
I added a further question above, maybe someone has a hint on that? :-)
stefan.at.wpf
@stefan: See my edit.
Robert Harvey
A: 

While variables can't be updated, you can define a second variable with the same name, in which case any references to that variable with the scope of its binding will bind to the later variable with the smaller scope.

So

let $x := $x + +1
return $x

means

let $x_2 := $x_1 +1
return $x_2
Nick Jones
A: 

Believe it.

XQuery is like a functional programming language in this regard. You don't want to change the value of already calculated computation from a functional/mathematical perspective. Also, data is immutable and cannot change state so the language can be used to build high concurrency applications. Erlang is a "good" example of a language built for high concurrency. Immutability is also used in some imperative languages such as Java for high concurrency.

Just like in any other functional language you can always ensure you "eval" your "expr" and then make the required changes with a copy.

Note that I am not saying XQuery is a good functional programming language. Have a look at erlang for an example of a good functional language and implementation that provides good performance.

abdollar
A: 

Actually, updating a variable is possible if your XQuery processor supports the XQuery Scripting Extension 1.0

E.g., the following example works with Zorba:

declare sequential function local:fib(){
  declare $a as xs:integer := 0;
  declare $b as xs:integer := 1;  
  declare $c as xs:integer := $a + $b;
  declare $fibseq as xs:integer* := ($a, $b);
  while ($c < 100) { 
     set $fibseq := ($fibseq, $c);
     set $a := $b;
     set $b := $c;
     set $c := $a + $b;
  };
  $fibseq;
};

local:fib()

A sequential function can do updates. The apply statement (each peace of code ending with ;) applies all updates immediately.

If you just want to have a counting variable in a FLWOR you can use the at keyword:

for $item at $x in ("a","b","c")
return $x

returns:

<?xml version="1.0" encoding="UTF-8"?>
1 2 3
Dennis Knochenwefel