Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

Triple Tech posted:

Be careful of using || as the "default" operator. What you really want is "defined-or" which was introduced in 5.10 as // (they lean).

Careful cuz you know why, right? truthiness of zero


That actually solves a problem for me (in the cases where I could conceive of someone passing 0, I was checking manually which was trash), guess I can put a big fat using 5.10.0 up above my includes now



e: :monar:

Adbot
ADBOT LOVES YOU

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Erasmus Darwin posted:

What you want here is to use \%little_hash instead of just %little_hash. With the slash there, $daddy_hash{little_hash} will contain a hash reference to %little_hash. Without the \, the contents of %little_hash get flattened into the list being used to define %daddy_hash, which throws things off since you've effectively doing this:
code:
%daddy_hash = ("little_hash", "foo",
               0, "bar",
               0, "thing_1",
               0, "thing_2",
               0);
And that's just all sorts of screwed up. I'm not sure exactly how Perl would handle this since you've got a bunch of repeat assignments to the 0 key, and you've got a mismatched key at the end.

I think Triple Tech tried to point this out with his "oh snap" comment, but I'm not sure he fully understood the degree of your misunderstanding. Or maybe I've misunderstood.

Also, if you use the \ notion, you need to be aware that a reference to %little_hash points to the same memory that %little_hash uses -- it's not a copy. So if you do '$little_hash{blahblah} = 7' after creating %daddy_hash, it'll still modify the contents of the hash in $daddy_hash{little_hash}. Of course once your function exits, there won't be a reference to %little_hash anymore, so you no longer have to worry about it being modified via things not directly accessing the contents of %daddy_hash (unless you pass the reference somewhere else).

Finally, Data::Dumper is your friend for testing various data structures. Just throw "use Data::Dumper;" at the beginning of your program and then stick "print Dumper(\%test);" at the end, and it'll print a nice, readable representation of what your data structure looks like.

So once the function exits, the data from %little_hash will still be there, but the original reference "%little_hash" won't be? Will it still be a hash? Or did it transmute into something else? What I'm really looking for is a way to put a hash into another one, so yeah, nested hashes.

Erasmus Darwin
Mar 6, 2001

Captain Frigate posted:

So once the function exits, the data from %little_hash will still be there, but the original reference "%little_hash" won't be?

Correct. As long as there's a reference to the hash data (in this case via $test{little_hash}), Perl will keep the data around. That's the magic of garbage collection.

quote:

Will it still be a hash?

For the most part, yes. Technically, $test{little_hash} is a hash reference rather than a hash. That's actually a special scalar value that gets dereferenced (via the -> or % operators) to get at the underlying hash structure. However, the dereferencing is sometimes implicit since Perl knows that a nested structure has to be a reference (since that's the only way to stick an array or hash within another array or hash).

And to cut through that confusing bit of text, here are some examples:

code:
my %test = make_hashes(); # From before.
my $hashref = $test{little_hash};
print $hashref, "\t", ref($hashref); # Prints: HASH(0x1231232)       HASH
print $hashref->{foo}; # Prints: 0
print $test{little_hash}->{foo}; # Prints: 0
print $test{little_hash}{foo}; # Prints: 0 -- Note that -> was implied.
my %newhash = %$hashref; # %newhash is now a copy of little_hash's contents.
Note that at the end of this code, $test{little_hash} and $hashref both refer to the same hash in memory while %newhash is just a copy. So if you were to change $hashref->{foo} to 5, it'd also change in $test{little_hash}, but it wouldn't change in %newhash.

quote:

What I'm really looking for is a way to put a hash into another one, so yeah, nested hashes.

In addition to using a reference to a hash variable (i.e. when we did \%little_hash back in the make_hashes function), you can also create anonymous hash references with brackets { }. For example:

my %test = ( little_hash => { foo => 0, bar => 0 }, thing_1 => 0, thing_2 => 0 );

(Note that parentheses are used for the outer enclosing punctuation and brackets are used for the subhash.)

