Trouble in wantarray context

R

Ronald Fischer

Does someone have an elegant solution to the following problem?

Consider a function F which is supposed to do the following:

(1) Perform X()

(2) Perform Y(); Y returns a different result in array- or
scalar context. The result of Y should be returned as the
result of F (which hence is also sensitive to array- vs.
scalar context)

(3) Perform Z() (which may do some cleanup-work, which can be
done only after Y has been executed).

Under these premises, what is an elegant way to code F? Here is
one straightforward, but not-so-elegant solution:

sub F()
{
X();
if(wantarray)
{ my @result=Y(); Z(); @result }
else
{ my $result=Y(); Z(); $result }
}

This works, and might be acceptable in this simple case, but
it is a bit awkward, because Z() has be repeated in both
branches, and there are two exit points instead of one.

Maybe someone can improve on this?

Ronald
 
P

Paul Lalli

Ronald said:
Does someone have an elegant solution to the following problem?

Consider a function F which is supposed to do the following:

(1) Perform X()

(2) Perform Y(); Y returns a different result in array- or
scalar context. The result of Y should be returned as the
result of F (which hence is also sensitive to array- vs.
scalar context)

(3) Perform Z() (which may do some cleanup-work, which can be
done only after Y has been executed).

Under these premises, what is an elegant way to code F? Here is
one straightforward, but not-so-elegant solution:

sub F()
^^
Do you know what () does there? Do you want that functionality? If
not, eliminate them.
{
X();
if(wantarray)
{ my @result=Y(); Z(); @result }
else
{ my $result=Y(); Z(); $result }
}

This works, and might be acceptable in this simple case, but
it is a bit awkward, because Z() has be repeated in both
branches, and there are two exit points instead of one.

Maybe someone can improve on this?

How about this solution? The tradeoff is two calls to wantarray and
two if statements, but I think it looks neater...

sub F {
X();
my @result = wantarray ? Y() : scalar(Y());
Z();
wantarray ? @result : $result[0];
}

Paul Lalli
 
X

xhoster

Does someone have an elegant solution to the following problem?

Consider a function F which is supposed to do the following:

(1) Perform X()

(2) Perform Y(); Y returns a different result in array- or
scalar context. The result of Y should be returned as the
result of F (which hence is also sensitive to array- vs.
scalar context)

(3) Perform Z() (which may do some cleanup-work, which can be
done only after Y has been executed).

Under these premises, what is an elegant way to code F? Here is
one straightforward, but not-so-elegant solution:

sub F()
{
X();
if(wantarray)
{ my @result=Y(); Z(); @result }
else
{ my $result=Y(); Z(); $result }
}

This works, and might be acceptable in this simple case, but
it is a bit awkward, because Z() has be repeated in both
branches, and there are two exit points instead of one.

Maybe someone can improve on this?

warn "untested";
use AtExit;
sub F()
{
my $scope1 = AtExit->new(\&Z);
X();
return Y();
}

Xho
 
A

axel

Ronald Fischer said:
sub F()
{
X();
if(wantarray)
{ my @result=Y(); Z(); @result }
else
{ my $result=Y(); Z(); $result }
}
This works, and might be acceptable in this simple case, but
it is a bit awkward, because Z() has be repeated in both
branches, and there are two exit points instead of one.

But why change anything? In my opinion there seems a certain symmetry
which is obvious to anyone reading the code. Just because a call
to Z() is repeated is not a problem because it is only called once,
either way.

Clarity is better than obscurity, especially when it is clarity in
code whereas obscurity in code just to avoid repeating something
is pointless. (I better clarify that... using loops and so on is
not what I am talking about).

Axel
 
R

Ronald Fischer

Ronald Fischer said:
But why change anything? In my opinion there seems a certain symmetry
which is obvious to anyone reading the code. Just because a call
to Z() is repeated is not a problem because it is only called once,
either way.

For two reasons:

First, the actual terms in the places of Y() and Z() in my application
are not just parameterless function calls, but functions with parameters
(I just simplified it to make the structure clear). Repeating the
parameters in two places is error prone, especially if some of the
actual parameters are expressions. For example, would you still
consider the following variation as clear and, more important, as
easy to maintain?

if(wantarray)
{
my @result=Y($i+1); Z(f($t),2*$k-1)-1; @result }
else
{ my $result=Y($i+1); Z(f($t),2*$k-1); $result }

Second, I found that if you are dealing with wantarray functions,
that the above pattern emerges again and again, and my solution
really seemed to be too clumsy to be used repeatedly.

Ronald
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top