fivemack: (spiky)
Tom Womack ([personal profile] fivemack) wrote2006-12-20 05:49 pm
Entry tags:

hair-tearing perl question

What I want: a subroutine footle such that, if you call footle(a,b) twice with the same a,b, it does nothing the second time

What I did:
use strict;
sub footle
{
  my ($a,$b,%done) = @_;
  my $concat = $a.$b;
  if ($done{$concat} == 0)
  {
    print "footling $a $b";
    $done{$concat} = 1;
  }
}

my %isdone = ();

footle("bootle","bumtrinket",%isdone);
footle("bootle","bumtrinket",%isdone);

But this doesn't work because parameters are passed by value.

But if I call as footle("bootle","bumtrinket",\%isdone), which passes isdone by reference, it still does the footling twice.

Even if I put $_[2]=%done before the end of the subroutine, it still does the footling twice.

And if I put print join "*",(keys %done); at the start of the subroutine, it says HASH(0x8188110)footling bootle bumtrinket

So how do I really pass the parameter by reference, as if I'd said void footle(int a, int b, set<string>& done) in C++?

Re: closure

[identity profile] fivemack.livejournal.com 2006-12-21 12:40 am (UTC)(link)
Cool, I didn't know about that feature. I'm not sure whether extensions to my program might want to see %done more explicitly, so I don't think I'll do it that way, but it's a really nifty trick!

[in my app, $a and $b are element symbols, so I use $a."-".$b as the hash key and the suffix/prefix issue doesn't arise]

Re: closure

[identity profile] tau-iota-mu-c.livejournal.com 2006-12-21 02:21 am (UTC)(link)
Except if you call with:

("foo-bar", "quux") vs ("foo", "bar-quux").

I'm just succeeding in getting my own head around perl objects (POOP == best programming paradigm name EVAR!), and I just looked through my code to find the single worst line I could find (I'm sure there's more).

my $x_err = $pivot[$i]->{its}[-1]->x_err;

Calling a method of an object which returns a (reference to? I can't remember) array, which is then indexed to get the last element, which is in turn an object, so we call a method to obtain a value from it.