Also, I'd recommend taking a look at the perlref, perllol, and perldsc manpages. They're a little on the dense side, and they'll cover some stuff that's likely to make your eyes glaze over, but they do cover the whole mess in detail. It's not a bad system once you're used to it (especially if you've got experience in dealing with pointers in other languages), but it does take a bit for it to all sink in.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
So, ultimately, what I have looks like this:

code:
sub make_hashes {
  my %little_hash = qw(foo 0 bar 0);

  my %daddy_hash = (
    little_hash => \%little_hash,   
    thing_1     => 0,
    thing_2     => 0,
  );

  return %daddy_hash;
}

my %test = makes_hashes;

So I can access the smaller hash with something like
code:
$false_thing=%test{little_hash}{foo};
?

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Pretty much...

Erasmus Darwin
Mar 6, 2001
Close. You want a dollar-sign in front of test, not a percent. So it's:
$false_thing=$test{little_hash}{foo};

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Erasmus Darwin posted:

Close. You want a dollar-sign in front of test, not a percent. So it's:
$false_thing=$test{little_hash}{foo};

Great, thanks.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
Wait, one more small question: if I set up the hash that way, do I still have to put the key in quotes?

EDIT: Do I have to make any changes if I want to make one of the members an array?

Captain Frigate fucked around with this message at 19:52 on Aug 11, 2009

Erasmus Darwin
Mar 6, 2001

Captain Frigate posted:

Wait, one more small question: if I set up the hash that way, do I still have to put the key in quotes?

Perl generally lets you omit the quotes around a hash key when it's inside braces like that. That works with any hash -- you don't need a special setup to do that. However, depending on what sort of symbols you've got in the key, you might have to use quotes. For example, if you've got spaces in there, you'll need to quote it.

quote:

EDIT: Do I have to make any changes if I want to make one of the members an array?

Nope. It works the same way. The only difference would be using \@litte_array instead of \%little_hash. Or, if you go the anonymous route, use brackets [] instead of braces {}.

Ninja Rope
Oct 22, 2005

Wee.

Erasmus Darwin posted:

Close. You want a dollar-sign in front of test, not a percent. So it's:
$false_thing=$test{little_hash}{foo};

Older versions of ActivePerl were buggy when using this syntax (referencing nested hashes without the arrow operator). Because of that, and the inconsistent (to new developers) quoting rules for hash keys, I find it's better to write $false_thing = $test{'little_hash'}->{'foo'}, though it may never matter for you.

Roseo
Jun 1, 2000
Forum Veteran
To answer the original namespaces in perl bit, now that you've got a better understanding of references, the rule of thumb is that anything passed into a subroutine or function via arguments or passed out via returns is done so as a straight list of scalars. Since perl will automatically try to convert these lists into whatever context you try using them in, you need to watch how you pass variables.

For example, this will not work as you might expect:

code:

sub make_two_hashes {
  my %hash1 = ( 'foo' => 'bar',
                'baz' => 'qux',
              );

  my %hash2 = ( 'one'   => 1,
                'two'   => 2,
                'three' => 3,
              );   
  return %hash1, hash2;
}

my (%firsthash, %secondhash) = make_two_hashes();

The reason for this is that %firsthash will take all of the scalars passed out of the function, and use them to make a hash with the keys 'foo', 'baz', 'one', 'two', and 'three. Because of this, it's bet to get into the habit of passing arrays and hashes by reference into functions. Thus, you'd return references:

code:
return \%hash1, \%hash2;
And store the results in scalars, dereferencing them to get at the contents.

code:
my ($firsthash, $secondhash) = make_two_hashes();

say $firsthash->{'foo'}    # bar
say $secondhash->{'two'}   # 2

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Roseo posted:

To answer the original namespaces in perl bit, now that you've got a better understanding of references, the rule of thumb is that anything passed into a subroutine or function via arguments or passed out via returns is done so as a straight list of scalars. Since perl will automatically try to convert these lists into whatever context you try using them in, you need to watch how you pass variables.

For example, this will not work as you might expect:

code:

sub make_two_hashes {
  my %hash1 = ( 'foo' => 'bar',
                'baz' => 'qux',
              );

  my %hash2 = ( 'one'   => 1,
                'two'   => 2,
                'three' => 3,
              );   
  return %hash1, hash2;
}

my (%firsthash, %secondhash) = make_two_hashes();

The reason for this is that %firsthash will take all of the scalars passed out of the function, and use them to make a hash with the keys 'foo', 'baz', 'one', 'two', and 'three. Because of this, it's bet to get into the habit of passing arrays and hashes by reference into functions. Thus, you'd return references:

code:
return \%hash1, \%hash2;
And store the results in scalars, dereferencing them to get at the contents.

code:
my ($firsthash, $secondhash) = make_two_hashes();

say $firsthash->{'foo'}    # bar
say $secondhash->{'two'}   # 2

Does this hold when I'm doing the opposite process, i.e. sending a hash to a function to either operate on it or print it out or something?

Edit: Is there a way to just straight up dereferencing a hash reference into another hash? Or would I have to go element by element?

Double Edit: Or would that just be:
code:
%hash=%{$href}; 
?

Captain Frigate fucked around with this message at 15:59 on Aug 14, 2009

Roseo
Jun 1, 2000
Forum Veteran

Captain Frigate posted:

Does this hold when I'm doing the opposite process, i.e. sending a hash to a function to either operate on it or print it out or something?

Yep. If you're sending one hash or one array, it won't be a problem. But sending two will combine them, perhaaps messily. And trying to assign a scalar after a hash would be an issue:

code:

my_sub(%hash,$arg2,$arg3);   # might break, you get $hash{$arg2} == $arg3 in the sub and 
                             # $arg2, $arg3 being undef when you read @_. However, you can
                             # use this to append or overwrite the hash at the time of 
                             # calling the sub, as the last input takes priority for defining 
                             # the value associated with the key.

my_sub($arg2,$arg3,%hash);   # lets you read the values in with my($arg2,$arg3,%hash) = @_;

quote:

Edit: Is there a way to just straight up dereferencing a hash reference into another hash? Or would I have to go element by element?

Double Edit: Or would that just be:
code:
%hash=%{$href}; 
?

I believe that works, but I usually use %hash = %$href; when I HAVE to have an actual hash instead of an href. Dereferencing it is easy enough, though, so I usually don't bother.

If it helps, http://www.perlmeme.org/howtos/using_perl/dereferencing.html is a decent reference on deref syntax.

Roseo fucked around with this message at 18:52 on Aug 14, 2009

S133460
Mar 17, 2008
hello

Captain Frigate posted:

Edit: Is there a way to just straight up dereferencing a hash reference into another hash? Or would I have to go element by element?

Double Edit: Or would that just be:
code:
%hash=%{$href}; 

Right, you are dereferencing $href to a hash, which evaluates in a list context. Since evaluating %hash supplies a list context, the assignment is a list assignment. Try this out...

code:
$scalar = %{$href};
%hash   = %{$href};
@array  = %{$href};
@array  = scalar %{$href};
Perl always evaluates an expression in either "scalar context" or "list context". Above, the first line is executed in scalar context because the left side of the assignment operator is a scalar. The left side "wants" a scalar. The other lines use list context assignment because of the expression on the left side. By evaluating @array, Perl knows it "wants" a list as a result of the assignment (and internally chooses a completely different C function to do the assignment than if it were scalar assignment!).

It is also important to understand what a scalar is and what a list is. A scalar is Perl's data structure for holding an opaque thing. A scalar's "thing" can be a string, a number, or a reference to another thing*. A scalar is one thing. A list is a stack of one or more scalars**. A list has no value. Here are examples of expressions that result in scalars:

code:
$foo;    # obviously a scalar
1;       # also a scalar
"one";   # ditto
\@bar;   # scalar whose "thing" is a ref to a array
\%buz;   # scalar whose "thing" is a ref to a hash
\&bam;   # scalar whose "thing" is a code reference
undef;   # basically, a "null scalar", or a scalar with no thing
The next thing you need to know is that an array and a hash and a list are different things. Like scalars, arrays and hashes are actual Perl data structures (called SV/AV/HV internally). A list is not a data structure.

code:
@bar;        # evaluate array in list context
%bar;        # evaluate hash in list context
%{$href};    # deref $href, evaluate hash in list context
1,2,3;       # evaluate 3 scalars in list context
(1,2,3);     # ditto
undef, undef # also list context!
Context is crucial to understanding Perl. For example:

code:
@colors = qw/blue red green/;
print "colors: " . @colors . "\n";
print "colors: ", @colors, "\n";
print "colors: " . scalar @colors . "\n";
See if you can figure out why these three lines don't print the same thing. Context!

S133460 fucked around with this message at 14:43 on Aug 15, 2009

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
Alright, one final question about hashes and functions:
If I have one function which returns a reference to a small hash, that I might want to use in other hashes, which also are generated by functions, would it look like this?

code:
sub foo {
     my(input_1, input2) = @_;
     %hash_1 = (
          field_1 => input_1,
          field_2 => input_2
     );
     return \%hash_1;
}

sub bar {
     $temp = foo(1,2);
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1 => %{$temp}
     );
     return \%hash_2;
}

