Use of "return" in place of "last" (newbie question)?

M

Michael

I am new to perl, and I am wondering whether it is a bad thing to jump out
of a foreach loop with return. I have a function which searches for a
value in one of several arrays. If the value is found in any of them,
then the whole function may as well terminate. At the moment I am setting
a flag when the value is found, which stops execution of the later loops.
Would it be safe / stylistically sound to do away with the flag by using
"return" rather than "last". Example code follows.

TIA

sub example{

my $found;
$found = 0;

foreach $item (@list)
{
if ($value eq $item)
{
print ("found $value\n");
$found = 1;
last;
}
}

.... several other foreach loops follow in which the only thing which
differs is the name of the array which is "@list" above, and the test for
the flag.

return
}
 
T

Tad J McClellan

Michael said:
I am new to perl, and I am wondering whether it is a bad thing to jump out
of a foreach loop with return.


Yes it is a bad thing, because it will not work. :)

I have a function which searches for a
value in one of several arrays. If the value is found in any of them,
then the whole function may as well terminate.


Oh.

Using a return() to return from a subroutine is perfectly fine
(even if the return() is within a loop).

Would it be safe / stylistically sound to do away with the flag by using
"return" rather than "last".


Yes.
 
M

Michael

On Sun, 09 Mar 2008 10:16:08 -0500, Tad J McClellan wrote:
Using a return() to return from a subroutine is perfectly fine (even if
the return() is within a loop).


Yes.

Many thanks for the prompt and helpful response Tad.

/M
 
J

Jürgen Exner

Michael said:
I am new to perl, and I am wondering whether it is a bad thing to jump out
of a foreach loop with return.

Technically it doesn't make a difference.

Stylistically it is a matter of which programming philosophy you are
following. For GOTOists it is standard operating procedure, for functional
programmers it is a sacrilege. Others are somewhere in between.

jue
 
J

Joost Diepenmaat

Jürgen Exner said:
Technically it doesn't make a difference.

Stylistically it is a matter of which programming philosophy you are
following. For GOTOists it is standard operating procedure, for functional
programmers it is a sacrilege. Others are somewhere in between.

Functional programmers don't use foreach either :)

Personally, I think using a return statement generally leads to less
convoluted, clearer code.
 
M

Michael

Technically it doesn't make a difference.

Stylistically it is a matter of which programming philosophy you are
following. For GOTOists it is standard operating procedure, for
functional programmers it is a sacrilege. Others are somewhere in
between.

Thank-you.

Just as a matter of interest, so far as I could see, my technique of
setting a flag was the simplest way of maintaining the integrity of the
foreach (terminating it with "last" rather than jumping out of it with
"return"), whilst not wasting processor cycles performing irrelevant loops
later in the function. I am a newbie and don't know much - is there a
more elegant alternative which would satisfy the functional programmers?
 
J

Joost Diepenmaat

Michael said:
Thank-you.

Just as a matter of interest, so far as I could see, my technique of
setting a flag was the simplest way of maintaining the integrity of the
foreach (terminating it with "last" rather than jumping out of it with
"return"), whilst not wasting processor cycles performing irrelevant loops
later in the function. I am a newbie and don't know much - is there a
more elegant alternative which would satisfy the functional programmers?

There are more "elegant" (for some value of elegant) functional
alternatives , but perl's constructs don't really allow you to write
them as nicely as more functional programming languages do. For one,
perl's if { ... } else { ... } constructs aren't expressions, and also,
perl uses arrays instead of linked lists:

example in common lisp

(defun find-value (value list)
(and list
(if (string= value (first list))
value
(find-value (rest list)))))

(defun example
(or (find-value my-value my-list)
(find-value my-other-value my-other-list)))

Using these kind of recursive calls almost automatically
force you to break up your sample problem into 2 subs.

Also note that you can then re-use the find-value sub to reduce the
total amount of code.


same algorithm in perl.

sub find_value {
my ($value,@list) = @_;
if (@list) {
my $first = shift @list;
if ($first eq $value) {
return $first;
}
return find_value($value,@list);
}
return; # return false
}

sub example {
find_value($value,@list) or
find_value($other_value,@other_list);
}

note that you probably still want to use plenty of return()s
here.

also note: is is pretty inefficient if @list is long. you'd
generally write the find_value function using foreach(), and pass
the lists as array references.

ps: none of this code has been tested. YMMV.
 
J

Jürgen Exner

Just as a matter of interest, so far as I could see, my technique of
setting a flag was the simplest way of maintaining the integrity of the
foreach (terminating it with "last" rather than jumping out of it with
"return"), whilst not wasting processor cycles performing irrelevant loops
later in the function. I am a newbie and don't know much - is there a
more elegant alternative which would satisfy the functional programmers?

