Lindsey Kuper (lindseykuper) wrote,
Lindsey Kuper
lindseykuper

I'm not a beginner...

I just make mistakes like one.

So, suppose you've got an object, like this, with some stuff in it:

my $example_object = {
          'key1' => 'foo',
          'key2' => 'bar',
        };

Let's say you want to write a function that'll make a new object just like the first one, but with a couple of the values changed, like this:

sub changeObject {
	my ($obj) = @_;
	
	my $new_obj = $obj;

	$new_obj->{key1} = 'baz';
	$new_obj->{key2} = 'quux';

	logChange($obj, $new_obj);
	
	return $new_obj;
}

Say logChange() is a function that compares its arguments $obj and $new_obj and prints a useful message if they're different, like this:

sub logChange { 
	my ($obj, $new_obj) = @_;
	
	foreach (keys %$obj) {
	      if ($obj->{$_} ne $new_obj->{$_}) {
	            print STDOUT "$obj->{$_} was changed to $new_obj->{$_}\n";
	      }
	}
}

(I know some of you are nodding knowingly right about now.) At this point, you ought to be able to call changeObject($example_object); and it should tell you something like

bar was changed to quux
foo was changed to baz

, because that's what you changed them to. Right?

Wrong! Can you spot the mistake? If it takes you less than an hour, you're doing better than I did:

The problem is that $new_obj and $obj are both just pointers to an anonymous hash. You changed the values in the hash that $new_obj points to, but $obj is pointing to the same one. So comparing $obj and $new_obj won't help you.

Instead, you have to dereference $obj and instantiate a new hash:

sub changeObject {
	my ($obj) = @_;
	
	# gaaaaaaaaaaahhhh.
	my %new_obj = %$obj;
	my $new_obj = \%new_obj;
	
	$new_obj->{key1} = 'baz';
	$new_obj->{key2} = 'quux';

	logChange($obj, $new_obj);
	
	return $new_obj;
}

And now you get the log message you're looking for!

bar was changed to quux
foo was changed to baz

This problem stumped me for way too long today. I just couldn't figure out how the change could be happening and not be getting logged. The real code was more involved than this, but not by much.

On the plus side, I think I finally and suddenly understand pointers. I wish this could've happened, oh, four years ago, but I'll take what I can get.

Hi ho.

Now I think I will finish my coffee and go rumble. Yay!

Tags: programming
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 25 comments