$href = bar();
%hash = %{$href};
while (($key,$value) = each %hash) {
     print "$key => $value";
}

Captain Frigate fucked around with this message at 19:54 on Aug 17, 2009

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
We don't say pointer, we say reference.

You don't have to copy the hash to "talk to it". You can just drop it in place, but make sure to dereference it.

code:
while ( my($key, $value) = each %$hash_ref ) {
  say "$key => $value";
}

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Triple Tech posted:

We don't say pointer, we say reference.

You don't have to copy the hash to "talk to it". You can just drop it in place, but make sure to dereference it.

code:
while ( my($key, $value) = each %$hash_ref ) {
  say "$key => $value";
}

Haha, my bad. My origins are showing through, and as I said earlier, I am completely new to perl as of about a month and a half ago. Anyway, as long as the above works like I would think, I thank you all for all of your help, but I can't promise that I won't be back in the future ;)

Erasmus Darwin
Mar 6, 2001

Captain Frigate posted:

code:
sub foo {
     my(input_1, input2) = @_;
     %hash_1 = (
          field_1 => input_1,
          field_2 => input_2
     );
     return \%hash_1;
}

This is fine, except for some minor syntax errors (missing dollar signs in front of input_1 and input_2, and a missing underscore in input_2 in the 'my' statement). But your understanding of what's going on seems fine.

