sub family_member { my @params = @_; my $brother = $params[0]; my $sister = $params[1]; my $mother = $params[2]; my $father = $params[3]; print "$father\n"; } # to tell who my father is, I'd have to: family_member( undef, undef, undef, undef, 'Larry', ); # now, imagine if you could use a function like # this instead: family_member({ father => 'Larry', }); # ...and even bundle your brothers together: my @brothers = qw( Jeremy Josh ); family_member({ father => 'Larry', brothers => \@brothers, }); # now, in the above array-style example, what if you # wanted to add an 'aunt' between 'brother' and 'sister'? # Your API would be horribly broken, along with your # current documentation. You'd forever be having your # users moving around undefs to deal with your changes. # With named refs, the only time your users feel a bite # is if you change what happens to a pre-named param: sub family_members( my $params = shift; my $brother = $params->{ brother }; my $sister = $params->{ sister }; my $mother = $params->{ mother }; my $father = $params->{ father }; # add an aunt my $aunt = $params->{ aunt }; # how 'bout grandparents my $grandpa = $params->{ grandpa }; if ( $father ) { return $father; } else { return "I don't have one\n"; } ) # then, you can throw at it what you want, and # get back what you expect: print family_member({ father => 'Larry' }); # ...or assign it: my $father = family_member({ father => 'Larry' });