Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum Goto page 1, 2, 3  Next
Larkin
Wizard


Joined: 25 Mar 2003
Posts: 1113
Location: USA

PostPosted: Mon Nov 12, 2007 4:20 pm   

[2.11Pro] Use of #RETURN multiple times in a function non-intuitive to me
 
I probably already know what I'm doing wrong here, but I was hoping to use logic in my functions that allowed for easier maintenance and a little cleaner code. (I plan to try a Lua function next!)

Anyway, would it be plausible to make the following function work the way a traditional function would work? Basically, I want to cut out of the function early on any one of a set of conditions, but when none of those is met I'll return the default value...

Code:
#FUNCTION able_apply {
#IF (@afflictions.slickness) {
  #RETURN 0
}
#IF (@leftarm == "severed" and @rightarm == "severed") {
  #RETURN 0
}
#IF (@afflictions.crucified) {
  #RETURN 0
}
#RETURN 1
}


It's always returning 1 now, and I suspect that's because the function doesn't abort on the first #RETURN. Am I right on that?
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Mon Nov 12, 2007 5:06 pm   
 
The trouble is that #return doesn't cause a function to exit.

#function omg {#return lol;#say hax}

the #say command will still execute because the function doesn't exit - #return basically just pushes a value onto the stack and that's it. I was going to post about this, but you beat me to it :P it'd be nice if it could do this, you're right.

However, you can build your function to exit itself once it reaches a return by nesting the #ifs or using #switch, so it's not that big a deal.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: Mon Nov 12, 2007 5:38 pm   
 
Just put #ABORT 0 in after the #RETURN.

[EDIT]: Since you're within an actual script block that should be #ABORT 1 to abort the whole function.
_________________
Taz :)
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Mon Nov 12, 2007 6:21 pm   
 
Yeah, I'm not sure about this one. I actually like being able to set the #RETURN value without exiting. This is actually how Delphi works. I Delphi functions, you do:

Result := whatever

to set the result of a function, but it doesn't cause the function to terminate. And this can be quite useful in many situations. So that's why I did it the same way in CMUD. Especially since there are already ways to abort a function. Although honestly, I've always considered using #abort (or using "break" in other languages) to be the same as a "goto" and just means your code probably isn't as well-structured as it could be. I know people still use it all the time...Delphi has "exit" and I do use it, but usually only at the beginning of a procedure or function to exit if it wasn't called with valid arguments. Using "exit" in the middle of a long routine is just asking for memory leaks and other obscure bugs unless you are religious about using try/finally blocks. Sorry for all of the Delphi references.
Reply with quote
Larkin
Wizard


Joined: 25 Mar 2003
Posts: 1113
Location: USA

PostPosted: Mon Nov 12, 2007 6:33 pm   
 
I avoid #ABORT like the plague after having seen it used incorrectly and causing odd side effects too many times. Smile

I figured out that it was very easy for me to just convert my #IF commands into one #SWITCH, so I'm happy with how it works now. Knowing how #RETURN works helps me code my #FUNCTIONs, and this behavior might be a good idea to note in the help file, just for those of us who come from traditional (non-Delphi Razz) coding background.

Thanks for the replies!
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Mon Nov 12, 2007 7:56 pm   
 
I went ahead and added this to the help file.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Arde
Enchanter


Joined: 09 Sep 2007
Posts: 605

PostPosted: Mon Nov 12, 2007 8:08 pm   
 
Hmm... It not returns, it only sets the value will be returned - technically it is more correct statement. Fang, may be you add more complex example to the help?
_________________
My personal bug|wish list:
-Wrong Priority when copy-paste setting
-1 prompt trigger for Mapper, Session and General Options, not 3 different!
-#SECTION can terminate threads
-Buttons can't start threads
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Mon Nov 12, 2007 10:52 pm   
 
Just for you, Arde, I rephrased it and added a few more examples. You're not getting a Christmas present now, just so you know.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Seb
Wizard


Joined: 14 Aug 2004
Posts: 1269

PostPosted: Mon Nov 12, 2007 11:11 pm   
 
Well, I agree with the complex examples sentiment. Most of the examples in zMUD were very simplistic and didn't necessarily indicate what the syntax would be in a more complex example. (So, often it was a question of trial and error.)
Reply with quote
Zhiroc
Adept


Joined: 04 Feb 2005
Posts: 246

