Answered LEAVE VS RETURN

Hi guys,

How are you ?

While coding today I was asking myself what is best to leave a procedure or a trigger with some test, is it the LEAVE or the RETURN ?

Example:
Code:
DEFINE VARIABLE i AS INTEGER

i = 1 .

IF i = 1 THEN LEAVE .

/* VS */

DEFINE VARIABLE i AS INTEGER

i = 1 .

IF i = 1 THEN RETURN .

What do you think and why ?
 

Stefan

Well-Known Member
Leave leaves the current block. Return leaves the current procedure.
And when the current block /is/ the current procedure? Which do you prefer and why?

I used to be very allergic to both return and leave since they escape the flow of a program. I only allowed a return (with value) at the end of a function block.

With the introduction of finally blocks for cleanup code I have become a bit more forgiving for returns halfway through.
 

Cringer

ProgressTalk.com Moderator
Staff member
Return should always be used to leave a procedure if that is the intention. Otherwise someone could come in and add a new block around the leave and you'll be losing functionality.
I tend to agree with leave/return, and avoid them as much as I can, but sometimes they are necessary to improve performance, or to provide certain desired behaviour.
 

TomBascom

Curmudgeon
I'm kind of old-school ;)

RETURN is for ending a procedure/function/method/trigger.

In most cases there should only be a single RETURN, at the end where it is, essentially, redundant noise. I am in the habit of putting it there even when it isn't strictly needed. It says "I'm done. The code for this procedure/function/method/trigger ends here."

I have never been a fan of RETURN ERROR or returning any values from procedures. For procedures returning values is the purpose of OUTPUT parameters.

For triggers RETURN NO-APPLY is a very common and appropriate thing to do.

For functions you need to use RETURN to return a value.

Multiple RETURN statements in a procedure/function/method/trigger should be avoided. The RETURN should almost always be at the very end of the procedure/function/method/trigger. Yes, I know I already said this - it's one of those things that should be repeated ;) It is a "bad code smell" for there to be multiple RETURN statements or for them to appear in strange upstream positions.

One upstream RETURN exception that I am comfortable with is if a procedure's "sanity check" fails.

Using LEAVE instead of RETURN, even where it would "work" is just creating confusion and being clever for the sake of being clever. Don't do it. You will confuse the next person to come along. Nobody will be impressed and somebody might end up doing something regrettable as a result.

You should label your blocks and use those labels whenever you LEAVE or NEXT a block (or UNDO or RETRY but IMHO you mostly shouldn't be doing those things). I confess that my own code could use quite a lot more block labelling.
 
Thank you all for your answer. I understand what you mean.

The way I was using was to leave a trigger/procedure when it's not needed to go further and avoid a series of "IF THEN DO" blocks . But maybe It was a mistake. Example bellow:
Code:
 DEFINE VARIABLE indnum AS CHARACTER   NO-UNDO.
    /* If the field is empty I don't need to go further in my trigger code */
    IF SELF:SCREEN-VALUE = "":U THEN DO:
          FI-va1ref:SCREEN-VALUE = "":U .
          RETURN.
    END.
    
    
    Some action on the field value .....

I will try to do as you say to have a cleaner code
 

TomBascom

Curmudgeon
I tend to reserve the early RETURN for situations where the "happy path" is relatively long. IOW, you cannot see, at a glance, where the end of the procedure is. In the bad old days that used to be a 15 or 20 line limit... these days I code on screens that show me 80 or 90 lines at a time - but I haven't extended the "at a glance" limit quite that far ;)

In a simple case like that you can avoid the early RETURN like so:
Code:
on any-printable of nothing in frame notHere do:
  if self:screen-value <> "" then
    do:
      /* some action on the field value */
    end.
  return.
end.
 
Top