in reply to Re: Corrupt Data?
in thread Corrupt Data?

Thanks for the discussion everyone...I always do my homework first, but the web has just as many bad examples and poorly written documentation as it does good ones. In any case, the goal here is for all of us, particularly myself, to become better programmers. To that end, since I didn't find any examples as unique as Almut's use of the unpack function, do I understand its use thusly:

return - we want to return a value
map - we're going to use the map function to evaluate each array node
"AP" . join "." - I understand what this is doing, but I don't understand from any documentation what the first argument to map is, generally speaking (everything before the first comma)
unpack - I see from documentation that the capital 'A' for unpack refers to any ASCII character with its whitespace, but again I don't understand from documentation that you can add the ordinal and/or * along with it, and how that modifies the query
lc $_ - perform the lowercase operation on the current scalar/node of the array
@_ - Store the results to the unnamed array @_

If anyone has any additional comments and/or suggestions regarding my understanding, please feel free. In addition, any suggestions for comprehensive documentation is appreciated. I currently use search engines to find as many examples of a particular piece of code until it clicks with me and I understand it.

Regards, Scott

Replies are listed 'Best First'.
Re^3: Corrupt Data?
by massa (Hermit) on Jul 15, 2008 at 00:11 UTC
    I will (too) try to explain and detail almut's answer:
    my @mac_addrs = ("0015FAA3F03A", "0015FAA3F03B", "0015FAA3F03C"); sub convert { return map { "AP" . join ".", unpack "(A4)*", lc $_ } @_; } print "$_\n" for convert(@mac_addrs);
    Well:
    •  @answer = map { do_something_with("$_") } @array transforms one @array into another array @answer where each element of @answer is the result of the transform do_something_with(). Try this:
      $ perl -le '@a = (2, 3, 4, 5); @b = map { 2 * $_ } @a; print for @b' 4 6 8 10
      Notice that @b has each of the elements of @a, doubled. The result of the block given to map can be an array, too, so:
      $ perl -le '@a = (2, 3, 4, 5); @b = map { $_ % 2 ? () : ($_, $_ / 2) } + @a; print for @b' 2 1 4 2
      Notice that it printed the number and its half -- for the even numbers in @a.
    • So, let's try the knowledge of map:
      $ perl -le '@mac_addrs = ("0015FAA3F03A", "0015FAA3F03B", "0015FAA3F03 +C"); @a = map { lc $_ } @mac_addrs; print for @a' 0015faa3f03a 0015faa3f03b 0015faa3f03c
    • Now, let's add unpack"(A4)*" to the equation (unpack any number of groups of four alphanumeric chars):
      $ perl -le '@mac_addrs = ("0015FAA3F03A", "0015FAA3F03B", "0015FAA3F03 +C"); @a = map { unpack "(A4)*", lc $_ } @mac_addrs; print for @a' 0015 faa3 f03a 0015 faa3 f03b 0015 faa3 f03c
    • Now, let's join the parts with ".":
      $ perl -le '@mac_addrs = ("0015FAA3F03A", "0015FAA3F03B", "0015FAA3F03 +C"); @a = map { join ".", unpack "(A4)*", lc $_ } @mac_addrs; print f +or @a' 0015.faa3.f03a 0015.faa3.f03b 0015.faa3.f03c
    • And then, add the "AP" in the beginning:
      @mac_addrs = ("0015FAA3F03A", "0015FAA3F03B", "0015FAA3F03C"); @a = ma +p { "AP" . join ".", unpack "(A4)*", lc $_ } @mac_addrs; print for @a +' AP0015.faa3.f03a AP0015.faa3.f03b AP0015.faa3.f03c
    • voilą!! you already have your answer. Now, package everything in a neat subroutine:
      $ perl -le ' > use strict; > my @mac_addrs = ("0015FAA3F03A", "0015FAA3F03B", "0015FAA3F03C"); > sub convert { > map { "AP" . join ".", unpack "(A4)*", lc $_ } @_ > } > print for convert @mac_addrs > ' AP0015.faa3.f03a AP0015.faa3.f03b AP0015.faa3.f03c
    Got it?
    []s, HTH, Massa
Re^3: Corrupt Data?
by ikegami (Patriarch) on Jul 14, 2008 at 22:50 UTC

    The first argument of map is code executed for every other argument of map.

    print map uc($_), qw( a b c d ); # Prints ABCD print map { uc($_) } qw( a b c d ); # Same thing

    unpack '(A4)*', $val splits the value into as many 4 byte blocks as possible. I would have used "W" instead of "A", though. unpack '(W4)*', $val splits the value into as many 4 character blocks as possible.

    @_ is not unamed —its name is @_— and nothing is being stored in it —its contents are being passed to map.

    @_ holds the arguments of the current function (convert).

      I would have used "W" instead of "A"

      The reason I used "A" is because it works in older Perls, too, like 5.8.8.  "W" is available in 5.10 only.

        Then I wouldn't have used unpack. /(.{1,4})/sg would do the trick too.
        The point is moot (between "A" and "W") because splickles stated that the input consists of hexadecimal MAC addresses, that would be matched by either one of them.
        []s, HTH, Massa
        pack (from v5.10.0):
        W An unsigned char value (can be greater than 255).
Re^3: Corrupt Data?
by FunkyMonk (Bishop) on Jul 14, 2008 at 23:02 UTC
    "AP" . join "." - I understand what this is doing, but I don't understand from any documentation what the first argument to map is, generally speaking (everything before the first comma)
    map this, that will do this to each element of that, with $_ being aliased to each of the elements

    For example

    my @in = 1 .. 5; my @out = map $_ * 2, @in; # doubles each element of @in @out = map $_ * 2, 1 .. 5; # same thing - any list will do

    Unless I state otherwise, all my code runs with strict and warnings