Re: Safe list assignment

[email protected] ("Chas. Owens")
Newsgroups perl.beginners
Message-ID <[email protected]>
On Tue, May 27, 2008 at 6:00 AM, Ed Avis <[email protected]> wrote:
> Perl's list assignment feature is very useful.
>
>    sub returns_three_things { return (1, 2, 3) }
>    my ($x, $y, $z) = returns_three_things();
>
> Often, though, you want to add some error checking.  Particularly when providing
> an interface that others can call.
>
>    # Parameters: first name, last name, birthday.
>    sub print_person_details {
>       croak 'pass three arguments' if @_ != 3;
>       my ($first_name, $last_name, $birthday) = @_;
>       say "$first_name $last_name was born on $birthday";
>    }
>
> The extra 'croak' test gives a more friendly error message than 'use of
> uninitialized value in ...', which would require the user of the subroutine to
> go digging in its code to find what he passed wrongly.
>
> Even in code that's not part of a public interface, you may want to check that
> the list has the right size before you do the assignment, just to catch
> programmer mistakes early rather than waiting for an uninitialized value warning
> later on.
>
> But it's rather a pain to keep checking the list size each time.  When you
> 'unpack a tuple' in Python the size is checked and an exception is thrown if
> it's too big or too small.  Is there an equivalent in Perl?  Something like
>
>     safe_assign ($a, $b, $c) = @array;    # will die if scalar(@array) != 3
snip

Not that I am aware of, but it is a breeze to build one:

#!/usrbin/perl

use strict;
use warnings;

sub safe_assign {
	unless (@_) {
		my ($f, $l) = (caller)[1,2];
		die "bad number of arguments to safe_assign at $f line $l.\n";
	}
	my $targets = shift;

	my $expected = @$targets;
	my $got      = @_;
	unless ($expected == $got) {
		my ($f, $l) = (caller(1))[1,2];
		die "bad number of arguments, exected $expected got $got at $f line $l.\n";
	}

	for my $target (@$targets) {
		$target = shift;
	}

	return @$targets;
}

sub test {
	safe_assign([my ($one, $two, $three)], @_);
}

sub test2 {
	safe_assign();
}

for my $i (0 .. 4) {
	my @args = 1 .. $i;
	eval { test(@args) };
	print "args were: (@args)\nerror was: $@\n" if $@;
}
test2();

}
-- 
Chas. Owens
wonkden.net
The most important skill a programmer can have is the ability to read.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.