I'm trying to pass additional RBL's to Net::RBLClient, sample code:-
use Net::RBLClient;
my $rbl = Net::RBLClient->new;
$rbl->lookup('25.23.75.65');
my #listed_by = $rbl->listed_by;
Documentation says that parameters can be passed as hash, however one of then parameter(which I'm trying to use) "lists" says it takes array reference. Couldn't understand how it exactly passed on this module.
I've a array reference like
my $rack = ['bl.spamcop.net', 'sbl.spamhaus.org', 'xbl.spamhaus.org'];
Not sure how this reference included in module construct.
Documentation:- CPAN
By the looks of the docs, the new() method accepts an optional hash as arguments, so pass in the array reference as the value to the lists key.
my $rack = ['bl.spamcop.net', 'sbl.spamhaus.org', 'xbl.spamhaus.org'];
my $rbl = Net::RBLClient->new(lists => $rack);
# then, after the object is created, carry on
$rbl->lookup('211.101.236.160');
my #listed_by = $rbl->listed_by;
You could also add other parameters in the same way if you needed/wanted to on object instantiation:
my $rbl = Net::RBLClient->new(
lists => $rack,
max_time => 10,
timeout => 3,
);
...etc. You could also declare the hash up front, and pass the whole shebang in:
my %params = (
lists => [
$blacklist_1,
$blacklist_2,
],
max_time => 10,
timeout => 3,
);
my $rbl = Net::RBLClient->new(%params);
Related
If I want to read a single parameter in a get request in scalatra I can do it as follows:
get("mypath/:id") {
val id = params("id")
...
}
According to the scalatra documentation I can also use multiParams to get a sequence of parameters:
val ids = multiParams("ids")
But it does not say how the URL should be formed should I wish to pass more than one parameter. So if I wanted to pass multiple ids what is the format for the URL?
I have tried it with ampersands, commas and semi-colons but to no avail: e.g.
../mypath/id1&id2
Check the docs: http://scalatra.org/guides/2.4/http/routes.html
As an example, let’s hit a URL with a GET like this:
/articles/52?foo=uno&bar=dos&baz=three&foo=anotherfoo
Look closely: there are two “foo” keys in there.
Assuming there’s a matching route at /articles/:id, we get the
following results inside the action:
get("/articles/:id") {
params("id") // => "52"
params("foo") // => "uno" (discarding the second "foo" parameter value)
params("unknown") // => generates a NoSuchElementException
params.get("unknown") // => None - this is what Scala does with unknown keys in a Map
multiParams("id") // => Seq("52")
multiParams("foo") // => Seq("uno", "anotherfoo")
multiParams("unknown") // => an empty Seq
}
So you would need to name each param. e.g. /mypath/?ids=id1&ids=id2&ids=id3
You can embed multiple same name parameters in the path and get them through multiParams:
// http://localhost:8080/articles/id1/id2
get("/articles/:id/:id"){
println(multiParams("id")) // => Seq("id1", "id2")
}
One of my colleagues used a comma after a statement instead of a semi-colon, what resulted was similar to the below code:
my $SPECIAL_FIELD = 'd';
my %FIELD_MAP = (
1 => 'a',
2 => 'b',
3 => 'c',
);
sub _translate_to_engine {
my ($href) = #_;
my %mapped_hash
= map { $FIELD_MAP{$_} => $href->{$_} } keys %$href;
$mapped_hash{$SPECIAL_FIELD} = FakeObject->new(
params => $mapped_hash{$SPECIAL_FIELD}
), # << comma here
return \%mapped_hash;
}
At first I was surprised that this passed perl -c, then I remembered the comma operator and thought I understood what was going on, but the results of the two print statements below made me doubt again.
my $scalar_return = _translate_to_engine(
{ 1 => 'uno', 2 => 'dos', 3 => 'tres' }
);
print Dumper $scalar_return;
# {'c' => 'tres','a' => 'uno','b' => 'dos','d' => bless( {}, 'FakeObject' )}
This call was made in scalar context and the result that I get is the expected result. The comma operator evaluated the LHS of the comma discarded, then evaluated the RHS. I don't believe that it can return the value of the RHS here, because evaluating the return statements leaves the subroutine.
my #list_return = _translate_to_engine(
{ 1 => 'uno', 2 => 'dos', 3 => 'tres' }
);
print Dumper \#list_return;
# [{'c' => 'tres','a' => 'uno','b' => 'dos','d' => bless( {}, 'FakeObject' )}]
This call was made in list context but the result I get is effectively the same as the call in scalar context. What I think is happening here: Both arguments are evaluated since the sub was called in list context, when the RHS is evaluated the return statement is executed so the LHS is effectively discarded.
Any clarification on the specific semantics that happen in either case would be appreciated.
Your explanation is accurate.
The context in which _translate_to_engine is called affects is the context in which all final expressions of the function are evaluated, including the argument to all return. There are two expressions affected in this case: the comma you mentioned, and \%mapped_hash.
In the first test, the returned value is \%mapped_hash evaluated in scalar context. And in the second, the returned value is \%mapped_hash evaluated in list context. \%mapped_hash evaluates to a reference to the hash, regardless of context. As such, the result of the sub is the same regardless of context.
The LHS of the expression is $mapped_hash{$SPECIAL_FIELD} = FakeObject->new(...) and the RHS is return \%mapped_hash. As you said, the comma operator evaluates the left hand side (which assigns a FakeObject instance to the hash key d), and then evaluates the right hand side, causing the sub to return the hashref. Makes sense to me.
Calling the sub in list or scalar context doesn't matter. It isn't going to change the context of the comma operator, which is the same in both cases.
I need help regarding handling of Perl variables. Here I am getting input as a hash. I now need to send this hash variable to another subroutine. How can pass data as an argument to another subroutine? The code below shows how I am approaching this:
if ($csData->{'CUSTOMER_INVOICE_DETAILS'})
{
$c->log->debug("API Response:". Dumper $csData->{'CUSTOMER_INVOICE_DETAILS'});
my $Charges = [];
my #customerCharges = $csData->{'CUSTOMER_INVOICE_DETAILS'};
foreach(#customerCharges)
{
my ($customername,$customeramount) = split /:/;
my $charge_hash = ({
customername => $customername,
customeramount => $customeramount
});
push(#$Charges, $charge_hash);
}
my #ReturnCharges = $self->API->get_customer_charges($Charges, $Customer->customerid, $params->{'invoiceid'});
The other subroutine where this data is being received is as follows:
sub get_customer_charges
{
my $self = shift;
my ($charge, $CustomerId, $INID) = #_;
my $http_request = {
action => 'GetTariff',
customerid => $CustomerId,
csid => $INID,
};
my $markups = $self->APIRequest($http_request);
###Charge Level ID Inserting As 10
my #ChargeLevels;
my #BaseLevelID;
foreach my $ch (#$charge)
{
my ($customername,$customeramount) = split(':', $ch->{'customername'}, $ch->{'customername'});
my $chargelevel = join(':', $ch->{'customername'}, $ch->{'customeramount'}, '10');
push(#BaseLevelID, $chargelevel);
}
push(#ChargeLevels, #BaseLevelID);
return #ChargeLevels;
}
When I print to the server log for CUSTOMER_INVOICE_DETAILS variable I am getting the following values:
API Response:$VAR1 = {
'Product' => '34.04',
'basetax' => '2.38',
'vattax' => '4.36'
};
After sending data to second subroutine the data coming in server log for second subroutine variable is as following:
Charges in API:$VAR1 = 'HASH(0xb75d6d8)::10';
Can anyone help how could I send the hash data from one subroutine to another?
Given your comments and that your source is:
API Response:$VAR1 = {
'Product' => '34.04',
'basetax' => '2.38',
'vattax' => '4.36'
};
And you're looking for:
API Response:$VAR1 = { 34.04:2.38:4.36:10 };
(and somehow you're getting:
Charges in API:$VAR1 = 'HASH(0xb75d6d8)::10';
This suggests this may be as simple as using the values system call. values extracts an array of all the values in the hash. Something like this (guessing a bit on which part of your code needs it).
my #list_of_values = values ( %{$csData->{'CUSTOMER_INVOICE_DETAILS'}} );
You say you want to "convert" a hash to an array, but your issue seems more complex and subtle so simple conversion is not likely what will solve your problem. Something in your subroutine is returning a hash reference when the rest of your code does not expect it to do so. If the data-structure you are passing contains the correct information but not in the form you expect, then you can either change the code to produce it in the expected form (e.g. to return an ARRAY) or change your subroutine so that it is able to handle the data that it is passed correctly.
As for "converting a hash" per se, if your data structure doesn't contain complex nested references and all you want to do is "convert" your hash to an array or list, then you can simply assign the hash to an array. Perhaps I'm not understanding your question but if this kind of simple "flattening" is all you want then you could try:
my $customer_purchase = {
'Product' => '34.04',
'basetax' => '2.38',
'vattax' => '4.36'
};
my #flat_customer_purchase = %{ $customer_purchase };
say "#flat_customer_purchase" ;
Output:
basetax 2.38 Product 34.04 vattax 4.36
You can then supply the hash data as the "array" to the second subroutine. e.g. treat #flat_customer_purchase as a list:
use List::AllUtils ':all';
say join " ", pairkeys #flat_customer_purchase
# basetax Product vattax
say join " ", pairvalues #flat_customer_purchase
# 2.38 34.04 4.36
etc.
NB: this assumes that for some reason you must pass an array. The example of running the pairvalues routine simply replicates #Sobrique's suggestion to use values directly on the hash you are passing but in my answer this grabs the values pairs from the array instead of the hash.
My sense is that there is more to the question. If API Response is a more complicated hash/object or, if for some other reason this basic perl doesn't work, then you will have to supply more information. You need to find out where your unexpected hash reference is coming from before you can decide how to handle it. You might find this SO discussion helpful:
Are Perl subroutines call-by-reference or call-by-value?
I have a perl array:
Print Dumper(\#jsession);
$VAR1 = [
'<html><body><form name = \'form\' id=\'form\' method = \'POST\' action = \'/Site.jsp\'><input type = hidden name = \'phpSessionID\' value = \'RBOpXs47l6AOw**\'><input type = hidden name = \'LoggedUserName\' value = \'User\'><!--input type = submit name = \'button\' value = \'goAhead\'--></form> <script language = \'JavaScript\'> document.getElementById(\'frmWelcome\').submit();</script></body'</html>
];
I want to get the value of the phpSessionID element into a perl variable.
Here is the HTML::TreeBuilder code that i tried:
$tree=HTML::TreeBuilder->new_from_content(#jsession);
$tree->dump();
It actually prints the HTML part from the array,But how do i use it to get the value of the element that i need?
Here is the code that actually worked for me,in case anyone else where to search for this:
$tree=HTML::TreeBuilder->new_from_content(#jsession);
$first_match = $tree->find_by_attribute('name' => 'phpSessionID');
$first_match->dump();
$value = $first_match->attr('value');
chomp($value);
print "$value";
You use look_down (https://metacpan.org/pod/HTML::Element#look_down) from the root element to describe and find the element you want -
#elements = $h->look_down( ...criteria... );
$first_match = $h->look_down( ...criteria... );
This starts at $h and looks thru its
element descendants (in pre-order), looking for elements matching the
criteria you specify. In list context, returns all elements that match
all the given criteria; in scalar context, returns the first such
element (or undef, if nothing matched).
Then use attr (https://metacpan.org/pod/HTML::Element#attr) on the found element to get the attribute value.
$value = $h->attr('attr');
$old_value = $h->attr('attr', $new_value);
Returns (optionally sets) the value of the given attribute of $h. The
attribute name (but not the value, if provided) is forced to
lowercase. If trying to read the value of an attribute not present for
this element, the return value is undef. If setting a new value, the
old value of that attribute is returned.
I am trying to make a state machine in Perl. To do this I have an array indexed by statenames. I can put subs into this array. Like this:
use constant {
stInit => 0,
stHeader => 1,
stSalesHeader => 2,
stCatagory => 3,
stData => 4,
stTotal => 5,
stError => 6,
};
my $state = stInit;
my #actions;
$actions[stInit] = [sub{logState("Initial state entered",2) }];
$actions[stHeader] = [sub{logState("Header state entered",2) }];
$actions[stSalesHeader] = [sub{logState("Sales header state entered",2) }];
$actions[stCatagory] = [sub{logState("Category state entered",2) }];
$actions[stData] = [sub{logState("Data state entered",2) }];
$actions[stTotal] = [sub{logState("Total state entered",2) }];
But then I have no Idea how to call the subroutine. I have tried this
$actions[$state]
But that appears not to work. Is this possible or am I completely off?
You really should add
use strict;
use warnings;
to the start of your code, which will find many simple mistakes for you. In this case your code is fine, and you can call your subroutines by using
$actions[$state][0]();
etc.
But there is no need to put the subroutines within square brackets, which just creates a one-element anonymous array and adds an additional level of indexing (hence the [0] in the above line of code. If you wrote code like this instead
$actions[stInit] = sub { logState("Initial state entered", 2) };
then you would be able to call the subroutines with
$actions[$state]();
On an a slightly different note, have you considered using FSA::Rules to write your state machine? It's fairly powerful, has optional GraphViz output and makes state machines rather easy to write.
You should do:
&{$actions[$state][0]}
but I'm not sure why you use an array... If you have just 1 function then
$actions[stData] = sub{ ... }
...
&{$actions[$state]}
will work. If you really want to execute many functions and use the array, then you can do:
map { &{$_} } #{$actions[$state]};
To call a subroutine from a reference:
&{$actions[$state]}();
However, based on your code, #actions does not contain subroutine references, but array references to the declaration of the subroutine.
first, declare the subs as you normally would and then build #actions:
$actions[0] = \&stInit;
$actions[1] = \&stHeader;
...and so on
Drop the extraneous anonymous array creation by removing the square brackets
$actions[stInit] = sub{logState("Initial state entered",2) };
You can then call the action with
$actions[stInit]();
If you have an action stored in a variable, e.g.
my $action = $actions[$actionID];
then you'll need a bit more syntax to make it actually do the call
$action->();
Then again, you could just use a hash instead of an array
my %actions = (
stInit => sub { logState("Initial state entered",2) },
stHeader => sub { logState("Header state entered",2) },
stSalesHeader => sub { logState("Sales header state entered",2) },
stCatagory => sub { logState("Category state entered",2) },
stData => sub { logState("Data state entered",2) },
);
which would save you from having to set up constants at the top. You could then call actions with
$actions{$state}();