LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-14-2008, 12:00 AM   #1
hopspitfire
LQ Newbie
 
Registered: Jun 2007
Distribution: Gentoo/FreeBSD
Posts: 7

Rep: Reputation: 0
Perl Quickie


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.
 
Old 04-14-2008, 02:08 AM   #2
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 65
I don't understand the sentence:
Quote:
How can I put the value execute the method THEN give the returned value to $adjustedUnits?
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.
 
Old 04-14-2008, 02:20 AM   #3
hopspitfire
LQ Newbie
 
Registered: Jun 2007
Distribution: Gentoo/FreeBSD
Posts: 7

Original Poster
Rep: Reputation: 0
Quote:
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;
        }
    }
}
adj_int_units subroutine
Code:
sub adj_int_units
{
    my $value = $_[0];
    my $units = ' ';
    $value = 0 unless($value);
    if($value > $divByOneMegAt)
        {
         #$value /= $oneMeg;
         #$units = 'm'
        }
     elsif($value > $divByOneKAt)
        {
         #$value /= $oneK;
         #$units = 'k'
        }
 return ($value, $units);
}
 
Old 04-14-2008, 02:59 AM   #4
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 65
What is line 1111 in the file?
 
Old 04-14-2008, 03:48 AM   #5
hopspitfire
LQ Newbie
 
Registered: Jun 2007
Distribution: Gentoo/FreeBSD
Posts: 7

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by matthewg42 View Post
What is line 1111 in the file?
The equivalency test, the point is to only output messages greater than 30megs (30000000 bytes is close enough):

Code:
if($adjustedUnits > 30000000)

Last edited by hopspitfire; 04-14-2008 at 05:11 AM.
 
Old 04-14-2008, 08:40 PM   #6
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
The return value of adj_int_units is a list, and it looks like you want $adjustedUnits to hold the first value (is this correct?).

If so, you would want something like this:
Code:
my ($adjustedUnits) = adj_int_units(${$hashRef->{$_}}[$index]);
Otherwise, with
Code:
my $adjustedUnits = adj_int_units(${$hashRef->{$_}}[$index]);
you get the last value (which is a string).
 
Old 04-14-2008, 11:17 PM   #7
hopspitfire
LQ Newbie
 
Registered: Jun 2007
Distribution: Gentoo/FreeBSD
Posts: 7

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by osor View Post
The return value of adj_int_units is a list, and it looks like you want $adjustedUnits to hold the first value (is this correct?).

If so, you would want something like this:
Code:
my ($adjustedUnits) = adj_int_units(${$hashRef->{$_}}[$index]);
Otherwise, with
Code:
my $adjustedUnits = adj_int_units(${$hashRef->{$_}}[$index]);
you get the last value (which is a string).


Wow, that worked perfectly. Thank you!

What does putting the parentheses around the variable signify?
 
Old 04-15-2008, 01:46 PM   #8
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by hopspitfire View Post
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:
Code:
#!/usr/bin/perl

@array               = ("one", "two", "three");
$scalar1             = ("one", "two", "three");
$scalar2             = @array;
$scalar3             = ("one", "two", "three", @array);
$scalar4             = ("one", "two", "three", @array)[1..3];
$arrayref            = \@array;
$scalarref           = \(@array);
($one, $two, $three) = ("one", "two", "three");
($initial)           = ("one", "two", "three");
(undef, $middle)     = ("one", "two", "three");

print "$_ is ", eval "\"$_\n\"" for
qw{ @array
    $scalar1 $scalar2 $scalar3 $scalar4
    @$arrayref $$scalarref
    $one $two $three
    $initial $middle
};
Explain each assignment and state the context in which each right-hand-side expression is evaluated.

Last edited by osor; 04-15-2008 at 01:49 PM.
 
Old 04-15-2008, 08:53 PM   #9
hopspitfire
LQ Newbie
 
Registered: Jun 2007
Distribution: Gentoo/FreeBSD
Posts: 7

Original Poster
Rep: Reputation: 0
Ok, lets see how much of this I got right...

Code:
#!/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
};
 
Old 04-16-2008, 12:48 PM   #10
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
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.

If you read the perlop section of the perldoc, you will find the semantics of the comma operator:
Quote:
Originally Posted by perldoc perlop
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
};
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
just a quickie on qt(3) and RH/Mandrake th3_d0c Linux - General 0 07-31-2004 10:20 PM
A quickie: Killing X? orange400 Linux - General 1 06-15-2004 04:47 AM
Samba quickie! asktoby Linux - Networking 1 09-26-2003 01:38 PM
Quickie bkerensa Linux - Newbie 4 08-28-2003 12:27 PM
Just a quickie bigjohn Linux - General 6 12-02-2002 06:33 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:53 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration