Re: Values passed into a sub routine
by toolic (Bishop) on Apr 19, 2011 at 16:02 UTC
|
Since it looks like you will be modifying your module and all your calling programs, consider passing your values as a hash reference. This is a common practice. It has the benefits of scalability and order-independence. It would be more verbose, but that's a good thing because it would be passing parameters by name, and therefore more readable. See: Pass by Reference. Here is one CPAN module which shows this technique; you could look at its source code.
Also, there are parameter checking modules, such as Params::Validate and Params::Check (Core). | [reply] |
Re: Values passed into a sub routine
by Nikhil Jain (Monk) on Apr 19, 2011 at 16:01 UTC
|
build_url(account => "test",transaction => "test1", location => "India
+", fname => "Nikhil", lname => "jain");
build_url(account => "test", fname => "nikhil", lname => "jain");
build_url(account => "test" ,transaction => "test1", fname =>"nikhil",
+ lname => "jain");
sub build_url {
my (%args) = @_;
my $fname = $args{fname} || "Bob the Builder";
my $lname = $args{lname} || "none that we know";
}
| [reply] [d/l] |
|
|
This is the way to go imho.
Remove the $ in the parameter names though (so account => "test" instead of $account => "test")
I like this idiom:
sub build_url {
my %param = ( fname => "default value",
...,
@_
);
...
# do stuff with $param{account} etc.
}
| [reply] [d/l] [select] |
Re: Values passed into a sub routine
by ikegami (Patriarch) on Apr 19, 2011 at 16:03 UTC
|
If I follow, the syntaxcalling convention is
build_url($account, [ $transaction, [ $location, ] ] $fname, $lname);
where square brackets denote optional parameters. You could use
sub build_url {
my $lname = pop;
my $fname = pop;
my ($account, $transaction, $location) = @_;
...
}
or
sub build_url {
my $account = shift;
my $transaction = @_>=4 ? shift : undef;
my $locaton = @_>=3 ? shift : undef;
my $fname = shift;
my $lname = shift;
...
}
or
sub build_url {
splice(@_, 1, 0, (undef)x(5-@_))
my ($account ,$transaction, $location, $fname, $lname) = @_;
...
}
| [reply] [d/l] [select] |
|
|
I like this way as you stated, but:
build_url( $account,[$fname], [$lname]);
sub build_url {
my $lname = pop;
my $fname = pop;
print "$lname and $fname\n";
my ($account ,$transaction, $location) = @_;
...
}
If a run this I am getting this:
Lname=ARRAY(0x8967f28) and Fname=ARRAY(0x8967748)
Any suggestion? Thanks!
| [reply] [d/l] |
|
|
build_url($account, $fname, $lname);
build_url($account, $transaction, $fname, $lname);
build_url($account, $transaction, $location, $fname, $lname);
If so, all three alternatives I provided should work. | [reply] [d/l] |
|
|
build_url(
account => $account,
fname => $fname,
lname => $lname],
);
sub build_url {
my (%args) = @_;
my $account = $args{account} || '';
my $fname = $args{fname} || '';
my $lname = $args{lname} || '';
my $other = $args{other} ||'';
...
}
There, it should prevent it to be out of order right? | [reply] [d/l] |
Re: Values passed into a sub routine
by wallisds (Beadle) on Apr 19, 2011 at 15:59 UTC
|
In my opinion the answer to your question is 'yes'. At least that's what I'd do. I'd probably just pass 0 through... In the sub I would then check for the value before proceeding.
From program A:
build_url( $account ,$transaction, $location, $fname, $lname);
From program B:
build_url( $account, 0, 0, $fname, $lname);
From program C:
build_url( $account, $transaction, 0, $fname, $lname);
From program D:
build_url( $account ,$transaction, $location, $fname, $lname);
sub build_url
{
my ($account ,$transaction, $location, $fname, $lname) = @_;
if ($location) { ... do what you would do ... }#example
}
| [reply] [d/l] [select] |
|
|
What if '0' is valid for one of the entries?!? Better to use 'undef' instead. And even better would be to just pass a hash reference in (or use named parameters).
Elda Taluta; Sarks Sark; Ark Arks
| [reply] |
|
|
Thanks Argel!
I appreciate what you have posted and I see your point. I think using undef makes sense when used also with 'defined', but here's my reasoning behind my original suggestion...
The question was:
"Should I make sure that I always pass 5 expected values to this sub routine even if I have to pass blank values, but preserving the order that the code is expecting them?"
The answer is yes to that question if the person asking is going to continue to use a list array method. I think Undef is only safer than 0 if you use 'defined' to check it, otherwise it's the same as 0, '', '0', right? At least that's what I got out of this perldoc:
http://perldoc.perl.org/functions/defined.html
Also, I thought 0 would be alright in this scenario based on what I interpreted the expected values to contain, but then again, it would be a mistake to assume data would be entered in any expected format, especially if it is coming in from a form.
If we don't use a hash this is a better solution:
build_url( $account, $transaction, undef, $fname, $lname);
sub build_url() {
... etc...
if (defined($location)) {
... stuff ...
}
}
Thanks! Dawn | [reply] [d/l] [select] |
|
|
|
|
Re: Values passed into a sub routine
by lostjimmy (Chaplain) on Apr 19, 2011 at 18:28 UTC
|
As Nikhil Jain and toolic have said, named parameters are a great way to go. On the other hand, since I'm a C++ programming by trade, I'm inclined to just put the optional parameters at the end of the list instead of in the middle. That way you only have to check if they are undef and clients don't have to worry about putting in placeholders. | [reply] [d/l] |
Re: Values passed into a sub routine
by patcat88 (Deacon) on Apr 20, 2011 at 00:29 UTC
|
you can also have the first parameter control whether to interpret the rest of @_ as @_ or $_[0] as a hashref, for example,
sub func {
my($param1, $param2, $param3) = @_;
my $tempparam1;
if(ref($param1) eq "HASH") {
$tempparam1 = $param1->{'param1'};
$param2 = $param1->{'param2'};
$param3 = $param1->{'param3'};
$param1 = $tempparam1;
}
print "param1 is $param1 param2 is $param2 param3 is $param3 \n";
}
func( 'one', 'two', 'three');
func( {param1 => 'one', param2 => 'two', param3 => 'three'});
I've seen the above in Perl. Offers users TIMTOWTDI. | [reply] [d/l] |