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

is there a simpler way to do the following: my $dqsel = unpack("I",pack("B*",join('',@exclude)));
exclude is an array of 32 0/1 values which needs to be turned into an unsigned integer to be passed as an argument to a C program. It works, but it feels ugly...

Replies are listed 'Best First'.
Re: unpack(pack(join simplification
by Anonymous Monk on Jul 04, 2007 at 14:23 UTC
    don't know if this is simpler or less ugly, but...

    C:\@Work\Perl>perl -we "print oct do { local $\" = ''; qq(0b@ARGV) }" 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2147483648 C:\@Work\Perl>perl -we "print oct do { local $\" = ''; qq(0b@ARGV) }" 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2147483647 C:\@Work\Perl>perl -we "print oct do { local $\" = ''; qq(0b@ARGV) }" 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2147483649 C:\@Work\Perl>perl -we "print oct do { local $\" = ''; qq(0b@ARGV) }" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 C:\@Work\Perl>perl -we "print oct do { local $\" = ''; qq(0b@ARGV) }" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

      Good idea to use oct(), but $" is deprecated; use join() instead.

      sub binary_array_to_uint { my $bin = join '', @_; return oct "0b$bin"; }
      perl -wlane 'print oct( "0b" . join( "", @F ) );' <<END 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 END
      Output: 2147483648 2147483647 2147483649 1 0

        Good idea to use oct(), but $" is deprecated; use join() instead.

        Fully agreeing on the use of join (in this case) instead of $", but how is the latter deprecated?

Re: unpack(pack(join simplification
by ikegami (Patriarch) on Jul 05, 2007 at 06:00 UTC
    my $dqsel = bin2dec(join '', @exclude);

    would be less ugly. Just define bin2dec appropriately, such as:

    sub bin2dec { my ($bin) = @_; return unpack("N", pack("B32", substr("0" x 32 . $bin, -32))); }
Re: unpack(pack(join simplification
by graff (Chancellor) on Jul 04, 2007 at 21:15 UTC
    Well, I guess I don't share your sense of esthetics -- I see no ugliness in that approach, just a usage that is "idiomatic" (and probably quite efficient) Perl coding, as opposed to being "conventional". But if being conventional makes you feel less "ugly", there's the more C-like method (but not abandoning Perlishness entirely):
    $dqsel = 0; my @a = reverse @exclude; $dqsel += $a[$_]<<$_ for(0..$#a);
    (I'm hoping I got the directionality right...)
Re: unpack(pack(join simplification
by blazar (Canon) on Jul 04, 2007 at 21:37 UTC
    is there a simpler way to do the following: my $dqsel = unpack("I",pack("B*",join('',@exclude)));

    Well, other than the other cool answers you got, you could remove unnecessary parens:

    my $dqsel = unpack "I", pack "B*", join '', @exclude; # neater, aint' it?