I am working on a Perl code using XML::DOM.
I found in Perl help(XML::DOM::Node) stating as below.
#list = $node->getChildNodes; # returns a perl list
$nodelist = $node->getChildNodes; # returns a NodeList (object reference)
for my $kid ($node->getChildNodes) # iterate over the children of $node
If I pass it in my function as below.
&myfunction($node->getChildNodes)
I am not getting the reference to the list.
Is there any way to get the reference with out declaring temporary scalar variable, like below.
my $tmp=$node->getChildNodes;
&myfunction($tmp)
Thank you.
myfunction([ $node->getChildNodes ])
myfunction(scalar $node->getChildNodes)
The second avoids creating a new array and a new reference, but the first might be clearer.
PS — Why are you telling Perl to ignore the prototype on myfunction? Don't use &.
Related
Let me start by saying I haven't programmed in Perl in a LONG time.
Currently trying to get some older code to work that relies on defined with an array.
Code (abridged):
# defined outside the file-reading block
my %refPRE;
# line from a file
#c = split();
if (defined #{$refPRE{$c[0]}})
{
# do stuff
}
Now this won't run like this because of the following error:
Can't use 'defined(#array)' (Maybe you should just omit the defined()?)
Fine, but if I removed the defined then I get the following error:
Can't use an undefined value as an ARRAY reference.
I can see what it's trying to do (if $c[0] is in the $refPRE then do this, else do something else) but I'm not familiar enough with Perl to figure out what the right way to get this to work is. Hoping this is trivial for someone.
Apparently posting here is all the catalyst I needed...
Switching if (defined #{$refPRE{$c[0]}}) to if ($refPRE{$c[0]}) was sufficient to work! Hopefully this helps someone else who searching for this (specific) problem...
Can't use an undefined value as an ARRAY reference.
This is saying that $refPRE{ $c[0] } is returning undef, and you cannot dereference undef as an array.
#{ undef } # will error
You don't need to deref this at all. If it returns undef, it's false. If it returns anything else, that will (likely) be true.
if ( $refPRE{$c[0]} )
{
my $foo = #{ $refPRE{$c[0]} };
# do stuff
}
Looking at your second error $refPRE{$c[0]} can be undefined so #{ ... } is failing. You can fix this using the undef or opperator // like this.
if (#{ $refPRE{$c[0]} // [] }) { ... }
This checks if $refPRE{$c[0]} is defined and if not returns an empty anonymous array. An empty array is false in an if statement.
I am trying to filter a liststore using the GTK2::TreeModelFilter. I can't seem to find an example online that uses perl and I am getting syntax errors. Can someone help me with the syntax below? The $unfiltered_store is a liststore.
$filtered_store = Gtk2::TreeModeFilter->new($unfiltered_store);
$filtered_store->set_visible_func(get_end_products, $unfiltered_store);
$combobox = Gtk2::ComboBoxEntry->new($filtered_store,1);
Then somewhere below:
sub get_end_products {
my ($a, $b) = #_;
warn(Dumper(\$a));
warn(Dumper(\$b));
return true; # Return all rows for now
}
Ultimately what I want to do is look at column 14 of the listore ($unfiltered_store) and if it is a certain value, then it filtered into the $filtered_store.
Can someone help me with the syntax on this? I checked a bunch of sites, but they're in other languages and using different syntax (like 'new_filter' -- doesn't exist with Perl GTK).
This is the most elegant solution to a fix I need to make and I would prefer to learn how to use this rather than using a brute force method of pulling and saving the filtered data.
The set_visible_func method of the filtered store should get a sub reference as the first argument, but you are not passing a sub reference here:
$filtered_store->set_visible_func(get_end_products, $unfiltered_store);
This will instead call the sub routine get_end_products and then pass on its return value (which is not a sub reference). To fix it add the reference operator \& in front of the sub name:
$filtered_store->set_visible_func(\&get_end_products, $unfiltered_store);
Regarding your other question in the comments:
According to the documentation the user data parameter is passed as the third parameter to get_end_products, so you should define it like this:
sub get_end_products {
my ($model, $iter, $user_data) = #_;
# Do something with $user_data
return TRUE;
}
If for some reason $unfiltered_store is not passed on to get_end_products, you can try pass it using an anonymous sub instead, like this:
$filtered_store->set_visible_func(
sub { get_end_products( $unfiltered_store) });
Running Perl 5.18 on Ubuntu 14.04 LTS, I wanted to create some pathname constants so I did
use Path::Class;
use constant FILEPATH => file('directory', 'filename');
However, when I came to use the constant in a hash aggregate ...
my $hash = { filepath => FILEPATH };
use Data::Dumper;
print Dumper $href;
... I was surprised to discover that the value of the filepath key was a blessed reference, not the string result from the function call that I was expecting.
I can work around the problem like this ...
use constant FILEPATH => file('directory', 'filename') . "";
... which forces the Perl interpreter to evaluate the blessed reference, but
(a) is there a better way, and
(b) what the heck is going on?!
I know that use constant is evaluated in a list context, but normally use constant MYCONST => mysub(arg1, arg2); does The Right Thing, evaluates the subroutine call and uses the return value. What's the cleverness with Path::Class::file that breaks this expectation?
The file function from the module Path::Class is in fact a constructor for a Path::Class object. It always returns an object. Even the SYNOPSIS says so.
use Path::Class;
my $dir = dir('foo', 'bar'); # Path::Class::Dir object
my $file = file('bob', 'file.txt'); # Path::Class::File object
If all you want is the path, call that method on the return value of file and assign that calls' return value to your constant. The object you get is a Path::Class::File. It provides various methods. To do the same as when you use the string overload, call the stringify method.
use constant FILEPATH => file('directory', 'filename')->stringify;
The relevant part of HTML::Tiny decides what to do based on the type of the inputs. It expects either undef, a string or an array ref, but you provided something that is none of these. In other words, this is a case of GIGO. You are using the value returned by file(), which is an object that overloads stringification.
Use either of the following to provide the expected input:
use constant FILEPATH => file('directory', 'filename')->stringify;
or
use constant FILEPATH => "".file('directory', 'filename');
Note that it's usually unsafe to unsafe to use objects as constants because they're not constant. However, since file() returns an immutable object, there's no harm in using it as a constant since it really is constant.
You're right about Path::Class::file returning an object. That's what all the "bless" stuff was in the Dumper output. Sorry I didn't realise that sooner.
As you'll see from my comments, I ran into the problem using HTML::Tiny, which you can see as follows:-
$ perl -MPath::Class -MHTML::Tiny -le 'print HTML::Tiny->new(mode=>"html")->form({action=>file("cgi-bin", "script")})'
<form action></form>
As you can see, the action attribute is missing the path. However,
$ perl -MPath::Class -MHTML::Tiny -le 'print HTML::Tiny->new(mode=>"html")->form({action=>file("cgi", "script").""})'
<form action="cgi/script"></form>
This works because the ."" string concatenation operator causes the Class::Path::File object's automatic stringifier to be called, so an actual string is passed in the {action=>value} hash, not an object.
If you dig into the HTML::Tiny 1.05 code, you'll find sub _tag on line 622, which goes
if ( ref $val ) {
return $attr if not $self->_xml_mode;
This test allows you to use { attr=>[] } to output an attribute name without a value, but unfortunately the test is also TRUE if $val is an object. I'll raise a bug report for this against HTML::Tiny.
The code:
my $compare = List::Compare->new(\#hand, \#new_hand);
print_cards("Discarded", $compare->get_Lonly()) if ($verbose);
print_cards expects (scalar, reference to array).
get_Lonly returns array. What's the syntax to convert that to a reference so I can pass it to print_cards? \#{$compare->getLonly()} doesn't work, for example.
Thanks!
You probably want
print_cards("Discarded", [$compare->get_Lonly])
Subroutines don't return arrays, they return a list of values. We can create an array reference with [...].
The other variant would be to make an explicit array
if ($verbose) {
my #array = $compare->get_Lonly;
print_cards("Discarded", \#array)
}
The first solution is a shortcut of this.
The #{ ... } is a dereference operator. It expects an array reference. This doesn't work as you think if you give it a list.
The following script gives me what I want but Perl also throws me a warning saying "Useless use of a variable in void context". What does it mean?
use strict;
use warnings;
my $example = 'http\u003a//main\u002egslb\u002eku6\u002ecom/c0/q7LmJPfV4DfXeTYf/1260269522170/93456c39545857a15244971e35fba83a/1279582254980/v632/6/28/a14UAJ0CeSyi3UTEvBUyMuBxg\u002ef4v\u002chttp\u003a//main\u002egslb\u002eku6\u002ecom/c1/q7LmJPfV4DfXeTYf/1260269522170/3cb143612a0050335c0d44077a869fc0/1279582254980/v642/10/20/7xo2MJ4tTtiiTOUjEpCJaByg\u002ef4v\u002chttp\u003a//main\u002egslb\u002eku6\u002ecom/c2/q7LmJPfV4DfXeTYf/1260269522170/799955b45c8c32c955564ff9bc3259ea/1279582254980/v652/32/4/6pzkCf4iqTSUVElUA5A3PpMAoA\u002ef4v\u002chttp\u003a//main\u002egslb\u002eku6\u002ecom/c3/q7LmJPfV4DfXeTYf/1260269522170/cebbb619dc61b3eabcdb839d4c2a4402/1279582254980/v567/36/19/MBcbnWwkSJu46UoYCabpvArA\u002ef4v\u002chttp\u003a//main\u002egslb\u002eku6\u002ecom/c4/q7LmJPfV4DfXeTYf/1260269522170/1365c39355424974dbbe4ae8950f0e73/1279582254980/v575/17/15/EDczAa0GTjuhppapCLFjtaQ\u002ef4v';
my #raw_url = $example =~ m{(http\\u003a.+?f4v)}g;
my #processed_url = map {
s{\\u003a}{:}g,$_;
s{\\u002e}{.}g,$_;
s{\\u002d}{#}g,$_;
} #raw_url;
print join("\n",#processed_url);
And why this map thing doesn't work if I omit those dollar underscores like so?
my #processed_url = map {
s{\\u003a}{:}g;
s{\\u002e}{.}g;
s{\\u002d}{#}g;
} #raw_url;
When I omit those dollar underscores, I get nothing except for a possibly success flag "1". What am I missing? Any ideas? Thanks like always :)
What you want is...
my #processed_url = map {
s{\\u003a}{:}g;
s{\\u002e}{.}g;
s{\\u002d}{#}g;
$_;
} #raw_url;
A map block returns the value composed of the last statement evaluated as its result. Thats why we pass the $_ as the last statement. The substitution operator s{}{} returns the number of substitutions made.
In your prior setup, you had by itself the following statement. Which is pretty much meaningless and that is what Perl is warning about.
s{\\u003a}{:}g, $_;
You already have the answer you were looking for, but I wanted to point out a subtlety about using the substitution operator inside a map block: your original array is also being modified. If you want to preserve the original array, one way to do it is to make a copy of the array, then modify only the copy:
my #processed_url = #raw_url;
for (#processed_url) {
s{\\u003a}{:}g;
s{\\u002e}{.}g;
s{\\u002d}{#}g;
}
Or, if you only need one array, and you want the original to be modified:
for (#raw_url) {
s{\\u003a}{:}g;
s{\\u002e}{.}g;
s{\\u002d}{#}g;
}