Fighter2 has asked for the wisdom of the Perl Monks concerning the following question:

Hi.

I am trying to learn by hacking Perl code instead of reading a book. I am very new. I am also new here to Perlmonks.com. Please be nice.

Here is the code.

############## #processfile.pl ############## use Fruits; #using a pm file here. $filehandle = "logfile.isf"; my $packets=[0AA0,0FFA]; my obj= new Fruits($filehandle, $packets); my $numApplepackets= $obj->{records}->{0AA0}->{totalRecords}; my $numBananapackets= $obj->{records}->{0FFA}->{totalRecords}; my BananaNum; my fruitobj; for($BananaNum=1; $BananaNum le $numBananapackets; $BananaNum++){ $fruitobj = $obj->parse0FFA($BananaNum); for(my $j=0;$j<2;$j++){ if($obj->{$j}->{rxABC} > -100){ print "Found"; } } } ############# #Fruits.pm ############# sub parse0FFA{ my $self=shift; my $i=shift; my $size=$self->{records}->{0FFA}->{totalRecords}; my $len=$self->{records}->{0FFA}->{$i}->{_length}; my $data=$self->{records}->{0FFA}->{$i}->{_data}; my ($obj,$tmp,$j); $obj->{timestamp}=$self->{records}->{0FFA}->{$i}->{_timestamp}; for($j=0;$j<2;$j++){ $len=$len-13; ($tmp, $obj->{$j}->{txABC},$obj->{$j}->{txDEF},$obj->{$j}->{txGHI} +, $obj->{$j}->{txJKL}, $obj->{$j}->{rxABC}, $obj->{$j}->{rxDEF}, $dat +a)=unpack("C v v v v v v a$len",$data); $obj->{$j}->{State} = int($tmp/32); $obj->{$j}->{Mode} = int($tmp/16); if($obj->{$j}->{txABC} >= 2*5){ $obj->{$j}->{txABC} -= 2*16;} $obj +->{$j}->{txABC} /= 256; if($obj->{$j}->{txDEF} >= 2*5){ $obj->{$j}->{txDEF} -= 2*16;} $obj +->{$j}->{txDEF} /= 256; if($obj->{$j}->{txGHI} >= 2*5){ $obj->{$j}->{txGHI} -= 2*16;} $obj +->{$j}->{txGHI} /= 256; if($obj->{$j}->{txJKL} >= 2*5){ $obj->{$j}->{txJKL} -= 2*16;} $obj +->{$j}->{txJKL} /= 256; if($obj->{$j}->{rxABC} >= 2*5){ $obj->{$j}->{rxABC} -= 2*16;} $obj +->{$j}->{rxABC} /= 256; if($obj->{$j}->{rxDEF} >= 2*5){ $obj->{$j}->{rxDEF} -= 2*16;} $obj +->{$j}->{rxDEF} /= 256; } return $obj; } #################END

Please Read. I am sorry if the above code is Big. I am new here, and I don't know all the rules and how things are done here. I am sorry if it sounds complicated.I also want to tell you that the .pl file I have works and runs fine. And it returns Found when you run from command line. I have some idea what we are doing here in this code. I am parsing something out and checking if a certain packet is there or not. I am only concerned about rxABC packet inside the 0FFA (Banana packets). Please don't worry about the calculations inside the for loop inside the pm file. My questions are here below.

2.What is happening here? Am I trying to fetch totalRecords which is inside 0AA0 which is inside records and storing that value in numApplepackets?? And is obj a reference to the subroutine Fruits?

my $numApplepackets= $obj->{records}->{0AA0}->{totalRecords};

3.What is happening here?

$fruitobj = $obj->parse0FFA($BananaNum);

4.Please explain this step to me? THe -> operator confuses me.

for($BananaNum=1; $BananaNum le $numBananapackets; $BananaNum++){ $fruitobj = $obj->parse0FFA($BananaNum); for(my $j=0;$j<2;$j++){ if($obj->{$j}->{rxABC} > -100){ print "Found"; } } }

5.What is a shift keyword for here. What does it do?

my $self=shift;

6.Explain this step very briefly (i have a small idea)?

my $size=$self->{records}->{0FFA}->{totalRecords};