quote:

code:
sub bar {
     $temp = foo(1,2);
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1 => %{$temp}
     );
     return \%hash_2;
}

First, "%{$temp}" can be written as "%$temp" since the "{}" in this case are just acting like parentheses (i.e. controlling order of operation) with regard to how Perl processes the data type.

Second, "%$temp" (and the equivalent "%{$temp}") is incorrect anyway because you need a hash reference as the value to store in the hash. So you just want "$temp". (Or, if you were crazy, you could do "\%$temp".)

Roseo
Jun 1, 2000
Forum Veteran

Captain Frigate posted:

Alright, one final question about hashes and functions:
If I have one function which returns a reference to a small hash, that I might want to use in other hashes, which also are generated by functions, would it look like this?

code:
sub foo {
     my(input_1, input2) = @_;
     %hash_1 = (
          field_1 => input_1,
          field_2 => input_2
     );
     return \%hash_1;
}

sub bar {
     $temp = foo(1,2);
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1 => %{$temp}
     );
     return \%hash_2;
}

$href = bar();
%hash = %{$href};
while (($key,$value) = each %hash) {
     print "$key => $value";
}


Not quite. You shouldn't be dereferencing $temp in bar(). Doing so expands it to a list when used in hash assignment context, so:

code:
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1 => %{$temp}
      };
expands to:


code:
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1  => field_1,
          input_1 => field_2,
          input_2
      };
Hashes store scalars, nothing else. To store a hash inside another hash, you need to store a scalar, or a reference to that hash.

You should be doing this instead:

code:
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1 => $temp
      };
or even simpler,

code:
     %hash_2 = (
          field_1 => 3,
          field_2 => 4,
          hash_1 => foo(1,2)
      };
Edit: Beaten handily; ah well.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
Ok, so then since the hash can only store the scalar, I have to dereference the reference whenever I want to access parts of it, right?

So would I use:

code:
%hash{hash_1}->{input_1};
to access the data there?

Roseo
Jun 1, 2000
Forum Veteran
right, but the -> is implied between key blocks.

code:
my %users = ( 'jdoe' => { 'email' => 'jdoe@example.com,
                          'pw'    => 'foobar',
                        },
            );

say $users{'jdoe'}{'email'};    # 'jdoe@example.com'
$users{'jdoe'} contains a href to the anonymous hash with 'email' and 'pw' keys. But to access the nested hashes, I just keep piling keys on.

Edit: Never use % when you want a scalar back. To access individual daya, use a scalar sigil. You'd use a hash in something like:

my %user_data = %{$users{'jdoe'}};

which would dereference the scalar at $users{'jdoe'} and assign the hash there to %user_data, containing 'email' and 'pw' keys that could then be accessed with:

$user_data{'email'};

Roseo fucked around with this message at 21:45 on Aug 17, 2009

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Roseo posted:

right, but the -> is implied between key blocks.

code:
my %users = ( 'jdoe' => { 'email' => 'jdoe@example.com,
                          'pw'    => 'foobar',
                        },
            );