PostPosted: Mon Nov 12, 2007 11:51 pm   
 
Hmm, if it's called #RETURN, it should return from the function at that point like every other language with a "return" directive. You can document it all you want, but you'll find people getting it wrong all the time otherwise....

Multiple #RETURNS are good for exiting loops early, and avoiding if/then/elseif statements.

And if you want the other behavior, it's easy to do with a local variable and a #RETURN at the end.
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Tue Nov 13, 2007 12:22 am   
 
You can already use #abort much like you'd use a return or break to exit a loop.

And see Zugg's post above for "every other language".
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Seb
Wizard


Joined: 14 Aug 2004
Posts: 1269

PostPosted: Tue Nov 13, 2007 12:33 am   
 
I have to agree with Zhiroc (changing "every other language" for "most other languages").

If #RETURN was like Zhiroc suggests, then for Zugg's example, you would just do
$Result = whatever
and then
#RETURN $Result

And actually, that looks very similar! Maybe functions could even return $Result by default if they reach the end of the code with no #RETURN statement. This would make $Result a special, reserved, local variable though.
Reply with quote
Guinn
Wizard


Joined: 03 Mar 2001
Posts: 1127
Location: London

PostPosted: Tue Nov 13, 2007 1:03 am   
 
Another vote for it seeming counter intuitive. Admittedly I've only really used Java so it's just my basis for 'normal' being different from Zugg's.
_________________
CMUD Pro, Windows Vista x64
Core2 Q6600, 4GB RAM, GeForce 8800GT
Because you need it for text... ;)
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Nov 13, 2007 1:28 am   
 
Sorry, but this isn't going to change. Sorry about it being counter-intuitive for some people, but it's just something you'll need to get used to.

The way it is now, you can always add your own #ABORT if you really want it to exit. If I changed it so that #RETURN also exited all the time, then there would be no way to use it the way it is now, and I don't want to restrict that functionality. As I mentioned, being able to do stuff after assigning the return value can be very useful.

Also, using multiple #RETURN commands should *not* cause any error messages. If it is, then that's a bug I need to fix. In fact, a very common use of #RETURN is the following:
Code:
#FUNCTION MyFunc {
  #RETURN 0  // set default return value
  #IF (something) {#RETURN newvalue}
}

In this case you set a default return value, and then only change the return value if an expression is true. I do this kind of stuff all the time in Delphi. If #RETURN always exited, then there would be no way to do this.

So that's why I'm leaving it the way it is...because you can still just add your own #abort if you need it. Making some sort of special $Result local variable just adds even more complexity to the parser and compiler, and then also prevents someone from using "Result" as their own local variable name.
Reply with quote
Seb
Wizard


Joined: 14 Aug 2004
Posts: 1269

PostPosted: Tue Nov 13, 2007 2:16 am   
 
How about an extra parameter to #RETURN?

#RETURN [RtnVal], [True/False]
where RtnVal defaults to "" and True/False is "Now?" and defaults to True (or False if you want). If it is True, then it returns immediately. If False, then it returns at the end. Or we could use "Yes", or "1" (minus the quotes) for "Now?". [EDIT: Actually any non-zero value should work for True, except for False, obviously.]


Last edited by Seb on Tue Nov 13, 2007 2:34 am; edited 2 times in total
Reply with quote
Guinn
Wizard


Joined: 03 Mar 2001
Posts: 1127
Location: London

PostPosted: Tue Nov 13, 2007 2:17 am   
 
Edit: Whoops, writing this as Seb replied

Quote:
If I changed it so that #RETURN also exited all the time, then there would be no way to use it the way it is now, and I don't want to restrict that functionality.

I wouldn't think it'd restrict functionality necessarily. Your example would become
Code:
#FUNCTION MyFunc {
  $return = 0  // set default return value
  #IF (something) {#RETURN newvalue}
  #RETURN $return
}


As it is, Larkin's becomes
Code:
#FUNCTION able_apply {
$return = 1
#IF (@afflictions.slickness) {
  $return = 0
}
#IF (@leftarm == "severed" and @rightarm == "severed") {
  $return = 0
}
#IF (@afflictions.crucified) {
  $return = 0
}
#RETURN $return
}


