Jump to content

Return command


steph Arnott
 Share

You are about to reply to a thread that has been inactive for 3915 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

There are 2 usage forms - the keyword by itself, and the keyword followed by a value (1 - return; and 2 - return value; ). In either case, once encountered, script execution leaves the function or event from which it was called, returning to the previous scope. The wiki gives a good explanation altogether, but the sentence stating that it returns execution to the previous scope, by itself isn't exactly correct. Inside a function, if used inside an inner block such as an if condition or for loop, the previous scope would still be inside that same function, just outside of the inner block in which it was used, which is not where the flow would return to. It will always cause flow to leave the entire function or event from which it was called.

Technically, you can think of the return keyword as always being used at the end of an event or function, but not being required because it is assumed by the LSL compiler when the end of a function or event is reached. The only time it is required is inside a function that has to return a value (return someValue; ) - at that point it will end the function returning the value following it. If it is encountered at some point before the end of a function or event, any code following it is ignored. It is often used as a shortcut to end a function or event prematurely in cases where the code following it does not need to be executed.

Except when used inside a function that needs to return a value, they keyword should only be used by itself followed by a semi-colon.

http://wiki.secondlife.com/wiki/Return

edited to remove the smileys

  • Like 1
Link to comment
Share on other sites

There are definitely places where it makes no sense to use return.  If you're lucky, it's a throwaway that has no effect at all, but it can produce odd effects. 

Here's one place where return does make sense.  Pick a card, any card .......

