Xquery result duplicated - xquery

I'm not getting the output I want. I don't understand why the result is duplicated. Can someone help me?
for $i in 1 to 2
let $rng:=random-number-generator()
let $rng1:=$rng('permute')(1 to 10)
let $rng:=$rng('next')()
let $rng2:=$rng('permute')(1 to 10)
let $rng:=$rng('next')()
let $rng3:=$rng('permute')(1 to 10)
return (string-join($rng1),string-join($rng2),string-join($rng3),",")
result:
23496815107
31018674529
31017684259
23496815107
31018674529
31017684259

The result is duplicated because of the initial for $i in 1 to 2, and because the variable $i is not actually used anywhere.
I edited the query based on your comment (getting 10 numbers). From what I understand, the difficulty here is to chain the calls (alternating between 'next' and 'permute'). Chaining calls can be done with a tail recursion.
declare function local:multiple-calls(
$rng as function(*),
$number-of-times as xs:integer) as item()* {
if($number-of-times le 0)
then ()
else
let $rng := $rng('next')
return ($rng('permute')(1 to 10),
local:multiple-calls($rng, $number-of-times - 1))
};
local:multiple-calls(random-number-generator(), 10)
Note: I am not sure if (1 to 10) is what needs to actually be passed to the call to $rng('permute'), or if it was an attempt to output ten numbers. In doubt, I haven't changed it.

The specification is here:
http://www.w3.org/TR/xpath-functions-31/#func-random-number-generator
It says:
Both forms of the function are ·deterministic·: calling the function
twice with the same arguments, within a single ·execution scope·,
produces the same results.
If you supply $i as the $seed argument to random-number-generator then the two sequences should be different.

I think I now understand what confuses you in this original query. One could indeed expect the random numbers to be generated differently for each iteration of $i.
However, XQuery is (to put it simply, with a few exceptions) deterministic. This means that the random generator probably gets initialized in each iteration with the same, default seed.
Thus, I have a second potential answer:
If you have a way to pass a different seed to $rng, you could slightly modify your initial query by constructing a seed based on $i and maybe current-dateTime() in each iteration before generating the numbers. But it will still be the same if you execute the query several times unless you involve the current date/time.

Related

Tail Recursions in erlang

I'm learning Erlang from the very basic and have a problem with a tail recursive function. I want my function to receive a list and return a new list where element = element + 1. For example, if I send [1,2,3,4,5] as an argument, it must return [2,3,4,5,6]. The problem is that when I send that exact arguments, it returns [[[[[[]|2]|3]|4]|5]|6].
My code is this:
-module(test).
-export([test/0]).
test()->
List = [1,2,3,4,5],
sum_list_2(List).
sum_list_2(List)->
sum_list_2(List,[]).
sum_list_2([Head|Tail], Result)->
sum_list_2(Tail,[Result|Head +1]);
sum_list_2([], Result)->
Result.
However, if I change my function to this:
sum_list_2([Head|Tail], Result)->
sum_list_2(Tail,[Head +1|Result]);
sum_list_2([], Result)->
Result.
It outputs [6,5,4,3,2] which is OK. Why the function doesn't work the other way around([Result|Head+1] outputing [2,3,4,5,6])?
PS: I know this particular problem is solved with list comprehensions, but I want to do it with recursion.
For this kind of manipulation you should use list comprehension:
1> L = [1,2,3,4,5,6].
[1,2,3,4,5,6]
2> [X+1 || X <- L].
[2,3,4,5,6,7]
it is the fastest and most idiomatic way to do it.
A remark on your fist version: [Result|Head +1] builds an improper list. the construction is always [Head|Tail] where Tail is a list. You could use Result ++ [Head+1] but this would perform a copy of the Result list at each recursive call.
You can also look at the code of lists:map/2 which is not tail recursive, but it seems that actual optimization of the compiler work well in this case:
inc([H|T]) -> [H+1|inc(T)];
inc([]) -> [].
[edit]
The internal and hidden representation of a list looks like a chained list. Each element contains a term and a reference to the tail. So adding an element on top of the head does not need to modify the existing list, but adding something at the end needs to mutate the last element (the reference to the empty list is replaced by a reference to the new sublist). As variables are not mutable, it needs to make a modified copy of the last element which in turn needs to mutate the previous element of the list and so on. As far as I know, the optimizations of the compiler do not make the decision to mutate variable (deduction from the the documentation).
The function that produces the result in reverse order is a natural consequence of you adding the newly incremented element to the front of the Result list. This isn't uncommon, and the recommended "fix" is to simply list:reverse/1 the output before returning it.
Whilst in this case you could simply use the ++ operator instead of the [H|T] "cons" operator to join your results the other way around, giving you the desired output in the correct order:
sum_list_2([Head|Tail], Result)->
sum_list_2(Tail, Result ++ [Head + 1]);
doing so isn't recommended because the ++ operator always copies it's (increasingly large) left hand operand, causing the algorithm to operate in O(n^2) time instead of the [Head + 1 | Tail] version's O(n) time.

