## Re: [xsl] 99 bottles of beer

 Subject: Re: [xsl] 99 bottles of beer From: "Andrew Welch" Date: Mon, 5 Feb 2007 20:36:32 +0000
On 2/5/07, Abel Braaksma <abel.online@xxxxxxxxx> wrote:
```Andrew Welch wrote:
>
> Nice! However a couple of small problems:
>
> 2 bottles of beer on the wall.
> 2 bottles of beer.
> Take one down, pass it around
> 1 bottles of beer on the wall.
>      ^^^^^^^
>
> 1 bottle of beer on the wall.
> 1 bottle of beer.
> Take one down, pass it around
> 0 bottle of beer on the wall.
>       ^^^^^^^^
>
> You just need to modify it slightly:```

```Thanks for the correction. But now we have duplicated logic (the cast +
ends-with), which some consider bad programming practice. Here's an
update that does not duplicate the logic, removes the nested for
(better: it shows a way of shortcutting nested loops with the comma
operator), corrects my error and is much less readable (which was not on
purpose, btw).```

```for \$i in reverse(1 to 99),
\$j in (1 to 3)```

```    return concat
(\$i - xs:integer(\$j mod 3 = 0),
' bottle',
('s')[not(\$i * 3 - \$j = (1 to 3))],
' of beer',```

```        (' on the wall.',
'.&#10;Take one down, pass it around',
' on the wall.&#10;' )[\$j]```

(I like the idea of using the predicate instead of if...then...else)

Genius Abel! Absolute genius...

As a tutorial it suits well for explaining why:

('s')[\$i * 3 - \$j != (1 to 3)]

yields exactly the same result as:

('s')[\$i * 3 - \$j = (1 to 3)]

```which is quite counter-intuitive (IIRC, for a '!=' to return false, none
from the left must be the same as any from the right; to be true, only
one item needs to be unequal. This is not backed up by the example
above, but I am sure I am overlooking something. Moreover, I found that
(1 to 2) != 10 returns false, and (1,2) != 10 returns true.... I am
really missing something here, this must be a faq somewhere :S  ).
```
```The difference there is that (1 to 2) != 10 returns a sequence of 2
items "true true", whereas (1,2) != 10 returns a single "true".  I
would have to look it up but I think anything other than a single
"true" converts to false, so "true true" returns false.```

```You could rewrite it as ((1 to 2) != 10) = false() to check the values
in the sequence for any occurance of false(), and return a single
true/false.```

```cheers
andrew```