On Wed, 2002-10-09 at 03:10, Mike Stok wrote: 
> In article <1034037350.867.30.camel / awaji>, Tony Sloane wrote:
> >
> > I'm relatively new to Ruby so perhaps I'm missing something, but I can't
> > get Array's pack to work in the following situation:
> > 
> > irb(main):001:0> "%08b" % ["4","7"].pack ('HXh')[0]
> > "00000111"
> > 
> > I'm expecting to see "01000111".
> 
> What are you really trying to do?

I'm trying to get a numeric byte comprised of 4 in the high nibble and 7
in the low nibble.  The "%08b" etc is just there so we can see what I
get in an understandable format, not because I want a string. 

If I use H and h separately I get what I expect. 

irb(main):003:0> "%08b" % ["4"].pack ('H')[0] 
"01000000" 
irb(main):004:0> "%08b" % ["7"].pack ('h')[0] 
"00000111" 

It would seem that packing a low (high) nibble obliterates the high
(low) nibble as a side effect, so when I back up a byte to write the
second nibble I overwrite the first with zeros.  Packing the nibbles in
the other order seems to confirms this. 

irb(main):009:0> "%08b" % ["7","4"].pack ('hXH')[0] 
"01000000" 

Is this feature of pack deliberate? It would seem to make it impossible
to pack nibbles. 

> There are some ugly ways to get ['4', '7'] into a string of 1's and 0s:
> 
> irb(main):001:0> sprintf('%08b', Integer("0x" + ['4', '7'].join('')))
> "01000111"
> irb(main):002:0> '%08b' % [["4", "7"].join("")].pack('H*')[0]
> "01000111"
> irb(main):003:0> ['47'].pack('H*').unpack('B*')
> ["01000111"]

Yes, there are a number of uglier ways to do it and I'm using one at the
moment as a workaround.  I just hoped that the simple pack method would
work since it seems like it should be just the inverse of the unpack. 

> > Note that unpack seems to work the way I would expect.  (ASCII code for
> > 'G' is 01000111.)
> > 
> > irb(main):002:0> "G".unpack ('HXh')
> > ["4", "7"]
> 
> Depending on your context you may want to use H* as a template and split
> the resulting string e.g.
> 
> irb(main):005:0> "G".unpack('H*')
> ["47"]
> irb(main):006:0> 'banana'.unpack('H*')
> ["62616e616e61"]

For my application the unpack ('HXh') above works fine to pick the data
apart. 

> I hope that I'm not off on some wild tangent, and that this is of some
> use.

Thanks for taking the time to reply. 

Cheers,
Tony