Jump to content

return command?


steph Arnott
 Share

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

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

Recommended Posts

link_message(integer sender_number, integer number, string msg, key id)
	{
		if ((number == 2003000) && (msg == "exitOpen"))
		{
			if(closed)
			{
				integer step;
				do
				{
					llSetPos(llGetPos()-a);
				}
				while (++ step < 9);
				llSetPos(llGetPos()-a/2);
				closed = FALSE;
			}
			else
				return;//Is this really needed?
		}
		if ((number == 2003000) && (msg == "exitClose"))
		{
			if(! closed)
			{
				integer step;
				do
				{
					llSetPos(llGetPos()+a);
				}
				while (++ step < 9);
				llSetPos(llGetPos()+a/2);
				closed = TRUE;
			}
			else
				return;

		}
	}

 

Link to comment
Share on other sites

Steph, if the only messages this thing will ever get are "exitOpen" and "exitClose", you can be a bit lazy and omit the test for "exitClose". If you get a message and it's not "exitOpen", it must  be "exitClose", right? And, if you do the comparison for the proper "number" before checking the message, you only have to do that comparison once, which will improve the execution time very slightly.

By using "else if", you'd also do the number comparison only once, but I thought it might be useful to show that there are times when it's wise break out the parts of a complex conditional.

If this script will get other messages that it must ignore, you'd have to do the test for "exitClose".

 

link_message(integer sender_number, integer number, string msg, key id)	{		if(number == 2003000) // no need to go further if number is wrong		{			if(msg == "exitOpen")			{				if(closed)				{					integer step;					do					{						llSetPos(llGetPos()-a);					}					while (++ step < 9);					llSetPos(llGetPos()-a/2);					closed = FALSE;				}			}			else // msg must be"exitClose"			{				if(! closed)				{					integer step;					do					{						llSetPos(llGetPos()+a);					}					while (++ step < 9);					llSetPos(llGetPos()+a/2);					closed = TRUE;				}			}		} // if(number == 2003000)	}

 

  • Like 1
Link to comment
Share on other sites


steph Arnott wrote:

I see what you mean, i never thought that way.

As I'm sure you are learning, when you deal with computers, you sometimes find yourself thinking "that way". I have been told by friends that I'm a pain in the ass because I think too logically. I don't doubt I'm a pain in the ass, but I think that's for other reasons.

;-)

Link to comment
Share on other sites


steph Arnott wrote:

I think you not. Tho i still can not get my head around the return.

Think about a simple linear computer

Linear meaning that instructions are executed one after the other in a linear fashion

When the processor reads a return instruction it stops the sequential execution and returns to where this bit of the linear code was requested, and continue the linear execution after that instruction.

The return instruction can return a variable value or not, but that is not essential for understanding it

:smileysurprised::):smileyvery-happy:

Still to day all computers are basically linear

We have multicore processors and threads that work in parallel,

but all are using linear processing

  • Like 1
Link to comment
Share on other sites

It may help to realize that an event handler is a code block and its closing brace, }, actually is an implied return, in that it ends the event handler. Within the code block of the event handler, one may wish to terminate code execution at that point and no longer process anything more. To do that, you'd use return;.

 

Often, this can be avoided by changing your logic constructs, such as using an else if chain (which "falls through" to the end) instead of a series of ifs (which requires each test to be done). However, there are times, such as meeting a certain condition within a loop, that return; will be required.

 

In general, if there isn't a loop involved, it is preferable to avoid the use of  return; if only because it might be missed in a quick reading of the code. And, within a loop or otherwise where it really is needed, I prefer to draw attention to it with a comment, just so I don't overlook it later.

 

Everything said here also applies to subroutines (user written functions) with an additional complication- a subroutine may be defined to return a value, in which case one must explicitly use a return value; within it.

  • Like 1
Link to comment
Share on other sites