7.What is happening here? Am I fetching _timestamp of i from 0FFA from records to obj of i ??

$obj->{timestamp}=$self->{records}->{0FFA}->{$i}->{_timestamp};

8.What is happening in this part of the for loop?

for($j=0;$j<2;$j++){ $len=$len-13; ($tmp, $obj->{$j}->{txABC},$obj->{$j}->{txDEF},$obj->{$j}- +>{txGHI}, $obj->{$j}->{txJKL}, $obj->{$j}->{rxABC}, $obj->{$j}->{rxDE +F}, $data)=unpack("C v v v v v v a$len",$data);

I know it might sound a little complicated. Basically its a big file which contains a lot of packets. The packet of concern here is rxABC. Ignore the rest. I know the unpack command is just trying to expand the values inside the string. I am very grateful for you to have read this code and trying to help me. I am new to Perl and I really need to know what's going on here. This is not homework. And there is no time to go fetch a Perl book to read/learn right now, but I am. Just haven't gotten the advanced parts yet. And I have little time to figure this code out to make some changes. Also, its been some yrs since I have programmed. People forget things. Your help is much much appreciated. Thank-you!!

p.s: user ikegami from stackoverflow told me come here to ask q's :)
  • Comment on I have a perl snippet. And I need help understanding it. Can you help answer these questions.
  • Select or Download Code

Replies are listed 'Best First'.
Re: I have a perl snippet. And I need help understanding it. Can you help answer these questions.
by davido (Cardinal) on Nov 07, 2011 at 22:18 UTC

    Here are some pointers:

    1. I didn't see a question 1.
    2. my $numApplepackets= $obj->{records}->{0AA0}->{totalRecords}; is accessing the scalar value held in a hash ref that is nested several levels deep. The entire structure is held in the object reference named $obj. Breaking encapsulization like that isn't a very good object interface for the Fruits class though.
    3. With $fruitobj = $obj->parse0FFA($BananaNum); the Fruits::parse0FFA() function is being used as an object method for the class Fruits's object held as a blessed reference in $obj. The -> operator is dereferencing $obj to access the parse0FFA() sub from package Fruits.
    4. $obj->{$j}->{rxABC} > -100 You're testing whether the value held in $obj->{$j}->{rxABC} is greater than -100.
    5. shift is documented in shift. It shifts a value off of the array passed to it as a parameter argument. If there's no parameter, it shifts off of @_, which is the param list from the sub that it's being invoked within (or @ARGV outside of subs).
    6. my $size = $self->{records}->{0FFA}->{totalRecords} stores a value in $size that is held in the object structure referred to by $self.
    7. $obj->{timestamp} is being assigned a value that is held in $self->{records}->{0FFA}->{$i}->{_timestamp}
    8. ( $tmp, $obj->{$j}->{txABC}, .... ) are being assigned the list of items that are unpacked by unpack.

    It probably still doesn't make a ton of sense yet. You're going to need to read the following: shift, unpack, pack, perlpacktut, perlreftut, perldsc, and perlobj, at minimum, before it's going to start becoming clearer. That's several hours of reading material, which will probably need to be broken up into a couple of days. The information is quite dense, and may or may not help the light bulb of understanding to flick on.

    A much gentler approach is available: It might be a really good idea to rush over to your local bookstore (or oreilly.com or amazon.com) and pick up a copy of Learning Perl (O'Reilly) and Intermediate Perl (O'Reilly). You'll spend a week or so with each book, and suddenly find yourself able to understand the code posted, as well as a great many other things Perl related.

    ps. ikegami is right. StackOverflow is fine for questions that can be answered without a lot of deeper discussion. StackOverflow is not well suited to threaded discussions. When it comes to coaching a person along the learning process, the PerlMonks Monastery is a more flexible environment.


    Dave

      Good answers to the specific questions. I just want to chime in and agree that this is pretty dense code to try to learn from. It's got unpack, which is fairly complex in itself, plus OO (and an object structure several levels deep), subroutine argument handling, and more. On top of that, it's not very Perlish code. If you're learning Perl, you don't want to learn to use C-style for loops like the first line below when you can do the second one:

      for( my $j=0; $j<2; $j++){ # C-style loop for my $j (0..1){ # Perl-style loop, much clearer

        hey bud. So when I replaced the for loop exactly the way you have mentioned I get the following error.

        Use of uninitialized value in numeric gt()) at logprocess.pl in line 119

        which is that loops line number where the for loop is at.

        Also, can you please teach me how to print the value inside of a nested nested nested hash. THis one. I want to see the value of rxABC from? $obj->{$j}->{rxABC} I tried print "Found: $$obj->{$j}->{rxABC}" and it wont work. :(

      Thank-you so much Dave! I am really grateful to you. I sort agree this is a bad way to study Perl. But then again, this is a work that fell in my lap, and they just expect me to do it ASAP whether I know Perl or not. I had to understand this code in order to make the required hacks/modifications to meet my new specs.

      I got the books you have told me to fetch from the company library :). Btw, to answer your question why is the scalar value nested in so deep, that is the way the log file is which I need to dig out the data from. It's from a Universal format for Scientific data called NetCDF unfortunately.

      For Question 3. I want to write down what I understood. I know parse0FFA is a function inside the .pm file Fruits.pm and that obj is a reference to that pm file and by $obj->parse0FFA() I am able to fetch a sub from that pm file. Correct me if I am wrong thus far.

      Now, you used a term 'deference' which I didn't understand in your answer. Here. Lets try again. Are you telling me sir that in

      $fruitobj=$obj->parse0FFA($BananaNum);

      the number of Bananapackets is given to the subroutine parse0FFA() which is in the pm file and the result (or return) of that function is now stored in the scalar variable $fruitobj. And that $obj is only a reference (what we call objects in C or C++) to the function parse0FFA ? Is that a correct understanding. I think I am getting the hang of Perl now. At-least syntax and coding style. And finally for Q7. I fully understand your answer. Thankyou. Please read your answer again. Now, I have a question. Is the $obj->{timestamp} the reference $obj from the logprocess.pl file or is this a local reference $obj from the .pm file? I think it's the latter, but just wanted to check. Thanks again!

        The word was "dereference," which means "to get at the thing pointed to by the reference." If you're familiar with C, references are a lot like pointers, except that you can't do arithmetic on them; they're essentially read-only. So for instance:

        my @array = qw(a b c d); # create an array print $array[2]; # prints 'c' my $arrayref = \@array; # create a reference to the array print $arrayref->[2]; # prints 'c'. The arrow is required when # getting an element of an array or hash # pointed to by a reference my @newarray = @{$arrayref}; # dereference $arrayref to get at the # array it points to, and # copy it to @newarray print $newarray[2]; # prints 'c'

        Aaron B.
        My Woefully Neglected Blog, where I occasionally mention Perl.

      I also now notice that 'new' is not a Perl keyword and it was another subroutine defined (and derived) from the pm file which I fail to notice and see. I should have realized that all Perl keywords are highlighted in blue color in my editor(Notepad++). btw, in case anyone's confused,new is a log parser, it takes a file and a filterlist and puts all the values into a variable.

        Correct: new() is not a built-in. I assumed that it existed in the module, and that you just didn't include that portion of the code. Otherwise, the code you posted wouldn't have made much sense. new() is the "constructor" for the object, and it has to be written by the module's author. There's nothing special about the name new() either. DBI uses connect(), and other modules use other names that make sense as constructors for their respective classes. However, unless you have a good reason, new() is usually the most predictable and sensible name to use.

        One thing: The code you posted is really a bad example to learn from. It's considered a bad practice to deal with the object's internals directly from outside the object, and that's what the example code is doing. The class's author should be free to implement the object however he wants internally, and expose its internals through well-defined accessors in a way that abstracts away the details of implementation. ...that's at least my opinion about what code I saw posted. But I understand you've got the hand of cards that some previous developer handed you. Just be aware that when it comes time to actually learn how to write OO in Perl, Intermediate Perl is an excellent resource. And Modern Perl (by chromatic) will get you started with Moose (Perl's newer, more palatable object system).


        Dave

Re: I have a perl snippet. And I need help understanding it. Can you help answer these questions.
by Fighter2 (Novice) on Nov 07, 2011 at 21:10 UTC
    testing comment