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

Hi, I'm using the following code to break apart a record:
(my $flags, my $x, my $y, my $mode3, my $callsign, my $route, my $spare1, my $spare2, my $flight_level, my $terminator, my $chksum_packet) = unpack ( "B16 n2 A4 A8 A2 A A A3 C2" }, $buffer);
I can't help thinking that I'd be better off using a data structure somehow. Is it possible to unpack directly into a structure and then access the individual elements of the structure?

Thanks for any ideas...

R.
--
Robin Bowes | http://robinbowes.com

Replies are listed 'Best First'.
Re: Data structure for this...
by ctilmes (Vicar) on Oct 16, 2003 at 12:44 UTC
    You could use a hash like this:
    my @keys = qw(flags x y mode3 callsign route spare1 spare2 flight_leve +l terminator chksum_packet); my %record; @record{@keys} = unpack("B16 n2 A4 A8 A2 A A A3 C2", $buffer);
    Just use $record{flags} instead of $flags etc.
Re: Data structure for this...
by Limbic~Region (Chancellor) on Oct 16, 2003 at 12:45 UTC
    robinbowes,
    First a comment on style - you do not need to repeat the use of my if all the variables in the list will be new lexicals.
    my ($one, $two, $three) = qw(1 2 3); # works just fine
    As far as using a datastructure, a hash makes the most sense since trying to remember which array index corresponds to which variable is a PITA. This will also allow you to create complex data structures (AoH, HoH, etc) later if you need to.
    #!/usr/bin/perl -w use strict; my $buffer; # Defined elsewhere my %hash; my @keys = qw(flags x y mode3 callsign route spare1 spare2 flight_leve +l); @hash{@keys} = unpack ( "B16 n2 A4 A8 A2 A A A3 C2" }, $buffer); print $hash{mode3};
    There are two more things to point out. The first is that it appears you have more variables than the unpack will return - which means undef values. The second is to understand auto-vivication when using hash slices.

    Cheers - L~R

      Hi,

      Thanks for the suggestions re: style - I knew it wasn't very elegant, but want to get the script to run with "use strict" so just pasted in all the "my"s !

      I'll go away and modify my code to use a hash as suggested.

      Regarding the issue of too many variables, both n2 and C2 unpack to two items each, so there is actually the correct no. of variables. Perhaps it would be clearer to write "n n" and "C C".

      Finally, WTF is auto-vivication?? !!
      --
      Robin Bowes | http://robinbowes.com
        robinbowes,
        my ($one, $two, $three) = qw(1 2 3); # works with warnings and stric +tures
        You are of course correct about unpack returning the correct number of values. I am a novice in that regard, so I leave the style up to you.

        Auto-vivication is the action by which a hash key that didn't previously exist gets created. This may or may not be intentional. Consider:

        #!/usr/bin/perl -w use strict; my %hash; print "wow\n" if $hash{foo}{bar}; print $_, $/ for keys %hash;
        Just by testing if the second level key 'bar' was true, 'foo' was automatically created. In the example code that I gave you, the hash keys were being auto-vivified intentionally in a hash slice. Sometimes it can be unintentional.

        Cheers - L~R

        auto-vivification - PerlDoc is your friend.

        Essentially, it's the fact that Perl will quietly create a space for something if you refer to it. Example:

        my %x; $x{foo} = 'bar';

        In that example, the memory for $x{foo} is auto-vivified. Contrast that with C++ and you'll see the benefit.

        ------
        We are the carpenters and bricklayers of the Information Age.

        The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

        ... strings and arrays will suffice. As they are easily available as native data types in any sane language, ... - blokhead, speaking on evolutionary algorithms

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Data structure for this...
by calin (Deacon) on Oct 16, 2003 at 14:56 UTC
    You can put any valid lvalues on the left side of a list assignment. Inexistent things (array and hash elements -- including slices, deep (referenced) objects) will come to life automagically. The automatic creation of referenced objects is called autovivification.

    See perldsc, perlref, perldata etc.

    As Limbic~Region has pointed out, if you get less values on the right than of the left side in a hash slice assignment, the hash elements that do not have a correspondent on the right side will be created with an undef value (they will exist as far as exists / keys etc. are concerned). Try this example:

    @h{'a', 'b'} = qw/ one /; print "Exists!\n" if exists $h{b}; print "Undef!\n" unless defined $h{b};
A reply falls below the community's threshold of quality. You may see it by logging in.