When you code a function or handler, you want to return from it the moment you've completed the job and have the result, or have determined you can't do the job and must return an error code (handlers don't return values, but functions can). That moment may not be at the end of your code. It's understandable to think that all code should end at the end, and you usually try to code it that way, but "return" gives you a way out when ending at the end would be difficult or inefficient.

In your original code example, the first return statement was actually useful because it would have prevented the computer from executing the second "if" if the first one passed (meaning the second "if" would certainly fail, and doing second "if"s test would be a waste of time). Changing the second "if" to "else if" did the same thing, in a more logical and less error prone fashion, making the first "return" redundant. The "else" makes the second "if" go only if the first one fails, and the code would end at the end, as you'd expect.

If you are coding a function that returns a value, you can't avoid using "return", as something must specify the thing to be returned. Here's an example that shows how return is used in a function, and also shows why you might use more than one return.

Let's imagine a function that returns the name of the day of the week given the number of the day, where 0 is Sunday, etc. There are better ways to code this, but I want to make an example...

string dayName(integer day){
    if(day==0){ return "Sunday";}
    if(day==1){ return "Monday";}
    if(day==2){ return "Tuesday";}
    if(day==3){ return "Wednesday";}
    if(day==4){ return "Thursday";}
    if(day==5){ return "Friday";}
    if(day==6){ return "Saturday";}
    else return "?";
}

You could also code this as:

string dayName(integer day){

   string name = "?";

    if(day==0) {name = "Sunday";}
    else if(day==1) {name ="Monday";}
    else if(day==2) {name = "Tuesday";}
    else if(day==3) {name = "Wednesday";}
    else if(day==4) {name = "Thursday";}
    else if(day==5) {name = "Friday";}
    else if(day==6) {name = "Saturday";}
    return name;
}

Which do you prefer?

There are more complex situations in which escaping a function or handler via a "return" well before the end of the code makes more sense than trying to end at the end.

  • Like 1
Link to comment
Share on other sites

@ All.

So basically unless I need a value then return is pointless in it's use and could even create a bug. I come to the conclusion that a lot of SL code that is free is just, well, badly written. Which is not very helpful when one is learning. Learning from them has actually given me more problems than they solved, in that I have had to unlearn bad practices and miss conceptions. All good fun, maybe, lol.

http://wiki.secondlife.com/wiki/Builders_Buddy This why i found it confusing. Maybe it becouse of other code langage that the return was used, but i gather its use here is irrelevent to the block becouse tthis } allready does the return. BTW i not saying the script is bad, i just used the snippet as an example.

 if( message == optReset ) {            llOwnerSay("Forgetting positions...");            llShout(PRIMCHAN, "RESET");            return;        }

 

Link to comment
Share on other sites


steph Arnott wrote:

So basically unless I need a value then return is pointless in it's use and could even create a bug.

I'm not sure how you got that impression, but it's certainly not the case, and return can greatly simplify code, both for readability and (especially) execution.

The readability thing is a bit controversial because there's a line of thinking going back decades that the flow of program control might be more obvious if each block only has a single exit. As with most things, taken to an extreme, this can lead to some very convoluted programming -- even in languages specially designed for it.

(I'd also just mention off-topic that the order in which conditionals are tested can affect program performance. Some of the sample code is testing a string match and then an integer, both of which need to be true for a branch of code to execute; unless there's a vast difference in frequency, it would be faster to filter first by the integer value, string operations being so much slower.)

Link to comment
Share on other sites

OK, I understand all that. So pretty much 90 + % of the usage in LSL is not needed and this would be better if it was else if instead of the return command.

 if ( message == optPos ) {            if(chatty) llOwnerSay("Positioning");            vector vThisPos = llGetPos();            rotation rThisRot = llGetRot();            llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));            return;        }        if ( message == optClean ) {            llRegionSay(PRIMCHAN, "CLEAN");            if(dieOnClean) llDie();            return;        }        if ( message == optDone ) {            llRegionSay(PRIMCHAN, "DONE");            if(chatty) llOwnerSay("Removing Builder's Buddy scripts.");            return;        }        if ( message == optChannel ) {            Sign = "+"; //default is a positive number            Input = "";            llDialog( agent, Caption, Menu2, MENU2_CHANNEL );        }

 

Link to comment
Share on other sites


Qie Niangao wrote:


steph Arnott wrote:

So basically unless I need a value then return is pointless in it's use and could even create a bug.

I'm not sure how you got that impression, but it's certainly not the case, and return can greatly simplify code, both for readability and (especially) execution.

The readability thing is a bit controversial because there's a line of thinking going back decades that the flow of program control might be more obvious if each block only has a single exit. As with most things, taken to an extreme, this can lead to some very convoluted programming -- even in languages specially designed for it.

(I'd also just mention off-topic that the order in which conditionals are tested can affect program performance. Some of the sample code is testing a string match and then an integer, both of which need to be true for a branch of code to execute; unless there's a vast difference in frequency, it would be faster to filter first by the integer value, string operations being so much slower.)

I use "return" frequently in my professional coding, as I often find myself in a place where my work is done (or more likely, I've tested my way down to an error condition) and can't see an easy way to get to the end of the routine. At that point, I return an error code. I don't think I've used "return" in any of my small LSL projects, simply because they never reach a level of complexity that makes a "return" attractive.

Your advice about decomposing complex conditionals (or rather avoiding their construction in the first place) is spot-on. I often nest simple "if"s for the reasons you cite, minding the execution times of the tests and their likelihood of failing. You'd want to do the fastest tests first, so that their failure will save you from executing costlier tests. When the tests are all of similar speed, you want the most failure prone tests first, so they'll maximize the chances the other tests can be skipped.

Link to comment
Share on other sites

"When the tests are all of similar speed, you want the most failure prone tests first, so they'll maximize the chances the other tests can be skipped"

So am i correct in that what you saying is the most likly used correct answer should be the first and least last. Can not say i bothered to even think of it.

Link to comment
Share on other sites

Imagine three conditions, A, B, and C, which must all be true for a block of code to execute. Also imagine that A is true 98% of the time you test, B is true 50% of the time, and C is true 2%. The final probability that the code block will execute is about 1% (.98 * .5 * .02 ≅ .01).

Now, let's code the conditional three different ways...

if(A && B && C) { code block }

Unless the compiler is smart enough to exit the "if" on the first failed test, A, B and C will all be tested 100% of the time, even though the code will run only approximately 1% of the time. If the compiler does terminate the "if" on the first fail, you'll have to know in which direction the compiler evaluates the statement (A && B && C), from right to left (C first), left to right (A first), or undefined. I can't remember detail like that for every compiler I use, so I don't generally rely on compiler behavior in situations like this.

Now let's try...

if(A){
   if(B){
       if©{
            code block
       }
   }
}

This would result in the test for A being done 100% of the time, The test for B being done 98% of the time, and the test for C being done 49% of the time. And again, the code will run approximately 1% of the time.

And finally, let's try...

if©{
   if(B){
       if(A){
           code block
       }
   }
}

This would result in the test for C being done 100% of the time, The test for B being done 2% of the time, and the test for A being done 1% of the time. And yet again, the code will run approximately 1% of the time.

In the last example, we've eliminated almost all of the testing for A and B, with no change in the code's overall function.

ETA: Fixed some errors.

  • Like 1
Link to comment
Share on other sites


steph Arnott wrote:

link_message(integer sender_number, integer number, string msg, key id)	{		if ((number == 2003000) && (msg == "exitOpen"))		{			if(closed)			{				integer step;				do				{					llSetPos(llGetPos()-a);				}				while (++ step < 9);				llSetPos(llGetPos()-a/2);				closed = FALSE;			}			else				return;//Is this really needed?		}		if ((number == 2003000) && (msg == "exitClose"))		{			if(! closed)			{				integer step;				do				{					llSetPos(llGetPos()+a);				}				while (++ step < 9);				llSetPos(llGetPos()+a/2);				closed = TRUE;			}			else				return;		}	}

 

I seem to have a hard time asking questions to this forum and getting a reply, I  thought may be it's the way I'm asking the question.  I see this post got lots of answers, so would this be a good example of how to post a question, specially sense I'm mostly looking for how, if, and or way some thing works and not needing help writing the script ?  I'd really like to learn more about how/why things in LSL work.

Link to comment
Share on other sites

I not know much about your comment, but I do know people here who answers are mostly code writers for a profession and have always been very patient with a dimwit like me asking probably stupid questions and grabbing lots of trancs before they hit me.

ADDED: Some times i feel maybe they think i playing stupid.

Link to comment
Share on other sites


phaedra Exonar wrote:

I seem to have a hard time asking questions to this forum and getting a reply, I  thought may be it's the way I'm asking the question.  I see this post got lots of answers, so would this be a good example of how to post a question, specially sense I'm mostly looking for how, if, and or way some thing works and not needing help writing the script ?  I'd really like to learn more about how/why things in LSL work.

 If you look back through a month or more of threads in this forum, you'll find two things that can help resolve your quandry.  First, there are really only a handful of people -- a dozen, maybe -- who respond to most questions here.  It's a small talent pool, and we have overlapping but not identical interests.  We also have varying degrees of experience with SL and with LSL.  For example, I have been in SL for 7 years, scripting for 5 of those, but am not a programming professional in RL.  I have little interest in scripting weapons systems, and I tend to ignore questions that will involve linking to external systems.  LepreKhaun and Peter are professionals in RL, and are more comfortable with those questions.  Steph has been scripting for a couple of years and is eagerly asking questions about many basic concepts that stir discussion, while offering her own insights about more complicated topics.

Second, the questions that get a lot of attention tend to be very well focused.  People who are stuck on a script and can ask "What's wrong with the way I'm coding this code snippet?" get a lot of quick answers.  People who post lengthy, complex scripts and say "I can't get this to work" get very few.  People like Steph who ask why using a timer event is "better" than using llSleep, or who wonder why implicit typecasting doesn't always work will get a lot of debate.  Others who ask ill-formed questions ("Is it possible to make a light switch with a sculpty that turns red when I am in another sim?") tend to be ignored.

I'd guess that more than half of the "regulars" here are self-taught scripters.  Many of us have relied on this forum and its predecessors for tips on how LSL works.  Most of us, I've observed, don't ask many questions any more, but we raise new issues in the course of answering other people's.  That's why so many threads seem to veer off course.  Once an OP's question is out of the way -- or ignored -- we start teaching each other impromptu ways to address issues that the OP's question provoked.  It's an inefficient, unplanned curriculum, but it works. 

So, I suggest jumping into the discussion when you see a response that tweaks your interest.  Sieze the chance to insert your own question or present a counter-example or a confusing bit of wiki wording that seems inconsistent with they way you thought LSL worked.  Post your own focused questions, making it clear that you don't want anyone to write your script but rather to explain how "this part right here" could be better.  And don't worry too much about the fact that you sometimes end up learning about something far removed from where you started.

Link to comment
Share on other sites


steph Arnott wrote:

I  thought nats had compound eyes.

ADDED: Just out of curiosity, when a man cooks, why they use every possible utensil ever invent to boil rice?

You're right about the compound eyes, so even with only one eye, one wing, and three legs, phaedra is ahead of most of us!

I've wondered about cooking rice myself. When I visited Japan long ago, I saw entire shelves at the department store devoted to all manner of rice cookers. My favorite had this inscribed on the outside...

"PLAIN - Fit the the life you are going to lead."

In the US, that would be an insult.

I learned to cook rice from my father, who told me to put rice and water (1:1.5 by volume) in a pot, bring it to a boil, stir it once, then set the flame as low as it goes and come back in 30 minutes. Never take the cover off the pot to check the rice! You must place your trust in the rice, it will be fine. If you check the rice, it will feel insulted and you'll taste the result.

;-)

  • Like 1
Link to comment
Share on other sites


steph Arnott wrote:  [ .... ]  Just out of curiosity, when a man cooks, why they use every possible utensil ever invent to boil rice?

1. There's more than one kind of rice.

2.  Some pots cook one kind of rice better than others do.

3.  Why would you have more than one utensil if you didn't want someone to use them all?

4.  And the big reason >>> Men are easily confused.  :smileywink:

Thank you for the metaphor, Steph.

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3803 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...