PickACard(){   @up;     integer rand = (integer)llFrand(gTotCards);    //Pick a number from zero to the maximum number of cards     integer idx = llListFindList(gWhat,[rand]);     if (~idx)       //Has this number been picked before?  If so ...     {            if (llGetListLength(gWhat) == gTotCards)       //We're never going to find an unusued number in range....          {             llRegionSayTo(Who,0,"Sorry.  There aren't any more cards left.");             return;   // There's nothing left to do here. Bail out.         }         else    //Otherwise, go back and pick a new number         {             jump up;         }     }     else    // This card hasn't been used already, so ....    {         gWhat += [rand];    //Make a record of the card number         string tex = (string)llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE,rand));         llRegionSayTo(Who,chan,tex);   //And send the random texture's UUID to the person    }}

 

 

 

 

  • Like 1
Link to comment
Share on other sites

OK all, I think I got all that. I been going thru others code and was a bit confused. Maybe others were using it incorrectly. Also I did not know I could jump back, have used it to jump down but not as back. Good to get it in a reasonably English explanation, LOL

Link to comment
Share on other sites

You made a good point in that return is often a throw-away command; that's one detail I had actually forgotten about. I think most of the time it is good for making it easier to understand what a scriptor's intentions are, and can be a little more readable if it can replace one or more layers of nested if conditions.

In the example where I used it:

touch_start(integer num){    if(time)    {        //Tell the toucher they have to wait        return;    }    //run any code when no one needs to wait}

 it could have simply been thrown away and replaced by surrounding the rest of the event's code inside an else block.

I like your example, but after looking at it a little bit, I realized the advantage again is in giving a clear understanding of what you want to happen, but it is still an example of a throw-away - if it were not there, the function as shown will still return at that point.

Link to comment
Share on other sites

Another way to skin that cat, without the Spaghetti.

 

integer gTotCards = 20;list gWhat;PickACard(){    integer rand;    integer idx;        if (llGetListLength(gWhat) == gTotCards) //We're never going to find an unusued number in range....     {        llOwnerSay("Sorry.  There aren't any more cards left.");    }    else    //Otherwise, we need to pick an unused number    {        do        {            rand = (integer)llFrand(gTotCards);            idx = llListFindList(gWhat,[rand]);//      }  while (!!~idx); // {ETA explanation below][And again, to substitute a much better conditional test]
       }  while (idx>=0); // A big "thank you" to Dora Gustafson for a marvelous suggestion! gWhat += [rand]; //Make a record of the card number llOwnerSay("You picked " + (string)rand + ". Try again?"); }}default{ touch_start(integer total_number) { PickACard(); }}

 

ETA: For those that may be unfamiliar with operators (http://wiki.secondlife.com/wiki/LSL_Operators), let me explain what is happening in the conditional test "!!~idx" I'm using.

 

Keep in mind that llListFindList() will return a -1 if there isn't a match, otherwise the index of where the match occured. And when you do a bit-wise NOT (~idx) to -1 you'll get 0, otherwise some other number (it doesn't matter what it is for what follows). The first logical NOT (!~idx) will then convert that 0 to 1 and everything else becomes 0. But that's opposite to what is needed to exit the while loop, so we apply a second logical NOT (!!~idx) to obtain the needed comparison.

Link to comment
Share on other sites


Dora Gustafson wrote:

Wonderful example of how to use the
command

(I see not a single one anywhere in the code)

 
        }  while (!!~idx);

Is this an example on readability?

:smileysurprised:
:)
:smileyvery-happy:

 

The function doesn't require a return statement as defined. Why should I have added one?

 

I appended an explanation for the conditional test to my original posting. for those of you that may be unfamiliar with reading operators.

Link to comment
Share on other sites


Dora Gustafson wrote:

        }  while (idx>=0);

is equivalent, self explaining, easier to read (years from now) and would have saved you a lot of words

:smileysurprised:
:)
:smileyvery-happy:

All true, but I do so love to write. :matte-motes-silly:

 

[ETA: And yours is faster as well! Amazing what one can learn here.]

Link to comment
Share on other sites

I have to admit I was entertained a little when I woke up to see the extras here and the jump up did kind of scream for a do-while. The last exchange does make me wonder though - while the wiki does recommend using the bit-wise not specifically for changing a -1 to 0 for a fast comparison, why does it say nothing about comparing to 0 always being faster and more efficient than comparing to any other integer value? I know that's the case in other languages and might make a lot of code easier to read and write, even when a comparison to another value might be more accurate yet unnecessary.

/me returns to the subject in an attempt to bypass retribution

If there had been code at the end of the function which needed to be executed at the end of all conditions except 1 (or a minority of them), a return command would then be appropriate inside that excepted condition.

ETA: I know that sounded complicated without an example but I'm not that much awake yet.

Link to comment
Share on other sites


Erik Verity wrote:

I have to admit I was entertained a little ...

I love the debates on style, and have always hated the "!~idx" form as unreadable.  As you say though, keeping to the subject ...

Not long ago Steph (OP) was asking about 'else if' and we had a similar debate where I waffled a lot.  Here, I'll be concise as returning one of a series of alternatives is one of the best uses for 'return' that I can think of, albeit in a silly example script:

string NumberString(integer Number){	if(0 > Number){		return "Some ghosts";	}else if(0 == Number){		return "A ghost";	}else if(1 == Number){		return "Just one person";	}else if(5 > Number){		if(2 == Number){			return "Two people";		}else if(3 == Number){			return "Three people";		}else{			return "Four people";		}	}else{		return "A surprising number of people";	}}default{	touch_end(integer HowMany){		llSay(0, NumberString(HowMany) + " touched me");	}}

 

Link to comment
Share on other sites

Style is based on training (or, in the case of first grade finger painters, the lack of. :matte-motes-delicious:). Unfortunately, some put way too much emphasis on it and end up disrailing threads and distracting the reader from the important issues.

 

Back to the topic: I agree with Steph, there is a lot of confusing and unnecessary use of return statements, even in production code on the Market Place. Not saying that's a bad thing, mind you, it's just makes me pause at times and wonder what they were thinking when they wrote it. Sometimes I want to recommend a class in Pascal (which doesn't have a return statement at all) so they'd learn how to structure their programs more correctly.

 

But all that's good. I'm certain they're enjoying themselves. I just enjoy coding differently.

Link to comment
Share on other sites

Yes, style is very subjective.  I was, in fact, expecting someone to point out that IF using multiple return statements was a good way to do things in my example (the alternative, more structured, approach being to assign the return value to a single local variable that is then returned when the function ends) then all my 'else if's are redundant.

In the case of that example IF the test evaluates as true the function will hit a return and terminate early, so it could only get to an 'else' if the test had failed.  As such, vanilla 'if's would be more efficient in this case.

Link to comment
Share on other sites

  • 2 weeks later...


PeterCanessa Oh wrote:

Yes, style is very subjective.  I was, in fact, expecting someone to point out that IF using multiple return statements was a good way to do things in my example (the alternative, more structured, approach being to assign the return value to a single local variable that is then returned when the function ends) then all my 'else if's are redundant.

In the case of that example IF the test evaluates as true the function will hit a return and terminate early, so it could only get to an 'else' if the test had failed.  As such, vanilla 'if's would be more efficient in this case.

Actually, the "more structured" approach would be to inline the unnecessary function you have in your example, which would make the "else if" construction preferable.

Link to comment
Share on other sites

Which would, however, mean that I had nothing from which to return, rendering the whole exercise invalid.  I had assumed that you were referring to the "single entry, single exit" rule of structured methods (for all: this says there shouldn't be multiple 'return' statements scattered all over the place because it confuses the flow of the programme and makes it less readable/maintainable).

In fact, I'd go as far as saying that inlining (duplicated) functions is never a structured approach - the whole point of structured programming being to enforce structure for maintainability, even at the expense of efficiency (which is the point of inlining).

ETA for below: I am in complete agreement, the example I posted was simply a toy demonstration of the return statement, not necessarily an approach I'd recommend.

Link to comment
Share on other sites


PeterCanessa Oh wrote:

Which would, however, mean that I had nothing from which to return, rendering the whole exercise invalid.  I had assumed that you were referring to the "single entry, single exit" rule of structured methods (for all: this says there shouldn't be multiple 'return' statements scattered all over the place because it confuses the flow of the programme and makes it less readable/maintainable).

In fact, I'd go as far as saying that inlining (duplicated) functions is 
never
a structured approach - the whole point of structured programming being to enforce
structure
for maintainability, even at the expense of efficiency (which is the point of inlining).

I believe you missed my point. Taking unduplicated code into a subroutine adds to the complexity of the code structure.  Modularity does have its place.

 

But, yes, I would've written your example with one return statement at the expense of an extra variable, just to keep it properly structured. The same as I would avoid the use of a "jump" within a function that made an extraneous return from the middle of it needed.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3915 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...