Seems like no functionality is really lost either way, it's just another way to skin the same cat...
Now if there was a #RETURNNOW function that did '#RETURN x;#ABORT' then we'd all be happy :) Or is that just being cruel to the poor cat?
_________________
CMUD Pro, Windows Vista x64
Core2 Q6600, 4GB RAM, GeForce 8800GT
Because you need it for text... ;)

Last edited by Guinn on Tue Nov 13, 2007 2:18 am; edited 1 time in total
Reply with quote
Iceclaw
Apprentice


Joined: 11 Sep 2005
Posts: 124

PostPosted: Tue Nov 13, 2007 2:18 am   
 
I like the extra parameter option, default FALSE, return at end :)
Reply with quote
Heretic
Newbie


Joined: 27 Oct 2005
Posts: 7

PostPosted: Tue Nov 13, 2007 3:06 am   
 
Zugg wrote:
In fact, a very common use of #RETURN is the following:
Code:
#FUNCTION MyFunc {
  #RETURN 0  // set default return value
  #IF (something) {#RETURN newvalue}
}



In all my years of programming I've never seen or had any interest in seeing this. Nor has anyone I've ever talked to with at least equivalent experience. Especially because this is absolutely trivial to implement without this kind of loss of readability.

The equivalent in C:
Code:

int something(){
   int r = 0;
   if (whatever) r =newvalue;
   return r;
}

Much more intuitive, same functionality, no significant amount of extra effort. Everyone's a winner.

Have a nice day!
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Nov 13, 2007 3:53 am   
 
Well, obviously my example above was a trivial example. Look, I've been programming for over 20 years, ok? Yes, I've always used Delphi/TurboPascal and not C/C++, so maybe I'm just weird. But in the example that you gave, if the programmer ever uses "exit" (or break, or whatever C uses to exit a routine prematurely), then you can end up with a function that has an undefined result. So I *always* set the default return value in my functions at the beginning.

This also helps with exception handling. If your routine gets an exception and you tell it to continue, then you still have the default function result instead of undefined.

Yes, it's also better to try/finally trap to ensure that you return a result. I use that as well. But I still have a lot of code that looks like this:

Code:
function MyFunc( args): Boolean;
begin
  Result := false;
  if Args not valid then exit;
  do function here and set Result := value;
end;

In other words, I set the default function value, then verify that correct arguments were passed (pointers not nil, etc). Yes, I could have also easily done this:
Code:
function MyFunc( args): Boolean;
begin
  if Args valid then begin
    do function here and set Result := value;
    end
  else Result := false;
end;

So, it's just a style difference. I use the first method because:

a) It makes it obvious to me what the default return value of every function should be at the very top
b) Allows me to make multiple argument checks and just use Exit for each one instead of building some huge IF statement.
c) Keeps the main function code indented one level less

Yes, some of these are trivial. This is all just a style issue.

But look, this discussion is getting carried away. I'm not going to add yet another argument to #RETURN to make it even more confusing. zScript is NOT C! There are lots and lots of things in zScript that are different than how C works. If you want to use a "return" that always aborts, then feel free to write your functions using Lua.
Reply with quote
Seb
Wizard


Joined: 14 Aug 2004
Posts: 1269

PostPosted: Tue Nov 13, 2007 4:13 am   
 
I don't mean to be incendiary, but:
Wikipedia: Return statement wrote:
In computer programming, a return statement causes execution to leave the current subroutine and resume at the point the subroutine was called -- known as its return address. The return address is saved, usually on the process's call stack, as part of the operation of making the subroutine call. Return statements in many languages allow a function to specify a return value to be passed back to the code that called the function.

In C++, ... <snip>

In Pascal there is no return statement. A subroutine automatically returns when execution reaches its last executable statement. Values may be returned by assigning to an identifier that has the same name as the subroutine (a function in Pascal terminology).

So why invent a new RETURN statement that doesn't actually return, when even Pascal doesn't use RETURN to just set a default return value and not return?

Zugg wrote:
a) It makes it obvious to me what the default return value of every function should be at the very top
b) Allows me to make multiple argument checks and just use Exit for each one instead of building some huge IF statement.
c) Keeps the main function code indented one level less

I can see the logic behind your point (a) and the benefit, but points (b) and (c) can be accomplished with returns that actually return as shown be some of the examples above, e.g.
Code:
#FUNCTION MyFunc {
  $return = 0  // set default return value
  #IF (something) {#RETURN newvalue}
  #RETURN $return
}

And that also covers point (a) too.
Reply with quote
Heretic
Newbie