Well, doing strict functional programming in Perl is extremely hard anyway
because that't not how the language was designed.
But if you follow structured programming/formal programming/program
transformations/... then the condition under which the loop terminiates
should be defined in the condition of the loop. Neither last() nor return()
fits that bill because they exit the loop unexpectedly from somewhere in the
middle which is a nightmare for e.g. formal program verification.

Using tons of flags is the typical workaround by inexperienced programmers.
I have seen that literally hundreds of times in our university classes.
Unfortunately flags can easily lead to to convoluted and difficult to
maintain code because it can become very difficult to follow their logic and
to analyse where which flag is being set under what conditions.

Very often it takes just a little bit of restructuring of the loop to get a
clean and easy to understand single exit condition without bail-outs in the
middle. One approach that works often is to rearrange the exection sequence
in the loop and/or reduce the loop by one iteration by moving some
initialization code before the loop:

Generic example:
while (cond_x) {
do_some_work();
if (cond_y) {last};
do_more_work();
}

can usually be transformed into something like
do__prep_work(); #includes do_some_work() for first iteration
while (cond_x and not cond_y) {
do_more_work();
do_some_work();
}

jue



IMO the better app
 
M

Michael

On Sun, 09 Mar 2008 19:49:41 +0000, Jürgen Exner wrote:
Well, doing strict functional programming in Perl is extremely hard
anyway because that't not how the language was designed. But if you
follow structured programming/formal programming/program
transformations/... then the condition under which the loop terminiates
should be defined in the condition of the loop. Neither last() nor
return() fits that bill because they exit the loop unexpectedly from
somewhere in the middle which is a nightmare for e.g. formal program
verification.

Using tons of flags is the typical workaround by inexperienced
programmers. I have seen that literally hundreds of times in our
university classes. Unfortunately flags can easily lead to to convoluted
and difficult to maintain code because it can become very difficult to
follow their logic and to analyse where which flag is being set under
what conditions.

Very often it takes just a little bit of restructuring of the loop to
get a clean and easy to understand single exit condition without
bail-outs in the middle. One approach that works often is to rearrange
the exection sequence in the loop and/or reduce the loop by one
iteration by moving some initialization code before the loop:

Generic example:
while (cond_x) {
do_some_work();
if (cond_y) {last};
do_more_work();
}

can usually be transformed into something like
do__prep_work(); #includes do_some_work() for first iteration while
(cond_x and not cond_y) {
do_more_work();
do_some_work();
}

Thank-you very much for taking the time to write so helpfully Jue.

/M
 
M

Michael

On Sun, 09 Mar 2008 18:56:51 +0100, Joost Diepenmaat wrote:

There are more "elegant" (for some value of elegant) functional
alternatives , but perl's constructs don't really allow you to write
them as nicely as more functional programming languages do. For one,
perl's if { ... } else { ... } constructs aren't expressions, and also,
perl uses arrays instead of linked lists:

example in common lisp

(defun find-value (value list)
(and list
(if (string= value (first list))
value
(find-value (rest list)))))

(defun example
(or (find-value my-value my-list)
(find-value my-other-value my-other-list)))

Using these kind of recursive calls almost automatically force you to
break up your sample problem into 2 subs.

Also note that you can then re-use the find-value sub to reduce the
total amount of code.


same algorithm in perl.

sub find_value {
my ($value,@list) = @_;
if (@list) {
my $first = shift @list;
if ($first eq $value) {
return $first;
}
return find_value($value,@list);
}
return; # return false
}

sub example {
find_value($value,@list) or
find_value($other_value,@other_list);
}

note that you probably still want to use plenty of return()s here.

also note: is is pretty inefficient if @list is long. you'd generally
write the find_value function using foreach(), and pass the lists as
array references.

ps: none of this code has been tested. YMMV.

Thank-you very much for taking the time to write so helpfully Joost.

/M
 
M

Michael

You might look at the function "first" from the core module List::Util
which implements that for you.

Thank-you. I had no idea that existed. Perl is a rather extensive
wonderland.

/M
 
T

Ted Zlatanov

M> Just as a matter of interest, so far as I could see, my technique of
M> setting a flag was the simplest way of maintaining the integrity of the
M> foreach (terminating it with "last" rather than jumping out of it with
M> "return"), whilst not wasting processor cycles performing irrelevant loops
M> later in the function. I am a newbie and don't know much - is there a
M> more elegant alternative which would satisfy the functional programmers?

Don't worry about satisfying functional programmers or anyone else. Get
the task done, write correct maintainable code, and that's enough.

Ted
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top