ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
So I have a method that I'm getting a value from, my question is at the bottom:
the method with parameters:
adj_int_units(${$hashRef->{$_}}[$index]);
I tried doing this but it doesn't get the returned value:
my $adjustedUnits = adj_int_units(${$hashRef->{$_}}[$index]);
$adjustedUnits becomes ' ', so when it gets executed I get this error:
Argument " " isn't numeric in numeric gt (>) at ./pflogsumm line 1111, <> line 7603457.
Question: How can I put the value execute the method THEN give the returned value to $adjustedUnits??
With (BA)SH shell scripting I could use:
adjustedUnits = `stuff to get a return value from first`
Last edited by hopspitfire; 04-14-2008 at 12:02 AM.
The warning you are getting makes me think that the argument you are passing:
Code:
${$hashRef->{$_}}[$index]
...is either undefined or evaluates to a non-numeric string, and a numeric value is expected.
The argument evaluates to an integer in the "# Used to be" section of "print_user_data" subroutine. When I change it to return the value to the variable $adjustedUnits, it doesn't evaluate (as far as I can tell)
I've included the full subroutines for this section. This project is basically heavily modifying pflogsumm for use at work.
print_user_data subroutine
Code:
# print "per-user" data sorted in descending order
# order (i.e.: highest first)
sub print_user_data
{
my($hashRef, $title, $index, $cnt, $quiet) = @_;
my $dottedLine;
return if($cnt == 0);
$title = sprintf "%s%s", $cnt > 0? "top $cnt " : "", $title;
unless(%$hashRef) {
return if($quiet);
$dottedLine = ": none";
}
else
{
$dottedLine = "\n" . "-" x length($title);
}
printf "\n$title$dottedLine\n";
foreach (map { $_->[0] }
sort { $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2] }
map { [ $_, $hashRef->{$_}[$index], normalize_host($_) ] }
(keys(%$hashRef)))
{
# Used to be:
#printf " %6d%s %s\n", adj_int_units(${$hashRef->{$_}}[$index]), $_;
#last if --$cnt == 0;
# Now it is:
my $adjustedUnits = adj_int_units(${$hashRef->{$_}}[$index]);
if($adjustedUnits > 30000000)
{
printf " %6d%s %s\n", adj_int_units(${$hashRef->{$_}}[$index]), $_;
last if --$cnt == 0;
}
}
}
What does putting the parentheses around the variable signify?
It forces list context which allows the right hand side to be evaluated as a list, and assigns corresponding elements on the right hand side to those on the left hand side. You already use this property when you say:
Code:
my($hashRef, $title, $index, $cnt, $quiet) = @_;
Here you have an array in list context. In the other statement, you want a list literal in list context, whereas you originally have it in scalar context.
An array in scalar context evaluates to its size, whereas a list literal in scalar context does not give a list at all, but rather evaluates the last expression in scalar context (and the previous expressions in void context) because of the semantics of the comma operator.
If you are confused by this behavior, here’s an exercise. Consider the following program:
#!/usr/bin/perl
# Standard dynamic array. It is evaluated left to right, index starts
# at 0.
@array = ("one", "two", "three");
# $scalar1 gets "one", "two" then "three", but it only retains
# the last value.
$scalar1 = ("one", "two", "three");
# $scalar2 gets the length of the array, 3 (I'm not sure why). I
# would expect it to get each value individually, and retain
# "three".
$scalar2 = @array;
# Combines the ideas of $scalar1 and $scalar2, feeds the values
# individually from "one"..."three", then it receives the length
# of the array (still not sure why).
$scalar3 = ("one", "two", "three", @array);
# This one builds upon the last 3, with the addition of the range
# operator. I'm not sure why it evaluates to one. It is
# evaluating outside the parentheses and has something to do with
# 1 through 3...
$scalar4 = ("one", "two", "three", @array)[1..3];
# I assume putting a backslash in front of the array makes it
# evaluate and output all valies from the array as one string.
$arrayref = \@array;
# Putting the @array in parentheses makes it evaluate the same
# way as $scalar=@array ??
$scalarref = \(@array);
# Each variable gets their value according to position (position assignments)
# so (1, 2, 3) = (1, 2, 3). I assume you can also use keyword assignments,
# such as ($one, $two, $three) = ($two="two", $one="one", $three="three")
# and the output would be exactly the same.
($one, $two, $three) = ("one", "two", "three");
# According to the output, putting the variable in parentheses makes it
# receive and retain the first value only.
($initial) = ("one", "two", "three");
# Also using position assignments. I assume undef is a keyword for null,
# so it doesn't retain a value. Since "two" is in the second position,
# $middle receives that value.
(undef, $middle) = ("one", "two", "three");
# What does \" do?
print "$_ is ", eval "\"$_\n\"" for
qw{ @array
$scalar1 $scalar2 $scalar3 $scalar4
@$arrayref $$scalarref
$one $two $three
$initial $middle
};
I think a basic concept you are missing is the concept of context in perl. Context can be either scalar or list (technically void is also a context, but we don’t care about it now), and what it means is that the thing on the left hand side determines how the right hand side behaves. If there is a scalar (using the $ sigil) on the left hand side (or the scalar function is used), you have scalar context. With anything else on the left hand side, you have list context. With no left hand side, you normally have void context. This applies to operators, builtins, and functions.
Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. This is just like C's comma operator.
In list context, it's just the list argument separator, and inserts both its arguments into the list. These arguments are also evaluated from left to right.
So here is an explanation of the program:
Code:
#!/usr/bin/perl
# Since you have an array on the left hand side, you give list
# context to the right hand side, and the overall result is list
# assignment, so corresponding entries on the right are assigned
# to the list on the left.
@array = ("one", "two", "three");
# Since you have a scalar on the left hand side, you give scalar
# context to the right. So the expression with the comma operator
# is the same as $scalar1 = ("one", ("two", "three")). Namely,
# "one" is evaluated (in void context) and thrown away, then
# ("two", "three") is returned in scalar context. In this case,
# "two" is evaluated (in void context) and thrown away, and finally
# "three" is evaluated in scalar context and returned. So the result
# is the assignment of "three" to $scalar1. In general, the net
# result of a list literal in scalar context is just the evaluation
# of the last term in scalar context.
$scalar1 = ("one", "two", "three");
# You give scalar context to the right hand side. A fundamental
# part of perl is that an array in scalar context evaluates to its
# size. So $scalar2 is assigned 3 (the size of @array).
$scalar2 = @array;
# This is similar to the $scalar1 assignment. In particular, the
# result should be the evaluation of the last term in scalar context.
# As we saw before it is just the size of @array (namely 3).
$scalar3 = ("one", "two", "three", @array);
# This one is tricky, since the slicing the list will flatten it.
# So this is the same as
# $scalar4 = ("one", "two", "three", "one", "two", "three")[1..3];
# which is the same as
# $scalar4 = ( "two", "three", "one" );
# which as you can see evaluates to "one" in scalar context.
# Slices are one of the places where you have somewhat arbitrarily-
# decided behavior in scalar context.
$scalar4 = ("one", "two", "three", @array)[1..3];
# Using a backslash will give you a reference to whatever is inside.
# Thus, $arrayref is assigned a reference to @array. In particular,
# "@$arrayref" expands to the same thing as "@array" does, and
# @array[0] == $arrayref->[0], etc.
$arrayref = \@array;
# In general, parentheses around a list literal cause a backslash to
# be distributed. So (in general), \("one", "two", @array) is the same
# as (\"one", \"two", \@array). As a special case, however, if the only
# term inside the parentheses is an array or hash, its contents (or in
# the case of a hash its keys) are first expanded. So the statement
# below is equivalent to $scalarref = (\"one", \"two", \"three"), and
# since you have scalar context, you evaluate the last term in scalar
# context. Thus, $$scalarref is the same as "three".
$scalarref = \(@array);
# Here you have a list on the left hand side, to force list context.
# So it is a list assignment similar to @array=("one","two","three"),
# Where corresponding entries on the right are assigned to those on
# the left.
($one, $two, $three) = ("one", "two", "three");
# This is the same as above, except there are no entries corresponding
# to the second and third entries on the right. This is okay, since
# perl will just discard them, and only the initial value is assigned.
($initial) = ("one", "two", "three");
# Similarly, to force assignment of the middle value, you put a dummy
# variable in the first slot. Better than a dummy variable is undef,
# which tells perl to discard the first term. The third term is also
# discarded as above.
(undef, $middle) = ("one", "two", "three");
# This part wasn’t very important, but basically it takes each literal
# word in the list at the end, and prints both the word itself and an
# evaluation of "$_\n", since you want double quotes to be part of the
# argument to eval, you have to escape them. You don’t really have to
# escape the \, since \n is alreay expanded to what you want (but it
# wouldn’t be wrong if you did have eval "\"$_\\n\"").
print "$_ is ", eval "\"$_\n\"" for
qw{ @array
$scalar1 $scalar2 $scalar3 $scalar4
@$arrayref $$scalarref
$one $two $three
$initial $middle
};
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.