Joined: 27 Oct 2005
Posts: 7

PostPosted: Tue Nov 13, 2007 4:18 am   
 
Zugg wrote:
Well, obviously my example above was a trivial example. Look, I've been programming for over 20 years, ok? Yes, I've always used Delphi/TurboPascal and not C/C++, so maybe I'm just weird. But in the example that you gave, if the programmer ever uses "exit" (or break, or whatever C uses to exit a routine prematurely), then you can end up with a function that has an undefined result.


Just for your information, in C "break" will end a loop. It's effectively "goto endofloop." It will cause a compiler error if you try to use it in a function without being in a loop, and has nothing to do with ending the function. Same with "continue" which is effectively "goto beginningofloop." In short, as long as you have a "return" statement at the end of the function, a function will -not- give up control without assigning some return value except for C++ exceptions, in which case it doesn't even conceptually make sense for there to be a return value.

It seems every time I post you brag about your "over 20 years of experience," and that certainly does give your opinion some weight, but don't forget that any programmer -always- has a lot to learn from other languages and other schools of thought.
Reply with quote
Seb
Wizard


Joined: 14 Aug 2004
Posts: 1269

PostPosted: Tue Nov 13, 2007 4:24 am   
 
Zugg, if you really want to keep functions the way they are, I think you should at least consider renaming the #RETURN command to #SETRETURNVALUE, since that is what it actually does (and does not return). It will cause a lot less confusion and argument.
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Tue Nov 13, 2007 5:14 am   
 
I can see both sides of this arguement. The convienence of return in C to end the function is useful, however even in C I often write it so that the return value is held in a variable from start to finish. I also programmed in Pascal, and often was irritatated at the lack of a quick out, exit wasn't allowed at the time. Having learned from that experience though I tend to write all loops, no matter what language, to have internal exit conditions as well as the external data. From an assembly standpoint the entire programming community are all liars, 1/20th of the instructions used are a form of 'goto'. Knowing that little detail since I started learning assembly, over 20 years ago, I am fairly certain of a few things:
1. #RETURN is a perfectly fine name
2. Whichever way Zugg does #RETURN is right.
3. The Wiki is not gospel, there are errors an ommisions
4. I am very likely to lock this thread
5. I haven't quite run out of patience yet

About all I can say for those that think #RETURN needs to exit is learn more diverse ways to write your code. An #IF-ELSE chain would work for Larkin's original problem. The reason it works is because he is actually doing if(not(slick&labroke&rabroke&crucified)) which has a number of logical equivalents. In this case he is looking to use this one if(not(slick)|not(labroke)|not(rabroke)|not(crucified)). The not is in the return values for those that are having trouble following. It gives just the same efficiency when coded that way as when return does a jump to end of function. Actually when a compiler is done with it the 2 forms end up nearly identical in assembly.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Tue Nov 13, 2007 11:21 am   
 
At the risk of looking like a sock puppet, I'm afraid I agree with Viji. These things don't really make a difference, since either method lets you accomplish either way of doing things. The first time you try to make a function and it doesn't work like you expect (whichever way you expect), you'll read the help file and discover what rules it uses.

I personally have never used a language that doesn't use return to exit a function, but I don't see a problem with doing it this way, either.

And while Wikipedia is the best site on the planet, it does have a tendency, as Seb's found, to state things that happen to be true as if they were Cosmic Facts.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Arde
Enchanter


Joined: 09 Sep 2007
Posts: 605

PostPosted: Tue Nov 13, 2007 11:38 am   
 
Fang Xianfu wrote:
Just for you, Arde, I rephrased it and added a few more examples. You're not getting a Christmas present now, just so you know.


Thank you, Fang! You can't deny that now help article for #RETURN is much, much better. And btw, I have my birthday in November, you may give me your present 1 month earlier instead of Christmas. Laughing

I tend to agree with what Vijilante wrote in his last paragraph and Zugg in his latest post (and I will not even bother thinking how I looks like - why I must do it?). The language (here it is the zScript) is just an instrument, learn it features and restrictions before use. The question is in having a complete documentation with plenty of samples, not in how Zugg had implemented one or another command of function. If anyone now would write a function for a first time, will he/she have a question on how #RETURN works? No, even if the name for a command is non-intuitive.

UPDATE: Fang, you have beat me in time with your answer. Smile
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net