say $users{'jdoe'}{'email'};    # 'jdoe@example.com'
$users{'jdoe'} contains a href to the anonymous hash with 'email' and 'pw' keys. But to access the nested hashes, I just keep piling keys on.

Edit: Never use % when you want a scalar back. To access individual daya, use a scalar sigil. You'd use a hash in something like:

my %user_data = %{$users{'jdoe'}};

which would dereference the scalar at $users{'jdoe'} and assign the hash there to %user_data, containing 'email' and 'pw' keys that could then be accessed with:

$user_data{'email'};

Ok, great. I think I've got it.

checkeredshawn
Jul 16, 2007

This is a stupid question that I figured I'd ask here because cowsay is written in Perl. A while ago I was goofing around with cowsay and I got to the point where I had a cow on the screen updating constantly saying the most recent line of a certain server log. I forget how I did this, and it's driving me crazy. I thought it was something as simple as `tail -f logfile | cowsay` but that isn't working. Does anyone know how I might've done this?

Vanadium
Jan 8, 2005

Does tail -f logfile | xargs -n 1 cowsay work?

checkeredshawn
Jul 16, 2007

Vanadium posted:

Does tail -f logfile | xargs -n 1 cowsay work?

It does, but I seem to remember it just being one cow and the text inside the bubble changing. Maybe I made a shell script or something that was like


while true; do
tail -n 1 logfile | cowsay;
sleep 3;
clear;
done;


edit: fixed typo

checkeredshawn fucked around with this message at 18:34 on Aug 19, 2009

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
This works a little nicer, it leaves each message on screen for at least one second and leaves it there until another arrives:
code:
tail -n1 -F /var/log/syslog | (while read line; do clear; echo $line | cowsay; sleep 1; done)

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
On a system that doesn't support 64 bit ints ("Q" and "q" aren't valid pack templates), how would you write one to a file? I ask this because if I just try:
code:
$packed_number = pack("h16",$bignumber);
I end up with a number that's been zero padded on the right. Does anyone know why that is? I guess an alternative is something like this:

code:
$bignumber = 2**45 #for example

if($bignumber > 2**(64-(8*1))) {
    $packed_number = pack("h16",$bignumber);
}elsif($bignumber > 2**(64-(8*2))) {
    $packed_number = pack("h14",$bignumber);
}elsif($bignumber > 2**(64-(8*3))) {
    $packed_number = pack("h12",$bignumber);
}elsif($bignumber > 2**(64-(8*4))) {
    $packed_number = pack("h10",$bignumber);
}elsif($bignumber > 2**(64-(8*5))) {
    $packed_number = pack("h8",$bignumber);
}elsif($bignumber > 2**(64-(8*6))) {
    $packed_number = pack("h6",$bignumber);
}elsif($bignumber > 2**(64-(8*7))) {
    $packed_number = pack("h4",$bignumber);
}elsif($bignumber > 2**(64-(8*8))) {
    $packed_number = pack("h2",$bignumber);
}

print OUTPUT $packed_number;
but that's a bit of a mess. Any suggestions?

EDIT: I figure it would be easiest to just divide by powers of ten equal to the number of additional zeros, but I'm not sure how many zeros are likely to show up. I don't think it's padding equal up to enough digits to hold a 64-bit value, because I gave it 2**45 and I ended up with two zeros padded to the right (instead of six, if it were padding to hold a 64-bit value). Any insights?

Captain Frigate fucked around with this message at 22:00 on Aug 20, 2009

CanSpice
Jan 12, 2002

GO CANUCKS GO
I don't know if this belongs here or in the Coding Horrors thread, but I just discovered the ternary lvalue:
code:
$group ? $Group : $Frame = $Obj;

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
With parentheses, it's not so bad..

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
The only other way to achieve the same effect, without resorting to using a string eval, is with references and an if block of sorts, so it's definitely a bit more concise.

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
I don't know if you guys know this but branching in Perl actually takes a lot of time (since it's an interpreted language). The fastest, aka best, way to do this is:

code:
my @lvalues = \($Group, $Frame);
${$lvalues[!!$group]} = $Obj;

S133460
Mar 17, 2008
hello

Filburt Shellbache posted:

I don't know if you guys know this but branching in Perl actually takes a lot of time (since it's an interpreted language). The fastest, aka best, way to do this is:

code:
my @lvalues = \($Group, $Frame);
${$lvalues[!!$group]} = $Obj;