Execute function in FLWOR without using 'let'

Let's say I create a map:
let $map := map:map()
How can I put something in that map without using let? Usually I have to do something like
let $map := map:map()
let $useless-var := map:put($map, $key, $value)
Seems strange that if I want to execute something and I don't care about the return value, I still have to store the result. What am I missing here?
Note: The important part is not map(), but the fact that I can't run a function without storing the result in some pointless variable.
One approach is to execute the functions as items in a sequence where only one item (typically, the first or last) in the sequence supplies the real value for an assignment or return, as in:
let $roundedX := (
math:floor($x),
local:function1(...),
local:function2(...)[false()],
...
)
...
return (
local:functionA(...),
local:functionB(...)[false()],
...,
$roundedX * 10
)
If the function returns a value that you want to throw away, just use a false predicate, as with two of the functions above.
Of course, this approach is only useful for functions with side effects.
Don't use a FLWOR unless you need it. In my opinion FLWOR expressions are somewhat overused. I often see expressions like:
let $a := current-time()
return $a
...when it would work just as well to write:
current-time()
See also: http://blakeley.com/blogofile/2012/03/19/let-free-style-and-streaming/
In MarkLogic 7 you can use the map constructor to generate maps recursively. I think this is probably what you want:
let $map := map:new(
(1 to 10) ! map:entry(., .)
)
Or you execute map:put as part of another sequence, or in the return statement before you return the map:
let $map := map:map()
let $not-useless-var := ...
return (map:put($map, string($not-useless-var), $not-useless-var), $map)
In plain XQuery (ignoring extensions like the XQuery scripting extension) there are no side-effects, so calling a function without using its return value is meaningless.
What you may be missing here is that map:put() returns a new map with an extra item added, it does not mutate the original map. So your $useless-var is not actually useless.
EDIT: Actually I'm not sure if MarkLogic's map:put() mutates the map. (If it does, that is really gross.) I was thinking of the proposed XQuery 3.1 maps (which I've used in BaseX) which definitely are immutable.
Since the focus of your question is about running a function without storing intermediate results, you might find the map operator (!) helpful:
local:build-sequence() ! local:do-something-to-each(.)
That's good for processing sequences. If you're thinking more about processing the result of something, the answer is likely in embracing the functional nature of XQuery:
local:produce-result(
local:build-parameter(),
local:retrieve-config()
)
Not sure exactly what you're looking for, but hopefully those help.

Returning multiple values in Ruby, to be used to call a function

Is it possible to return multiple values from a function?
I want to pass the return values into another function, and I wonder if I can avoid having to explode the array into multiple values
My problem?
I am upgrading Capybara for my project, and I realized, thanks to CSS 'contains' selector & upgrade of Capybara, that the statement below will no longer work
has_selector?(:css, "#rightCol:contains(\"#{page_name}\")")
I want to get it working with minimum effort (there are a lot of such cases), So I came up with the idea of using Nokogiri to convert the css to xpath. I wanted to write it so that the above function can become
has_selector? xpath(:css, "#rightCol:contains(\"#{page_name}\")")
But since xpath has to return an array, I need to actually write this
has_selector?(*xpath(:css, "#rightCol:contains(\"#{page_name}\")"))
Is there a way to get the former behavior?
It can be assumed that right now xpath func is like the below, for brevity.
def xpath(*a)
[1, 2]
end
You cannot let a method return multiple values. In order to do what you want, you have to change has_selector?, maybe something like this:
alias old_has_selector? :has_selector?
def has_selector? arg
case arg
when Array then old_has_selector?(*arg)
else old_has_selector?(arg)
end
end
Ruby has limited support for returning multiple values from a function. In particular a returned Array will get "destructured" when assigning to multiple variables:
def foo
[1, 2]
end
a, b = foo
a #=> 1
b #=> 2
However in your case you need the splat (*) to make it clear you're not just passing the array as the first argument.
If you want a cleaner syntax, why not just write your own wrapper:
def has_xpath?(xp)
has_selector?(*xpath(:css, xp))
end

Simple function in lua: pick a random parameter passed into it

i would love to have functionality like this:
print(randomParameter(1,2,3))
-- prints 1 2 or 3... randomly picks a parameter
i have tried using the func(...) argument but i cant seem to use the table ARG when i pass multiple parameters. I tried this:
function hsv(...)
return arg[math.random(1,#arg)] -- also tried: return arg[math.random(#arg)]
end
print(hsv(5,32,7))
i have even tried putting the #arg into a variable using the rand function, also making a for loop with it sequentially adding a variable to count the table. still nothing works.
i remember doing this a while back, amd it looked different then this. can anyone Help with this? THANKS!
To elaborate a bit on #EgorSkriptunoff's answer (who needs to change his habit of providing answers in comments ;)): return (select(math.random(select('#',...)),...)).
... provides access to vararg parameter in the function
select('#', ...) returns the number of parameters passed in that vararg
math.random(select('#',...)) gives you a random number between 1 and the number of passed parameters
select(math.random(select('#',...)),...) gives you the element with the index specified by that random number from the passed parameters.
The other solution that is using arg = {...} gives you almost the same result with one subtle difference related to the number of arguments when nil is included as one of the parameters:
> function f(...) print(#{...}, select('#', ...)) end
> f(1,2,3)
3 3
> f(1,2,nil)
2 3
> f(1,2,nil,3)
2 4
As you can see select('#',...) produces more accurate results (this is running LuaJIT, but as far as I remember, Lua 5.1 produces similar results).
function randomNumber(...)
t = {...}
return t[math.random(1,#t)]
end
print(randomNumber(1, 5, 2, 9))
> 1 or 5 or 2 or 9

Get nth element of a collection in Cypher

Using Cypher 1.8, there are some functions working on collections and returning a single element:
HEAD( expression ):
START a=node(2)
RETURN a.array, head(a.array)
LAST( expression ):
START a=node(2)
RETURN a.array, last(a.array)
However, I could not find a function to return the nth element of a collection. What am I missing?
There's no good way to do that at the moment. Please submit a feature request at https://github.com/neo4j/neo4j
I've seen people do head(tail(tail(tail(coll)))), and while it's probably acceptably fast, it still makes me a little ill to see in a query, especially if you're talking about the 17th element or worse.
Example:
http://console.neo4j.org/r/bbo6o4
Update:
Here's a way to do it using reduce and range. It makes it so you can give a parameter for nth at least, even though it still makes me cringe:
start n=node(*)
with collect(n) as allnodes
return head(reduce(acc=allnodes, x in range(1,3): tail(acc)));
http://console.neo4j.org/r/8erfup
Update 2 (8/31/2013):
The new collection syntax is now merged into 2.0 and will be theoretically be a part of M05! So, you'll be able to do:
start n=node(*)
with collect(n) as allnodes
return allnodes[3]; // or slices, like [1..3]
I'll add a link to the snapshot documentation when it gets updated.
I've just come across this old question, and for the benefit of anyone else recently coming across it... it seems the list support has improved.
From the Cypher 4 list docs:
Cypher has comprehensive support for lists.
^ Sidenote: I think that's list comprehensions pun? ;-)
They go on to give an example showing how you'd access the n'th element of a list:
To access individual elements in the list, we use the square brackets again. This will extract from the start index and up to but not including the end index.
... we’ll use the range function. It gives you a list containing all numbers between given start and end numbers. Range is inclusive in both ends.
RETURN range(0, 10)[3]
^ returns "3"
Currently, with the release of APOC Procedures 3.3.0.2 you can use aggregation functions.
This way, you can do thinks like:
create (:Node {node_id : 1}),
(:Node {node_id : 2}),
(:Node {node_id : 3});
match(n:Node)
with n order by n.node_id
// returns {"node_id":2}
return apoc.agg.nth(n, 1);
or:
match(n:Node)
with n order by n.node_id
// returns {"node_id":1}
// you can also use apoc.agg.last
return apoc.agg.first(n);
To work with lists UNWIND the list first:
with ['fist', 'second', 'third'] as list
unwind list as value
// returns 'second'
return apoc.agg.nth(value, 1);

Resources