XQuery. Error: unknown function - function

I have an assignment:
Define the co-author graph G of the dblp-excerpt to be the undirected graph that has all authors as nodes, such that there is an edge between author a and author b in G if and only if a and b have written a publication together.
Define the distance between two authors a and b to be the length of the shortest path between a and b in G. Hence, authors that have published together have distance 1.
Moreover, if a and b have not published together but they have both published together with c, then the distance between a and b is two. Write an XQuery program that computes, for each pair of authors x and y 6= x the distance
between x and y using the following output format.
I wrote a code, but it doesn't work. I'm sure, it is very simple mistake, but I can't find it.
I have an error: Error:
Stopped at C:/Users/Zhanna/Desktop/Test/test_3.xq, 28/44: [XPST0017]
Unknown function 'local:getAvailablePathSizes'.
It underlines the beginning of the list of arguments in line 28, which is:
return
local:getAvailablePathSizes($graph,$current,$target,$visitedList,$count+1)
I validate the query with the Saxon as well and it also give a msg like this:
Error XPST0008: Unresolved reference to variable $count Static
error(s) in query
Help me, please, to fix it.
<ee>
let $graph:=(
<graph>{
for $a in distinct-values(//author)
let $publications:=/dblp/*[author=$a]
order by $a
return
<node name="{$a}">
{
let $co:=$publications/author[(.)!=$a] return
for $distinctCo in distinct-values($co) return
<edge from="{$a}" to="{$distinctCo}"/>
}
</node>
}</graph>
) return
declare function local:getAvailablePathSizes
($graph, $start, $target, $visitedList, $count)
{
let $cos:=$graph/node[#name=$start]/edge/#to return
let $listOfDistances:=(
for $current in $cos
return
if($current=$target) then $count+1 else
if (empty(visitedList[.=$current])) then(
let $visitedList:=insert-before(data($current), 0, $visitedList)
return local:getAvailablePathSizes($graph,$current,$target,$visitedList,$count+1)
) else()
)
return $listOfDistances
};
<distances>
{
for $node in $graph/node return
for $to in $graph/node[#name!=$node/#name]
let $dist:=min(local:getAvailablePathSizes($graph, $node/#name, $to/#name, null, 0))
return
if($dist>0) then(
<distance
author1="{$node/#name}"
author2="{$to/#name}"
distance="{$dist}"/>)
else()
}
</distances>
</ee>
This is the XML file
http://www.filedropper.com/dblp

The first problem is, that you did omit curly braces around the XQuery code inside the <ee> element, so large parts of your code haven't been evaluated (but interpreted as text instead). This resulted in a barely helpful error message indicating the second problem: you must define functions in the so-called prolog before the "normal" XQuery statements (in the query body).
declare function local:getAvailablePathSizes
($graph, $start, $target, $visitedList, $count)
{
let $cos:=$graph/node[#name=$start]/edge/#to return
let $listOfDistances:=(
for $current in $cos
return
if($current=$target) then $count+1 else
if (empty(visitedList[.=$current])) then(
let $visitedList:=insert-before(data($current), 0, $visitedList)
return local:getAvailablePathSizes($graph,$current,$target,$visitedList,$count+1)
) else()
)
return $listOfDistances
};
<ee>{
let $graph:=(
<graph>{
for $a in distinct-values(//author)
let $publications:=/dblp/*[author=$a]
order by $a
return
<node name="{$a}">
{
let $co:=$publications/author[(.)!=$a] return
for $distinctCo in distinct-values($co) return
<edge from="{$a}" to="{$distinctCo}"/>
}
</node>
}</graph>
) return
<distances>
{
for $node in $graph/node return
for $to in $graph/node[#name!=$node/#name]
let $dist:=min(local:getAvailablePathSizes($graph, $node/#name, $to/#name, null, 0))
return
if($dist>0) then(
<distance
author1="{$node/#name}"
author2="{$to/#name}"
distance="{$dist}"/>)
else()
}
</distances>
}
</ee>

Related

While Iterator in groovy

I'm trying to create a loop to read, for example, 4200 users from 1000 to 1000 but I can't get it to cut when it reaches the end. I tried it with if, for and I couldn't do it.
I have programmed in JAVA but with Groovy I see that the structure is different.
urlUsers = urlUsers.concat("/1/1000");
List<UserConnectorObject> usersList = null;
while({
gesdenResponse = GesdenUtils.sendHttpRequest(urlUsers, "LOOKUP", null,
request.getMetaData()?.getLogin(), request.getMetaData()?.getPassword());
log.info("Users data in JSON: "+gesdenResponse.getOutput())
usersList = GesdenUtils.fromJSON(gesdenResponse.getOutput(), GesdenConstants.USER_IDENTITY_KEY);
usersList.size() == 10;
log.info("List size in JSON "+usersList.size());
}()) continue
Groovy has lots of loop structures, but it is crucial to separate the regular ones (lang built-ins) and the api functions which take closure as an argument
take closure - no plain way to escape
If you want to iterate from A to B users, you can use, for instance,
(10..20).each { userNo -> // Here you will have all 10 iterations
if ( userNo == 5) {
return
}
}
If something outrageous happens in the loop body and you cannot use return to escape, as loop boddy is a closure (separate function) and this resurn just exits this closure. Next iteration will happen just after.
use regular lang built-in loop structures - make use of break/continue
for (int userNo in 1..10) { // Here you will have only 5 iterations
if (userNo == 5) {
break
}
}
It looks like your closure always return falsy because there is no explicit return, and the last statement evaluated is the call to log.info(String) which returns void.
Use an explicit return or move/delete the log statement.

How to check if a function parameter is a string or array in Perl

I'm trying to write a custom validateParameter function with Perl.
I have the following code which also works:
sub validateParameter {
my ($args, $list) = #_;
if ( ref($list) eq "ARRAY" ) {
foreach my $key (#$list) {
if ( not defined $args->{$key} ) {
die "no $key given!";
}
}
}
#elsif ( check if string ) {
#}
}
I want to call my function the following way:
validateParameter({ hallo => "Welt", test => "Blup"}, ["hallo", "test"]);
But I also want to call my function like this:
validateParameter({ hallo => "Welt", test => "Blup"}, "hallo");
I know that Perl only has the following three data-types (scalars, hashes, arrays). But maybe there is a smart way to check if a variable is a string.
How can I check if the given arg is a string?
Update: I somehow missed the end of the question. Just testing ref($list) eq 'ARRAY' will work most of the time, but to properly allow even overloaded objects, you should just try dereferencing the parameter:
if ( eval { \#$list } ) {
# it was an array
}
else {
# assume it is a string
}
Original answer:
You can check a number of things about a parameter:
if ( ! defined $param ) {
# undefined
}
elsif ( defined Scalar::Util::blessed($param) ) {
# object
}
elsif ( ref $param ) {
# reference (return of ref will give the type)
}
elsif ( length do { no warnings "numeric"; $param & '' } ) {
# number
}
else {
# string
}
But all of that (except perhaps the defined check) kind of defeats the purpose of Perl's automatically converting to your desired type and will limit what can be passed (for instance, a string or dualvar where a number is wanted, or an overloaded object where a string, number, or reference is wanted, or tied variables or magic variables such as $!).
You may want to also just look at what Params::Validate can do.
Don't base behaviour on the "type" of arguments because there really isn't such a thing. You will run into problems if you use type-base polymorphism because Perl values often have more than one type.
For example,
The scalar produced by "123" is stored as as string, but Perl doesn't distinguish it from the scalar produced by 123 which isn't stored as a string.
Scalars can contain both a number and a cached stringification of that number. (e.g. my $i = 123; "".$i;)
Scalars can contain both a number and a string (that isn't a stringification of the number). Common examples of these are $! and !1.
A reference to an object that overloads stringification is also a useful string. (e.g. DateTime->now)
A reference to an array may overload %{} to usable as a hash reference. A reference to an hash may overload #{} to usable as an array reference.
And more.
No, there is no way to check if a scalar is a string, as Perl does implicit type conversions depending on context. If you give a number as the second argument to your function, and you use it in a context that requires a string, it will be automatically converted to a string. So, just check if ref($list) is empty - in such case, $list is not a reference, and therefore it is a string or a number, and you don't need to distinguish between those two.

'Not an ARRAY reference' error thrown

I'm writing a Perl script that is meant to deal with an API which returns metrics about a set of URLs that I pull from MySQL then post these metrics back into a different table. Currently this piece of code:
my $content = $response->content;
my $jsontext = json_to_perl($content);
my $adsql = 'INSERT INTO moz (url_id,page_authority,domain_authority,links,MozRank_URL,MozRank_Subdomain,external_equity_links) VALUES (?,?,?,?,?,?,?)';
my $adrs = $db->prepare( $adsql );
my $adsql2 = 'UPDATE url
SET moz_crawl_date = NOW()
where url_id = ?;';
my $adrs2 = $db->prepare( $adsql2 );
my $currentUrlId = 0;
foreach my $row (#$jsontext){
$adrs->execute($url_ids[$currentUrlId], $row->{'fmrp'}, $row->{'upa'}, $row->{'pda'}, $row->{'uid'}, $row->{'umrp'}, $row->{'ueid'});# || &die_clean("Couldn't execute\n$adsql\n".$db->errstr."\n" );
$adrs2->execute($url_ids[$currentUrlId]);
$currentUrlId++;
}
is throwing this error:
Not an ARRAY reference at ./moz2.pl line 124.
this is line 124:
foreach my $row (#$jsontext){
this whole chunk of code is in a while loop. I am actually able to iterate a couple times and fill my MySQL table before the script fails (technically the program works, but I don't want to just leave an error in it).
Anybody have any suggestions?
Perl gave you the correct answer
Not an ARRAY reference: #$jsontext
You are dereferencing $jsontext, which is the result of json_to_perl(string), to an array.
But json_to_perl() didn't return an arrayref.
json_to_perl seems to be from this API: http://search.cpan.org/~bkb/JSON-Parse-0.31/lib/JSON/Parse.pod#json_to_perl
which returns according to the doc either an arrayref or a hashref.
Apparently it did return a hashref in your case, so you have to add the logic to deal with the HASH case. Which seems to be a single row.
if (ref $jsontext eq 'HASH') {
# seems to be a single row
$adrs->execute($url_ids[$currentUrlId], $jsontext->{'fmrp'}, $jsontext->'upa'}, $jsontext->'pda'}, $jsontext->'uid'}, $jsontext->'umrp'}, $jsontext->'ueid'});# || &die_clean("Couldn't execute\n$adsql\n".$db->errstr."\n" );
$adrs2->execute($url_ids[$currentUrlId]);
$currentUrlId++;
} elsif (ref $jsontext eq 'ARRAY') {
foreach my $row (#$jsontext){
$adrs->execute($url_ids[$currentUrlId], $row->{'fmrp'}, $row->{'upa'}, $row->{'pda'}, $row->{'uid'}, $row->{'umrp'}, $row->{'ueid'});# || &die_clean("Couldn't execute\n$adsql\n".$db->errstr."\n" );
$adrs2->execute($url_ids[$currentUrlId]);
$currentUrlId++;
}
}

NSManagedObject nil value

I save data with CoreData. I have an Array and the last occurrence is 'nil' value. I do not want to save the 'nil' value in CoreData. I try to check the 'nil' value but I can not achieve. My code:
for (NSManagedObject *category in array)
{
//if (![category isEqual:nil]) { <- FAILED ATTEMPT
//if (![category isFault]) { <- FAILED ATTEMPT
//if (category != NULL) { <- FAILED ATTEMPT
[ more Objective-C code ...]
// Insert Objects in the Core Data
theLine = [NSEntityDescription insertNewObjectForEntityForName:entName
inManagedObjectContext:context];
//}
}
I can not understand why is so hard to check a NSManagedObject 'nil value'.
In my code, 'category' is a NSManagedObject. I want to know when it has 'nil' value:
(NSManagedObject) isEqual
(NSManagedObject) isFault
(NSManagedObject) = NULL
Any of these options does not run. Can anyone help me?
Thanks a lot in advance.
I think if you just use if(category) or if(category == nil) they should check if it is equal to nil.
Failing this you could do a for loop like:
for (int cycle =0 ; cycle < [array count]; cycle++){
if ([[array objectAtIndex:cycle]isKindOfClass[NSNull class]]){
////Do some code here
}
}
This will check is the value of the object is not Null because your loop will only look at NSManagedObjects

Why is my Scala function returning type Unit and not whatever is the last line?

I am trying to figure out the issue, and tried different styles that I have read on Scala, but none of them work. My code is:
....
val str = "(and x y)";
def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int )
var b = pos; //position of where in the expression String I am currently in
val temp = expreshHolder; //holder of expressions without parens
var arrayCounter = follow; //just counts to make sure an empty spot in the array is there to put in the strings
if(exp(b) == '(') {
b = b + 1;
while(exp(b) == ' '){b = b + 1} //point of this is to just skip any spaces between paren and start of expression type
if(exp(b) == 'a') {
temp(arrayCounter) = exp(b).toString;
b = b+1;
temp(arrayCounter)+exp(b).toString; b = b+1;
temp(arrayCounter) + exp(b).toString; arrayCounter+=1}
temp;
}
}
val hold: ArrayBuffer[String] = stringParse(str, 0, new ArrayBuffer[String], 0);
for(test <- hold) println(test);
My error is:
Driver.scala:35: error: type mismatch;
found : Unit
required: scala.collection.mutable.ArrayBuffer[String]
ho = stringParse(str, 0, ho, 0);
^one error found
When I add an equals sign after the arguments in the method declaration, like so:
def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int ) ={....}
It changes it to "Any". I am confused on how this works. Any ideas? Much appreciated.
Here's a more general answer on how one may approach such problems:
It happens sometimes that you write a function and in your head assume it returns type X, but somewhere down the road the compiler disagrees. This almost always happens when the function has just been written, so while the compiler doesn't give you the actual source (it points to the line where your function is called instead) you normally know that your function's return type is the problem.
If you do not see the type problem straight away, there is the simple trick to explicitly type your function. For example, if you thought your function should have returned Int, but somehow the compiler says it found a Unit, it helps to add : Int to your function. This way, you help the compiler to help you, as it will spot the exact place, where a path in your function returns a non-Int value, which is the actual problem you were looking for in the first place.
You have to add the equals sign if you want to return a value. Now, the reason that your function's return value is Any is that you have 2 control paths, each returning a value of a different type - 1 is when the if's condition is met (and the return value will be temp) and the other is when if's condition isn't (and the return value will be b=b+1, or b after it's incremented).
class Test(condition: Boolean) {
def mixed = condition match {
case true => "Hi"
case false => 100
}
def same = condition match {
case true => List(1,2,3)
case false => List(4,5,6)
}
case class Foo(x: Int)
case class Bar(x: Int)
def parent = condition match {
case true => Foo(1)
case false => Bar(1)
}
}
val test = new Test(true)
test.mixed // type: Any
test.same // type List[Int]
test.parent // type is Product, the case class super type
The compiler will do its best to apply the most specific type it can based on the possible set of result types returned from the conditional (match, if/else, fold, etc.).