I'm not sure if that is true versus the conditional op as an lvalue. Perl speed is based on how many ops are performed, and I believe your code probably results in more ops than what CanSpice posted (because the ${} implies a scope op, there's an array access, !! is two ops, etc).

I'm usually wrong though. :)

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Captain Frigate posted:

I figure it would be easiest to just divide by powers of ten equal to the number of additional zeros, but I'm not sure how many zeros are likely to show up. I don't think it's padding equal up to enough digits to hold a 64-bit value, because I gave it 2**45 and I ended up with two zeros padded to the right (instead of six, if it were padding to hold a 64-bit value). Any insights?

Alternately, is there a way to use sprintf for numbers longer than the supported int size?

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

Captain Frigate posted:

Alternately, is there a way to use sprintf for numbers longer than the supported int size?
Not sure if that helps you, but you might want to have a look at bignum and bigrat. If you make use of them, be aware though that they'll slow your stuff the gently caress down.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Mithaldu posted:

Not sure if that helps you, but you might want to have a look at bignum and bigrat. If you make use of them, be aware though that they'll slow your stuff the gently caress down.

Is there a way to only use bignum ints after a certain point? Like, if I have a main loop that doesn't need them, but some minor calculations afterward that do, could I put the "use" statement after the main loop and have it not take a day to process my data?

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
Just do:

code:
# blorf here

use bignum;

# big number stuff here

no bignum;

# mārp here
Or whatever similar thing is appropiate. :)

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Mithaldu posted:

Just do:

code:
# blorf here

use bignum;

# big number stuff here

no bignum;

# mārp here
Or whatever similar thing is appropiate. :)

Oh neat, I didn't know about the "no" statement. Very nice. Thank you!

Erasmus Darwin
Mar 6, 2001
You can also use Math::BigInt and then just explicitly use a Math::BigInt object for the items that will hold large values.

Also, here's a quick and dirty attempt at emulating "pack('Q', $num)" using Math::BigInt. My morning coffee hasn't kicked in, and I made it work by comparing the binary representations and just fiddling with it until it matched, so I may have screwed something up. So standard disclaimers apply. Oh, and it's little endian only. Anyway, here's the code:

code:
#!/usr/bin/perl -w

use Math::BigInt;

$x = 0x12345678;

$goal = pack('Q', $x);

$big_num = new Math::BigInt($x);

$hex = $big_num->as_hex();

$hex =~ s/^0x//;

if (length($hex) < 16) {
    $hex = '0' x (16 - length($hex)) . $hex;
}

$attempt = reverse(pack('H*', $hex));

if ($attempt eq $goal) {
    print "Goal matched.\n";
} else {
    print "Failure.\n";
}

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Erasmus Darwin posted:

You can also use Math::BigInt and then just explicitly use a Math::BigInt object for the items that will hold large values.

Also, here's a quick and dirty attempt at emulating "pack('Q', $num)" using Math::BigInt. My morning coffee hasn't kicked in, and I made it work by comparing the binary representations and just fiddling with it until it matched, so I may have screwed something up. So standard disclaimers apply. Oh, and it's little endian only. Anyway, here's the code:

code:
#!/usr/bin/perl -w

use Math::BigInt;

$x = 0x12345678;

$goal = pack('Q', $x);

$big_num = new Math::BigInt($x);

$hex = $big_num->as_hex();

$hex =~ s/^0x//;

if (length($hex) < 16) {
    $hex = '0' x (16 - length($hex)) . $hex;
}

$attempt = reverse(pack('H*', $hex));

if ($attempt eq $goal) {
    print "Goal matched.\n";
} else {
    print "Failure.\n";
}

Yes, I remember someone (you?) suggesting something along these lines for getting around the my lack of "q" support a couple pages back, and I have been using this for a lot of my packing and unpacking needs. Also, it appears that I am a colossal idiot, because I forgot I was dealing with filesizes and was only getting issues with numbers larger than ~2**45, which is still larger than any file has any right to be.

Adbot
ADBOT LOVES YOU

Erasmus Darwin
Mar 6, 2001

Captain Frigate posted:

Yes, I remember someone (you?) suggesting something along these lines for getting around the my lack of "q" support a couple pages back, and I have been using this for a lot of my packing and unpacking needs.

Yep, that was me. I took a peek at my previous code and used it as a cheat sheet for getting this to work.

  • Locked thread