www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - no return value

reply "Andrew Fedoniouk" <news terrainformatica.com> writes:
Following program, being compiled
in -debug,  in runtime ends up with the
following:

C:\d\test>test.exe
Error: AssertError Failure test(8)

The source of the problem is in int something() -
it does not have renturn value set.

IMO, either this code must not compile at all or
flag -w (warnings) should be 'on' by default.

Andrew.

==test.d================
static int v = 0;

int something(int vv)
{
  v = vv;
}

int main(char[][] args)
{
  something(28);
}

==test.d==EOF============= 
Mar 15 2005
next sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Andrew Fedoniouk wrote:

 ==test.d================
 static int v = 0;
 
 int something(int vv)
 {
   v = vv;
 }
 
 int main(char[][] args)
 {
   something(28);
 }
 
 ==test.d==EOF============= 

Here's what I get with GDC 0.10:
 test.d:3: function test.something function expected to return a value of type
int
 test.d:8: function test.main function expected to return a value of type int

--anders
Mar 15 2005
parent "Andrew Fedoniouk" <news terrainformatica.com> writes:
You are extremely lucky as.

    dmd.exe test.d

is just silently enjoying compilation of this.

Andrew.


"Anders F Björklund" <afb algonet.se> wrote in message 
news:d17m4a$298h$1 digitaldaemon.com...
 Andrew Fedoniouk wrote:

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============

Here's what I get with GDC 0.10:
 test.d:3: function test.something function expected to return a value of 
 type int
 test.d:8: function test.main function expected to return a value of type 
 int

--anders

Mar 15 2005
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 15 Mar 2005 13:58:10 -0800, Andrew Fedoniouk  
<news terrainformatica.com> wrote:
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

See: http://www.digitalmars.com/d/archives/digitalmars/D/bugs/1553.html It's the same/very similar reasoning as the assert in the switch statement. The compier cannot know your intent, throwing the assert forces you to consider your intent and make it clear in the code so as the compiler (and next programmer to look at it) knows for sure what you intend. Regan
Mar 15 2005
parent reply "Andrew Fedoniouk" <news terrainformatica.com> writes:
 The compier cannot know your intent, throwing the assert forces you to 
 consider your intent and make it clear in the code so as the compiler (and 
 next programmer to look at it) knows for sure what you intend.

Agreed, it is very reasonable. "no return value" should not be a warning but ruther just an error. Right? As I understand assertion in runtime is sort of atavism at these stage of the compiler. Andrew. "Regan Heath" <regan netwin.co.nz> wrote in message news:opsno9iqp723k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 13:58:10 -0800, Andrew Fedoniouk 
 <news terrainformatica.com> wrote:
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

See: http://www.digitalmars.com/d/archives/digitalmars/D/bugs/1553.html It's the same/very similar reasoning as the assert in the switch statement. The compier cannot know your intent, throwing the assert forces you to consider your intent and make it clear in the code so as the compiler (and next programmer to look at it) knows for sure what you intend. Regan

Mar 15 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 15 Mar 2005 14:41:26 -0800, Andrew Fedoniouk  
<news terrainformatica.com> wrote:

 The compier cannot know your intent, throwing the assert forces you to
 consider your intent and make it clear in the code so as the compiler  
 (and
 next programmer to look at it) knows for sure what you intend.

Agreed, it is very reasonable. "no return value" should not be a warning but ruther just an error. Right?

Yes.
 As I understand assertion in runtime is
 sort of atavism at these stage of the compiler.

The runtime assert is given because detecting this at compile time is either very difficult or perhaps impossible in some situations. So, if you were used to it giving an error at compile time, then happened to have one that it could not (or did not yet) detect, you would not know it, and the bug it caused would manifest later in the code, and be hard to track/find. Throwing the assert tells you exactly where and when the bug occured, allowing you to resolve it quickly and easily. Regan
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsno9iqp723k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 13:58:10 -0800, Andrew Fedoniouk
 <news terrainformatica.com> wrote:
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

See: http://www.digitalmars.com/d/archives/digitalmars/D/bugs/1553.html It's the same/very similar reasoning as the assert in the switch statement. The compier cannot know your intent, throwing the assert forces you to consider your intent and make it clear in the code so as the compiler (and next programmer to look at it) knows for sure what you intend. Regan


Mar 15 2005
prev sibling next sibling parent reply "Charles" <cee-lo green.com> writes:
Yea we've been trying to get Walter to make this a compile time error
forever, he stands alone on the 'shut-up code' argument last I read.

Can anyone give me a situation where no return is NOT an error, and
therefore should not be caught at compile time ?  I'd even go further and
say 'not-all control paths return a value' should be a compile time error.

"Andrew Fedoniouk" <news terrainformatica.com> wrote in message
news:d17lpi$291e$1 digitaldaemon.com...
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

 Andrew.

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============

Mar 15 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 15 Mar 2005 18:18:36 -0600, Charles <cee-lo green.com> wrote:
 Yea we've been trying to get Walter to make this a compile time error
 forever, he stands alone on the 'shut-up code' argument last I read.

 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go further and
 say 'not-all control paths return a value' should be a compile time  
 error.

The problem is not simply whether it's an error or not. It's whether you can correctly detect all cases, and the answer seems to be "no, you cannot", or, "you might be able to but it would take a lot of work to do so". It's true that some C/C++ compilers attempt to, they also give false positives, meaning, when you get one you're not sure if it's a real one, or not. Regan
 "Andrew Fedoniouk" <news terrainformatica.com> wrote in message
 news:d17lpi$291e$1 digitaldaemon.com...
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

 Andrew.

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============


Mar 15 2005
parent reply "Charles" <cee-lo green.com> writes:
 The problem is not simply whether it's an error or not. It's whether you
 can correctly detect all cases, and the answer seems to be "no, you
 cannot", or, "you might be able to but it would take a lot of work to do
 so".

You mean for the no return statement ? Im not familiar with compiler internals but wouldn't it have to inject an assert there when generating code ? If thats the case then it should be easy to switch to a compile time error maybe ? "Regan Heath" <regan netwin.co.nz> wrote in message news:opsnpibito23k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 18:18:36 -0600, Charles <cee-lo green.com> wrote:
 Yea we've been trying to get Walter to make this a compile time error
 forever, he stands alone on the 'shut-up code' argument last I read.

 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go further


 say 'not-all control paths return a value' should be a compile time
 error.

The problem is not simply whether it's an error or not. It's whether you can correctly detect all cases, and the answer seems to be "no, you cannot", or, "you might be able to but it would take a lot of work to do so". It's true that some C/C++ compilers attempt to, they also give false positives, meaning, when you get one you're not sure if it's a real one, or not. Regan
 "Andrew Fedoniouk" <news terrainformatica.com> wrote in message
 news:d17lpi$291e$1 digitaldaemon.com...
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

 Andrew.

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============



Mar 15 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 15 Mar 2005 19:31:54 -0600, Charles <cee-lo green.com> wrote:
 The problem is not simply whether it's an error or not. It's whether you
 can correctly detect all cases, and the answer seems to be "no, you
 cannot", or, "you might be able to but it would take a lot of work to do
 so".

You mean for the no return statement ?

Yes.
 Im not familiar with compiler
 internals but wouldn't it have to inject an assert there when generating
 code ?

Yes. But... int foo() { if (true) return 5; } the compiler simply injects an assert at the end of this function. We're it to give an error, it would be wrong.
 If thats the case then it should be easy to switch to a compile time  
 error maybe ?

No. Because of false errors, as shown in the example above. Regan
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsnpibito23k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 18:18:36 -0600, Charles <cee-lo green.com> wrote:
 Yea we've been trying to get Walter to make this a compile time error
 forever, he stands alone on the 'shut-up code' argument last I read.

 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go further


 say 'not-all control paths return a value' should be a compile time
 error.

The problem is not simply whether it's an error or not. It's whether you can correctly detect all cases, and the answer seems to be "no, you cannot", or, "you might be able to but it would take a lot of work to do so". It's true that some C/C++ compilers attempt to, they also give false positives, meaning, when you get one you're not sure if it's a real one, or not. Regan
 "Andrew Fedoniouk" <news terrainformatica.com> wrote in message
 news:d17lpi$291e$1 digitaldaemon.com...
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

 Andrew.

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============




Mar 15 2005
parent reply "Charles" <cee-lo green.com> writes:
I would prefer this an error as well :).


"Regan Heath" <regan netwin.co.nz> wrote in message
news:opsnpiuwlf23k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 19:31:54 -0600, Charles <cee-lo green.com> wrote:
 The problem is not simply whether it's an error or not. It's whether



 can correctly detect all cases, and the answer seems to be "no, you
 cannot", or, "you might be able to but it would take a lot of work to



 so".

You mean for the no return statement ?

Yes.
 Im not familiar with compiler
 internals but wouldn't it have to inject an assert there when generating
 code ?

Yes. But... int foo() { if (true) return 5; } the compiler simply injects an assert at the end of this function. We're it to give an error, it would be wrong.
 If thats the case then it should be easy to switch to a compile time
 error maybe ?

No. Because of false errors, as shown in the example above. Regan
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsnpibito23k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 18:18:36 -0600, Charles <cee-lo green.com> wrote:
 Yea we've been trying to get Walter to make this a compile time error
 forever, he stands alone on the 'shut-up code' argument last I read.

 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go further


 say 'not-all control paths return a value' should be a compile time
 error.

The problem is not simply whether it's an error or not. It's whether



 can correctly detect all cases, and the answer seems to be "no, you
 cannot", or, "you might be able to but it would take a lot of work to



 so".

 It's true that some C/C++ compilers attempt to, they also give false
 positives, meaning, when you get one you're not sure if it's a real



 or not.

 Regan

 "Andrew Fedoniouk" <news terrainformatica.com> wrote in message
 news:d17lpi$291e$1 digitaldaemon.com...
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

 Andrew.

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============





Mar 17 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 17 Mar 2005 16:36:12 -0600, Charles <cee-lo green.com> wrote:
 I would prefer this an error as well :).

An incorrect/false error? Regan
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsnpiuwlf23k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 19:31:54 -0600, Charles <cee-lo green.com> wrote:
 The problem is not simply whether it's an error or not. It's whether



 can correctly detect all cases, and the answer seems to be "no, you
 cannot", or, "you might be able to but it would take a lot of work to



 so".

You mean for the no return statement ?

Yes.
 Im not familiar with compiler
 internals but wouldn't it have to inject an assert there when  

 code ?

Yes. But... int foo() { if (true) return 5; } the compiler simply injects an assert at the end of this function. We're it to give an error, it would be wrong.
 If thats the case then it should be easy to switch to a compile time
 error maybe ?

No. Because of false errors, as shown in the example above. Regan
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsnpibito23k2f5 nrage.netwin.co.nz...
 On Tue, 15 Mar 2005 18:18:36 -0600, Charles <cee-lo green.com> wrote:
 Yea we've been trying to get Walter to make this a compile time  



 forever, he stands alone on the 'shut-up code' argument last I  



 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go  



 and
 say 'not-all control paths return a value' should be a compile time
 error.

The problem is not simply whether it's an error or not. It's whether



 can correctly detect all cases, and the answer seems to be "no, you
 cannot", or, "you might be able to but it would take a lot of work to



 so".

 It's true that some C/C++ compilers attempt to, they also give false
 positives, meaning, when you get one you're not sure if it's a real



 or not.

 Regan

 "Andrew Fedoniouk" <news terrainformatica.com> wrote in message
 news:d17lpi$291e$1 digitaldaemon.com...
 Following program, being compiled
 in -debug,  in runtime ends up with the
 following:

 C:\d\test>test.exe
 Error: AssertError Failure test(8)

 The source of the problem is in int something() -
 it does not have renturn value set.

 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

 Andrew.

 ==test.d================
 static int v = 0;

 int something(int vv)
 {
   v = vv;
 }

 int main(char[][] args)
 {
   something(28);
 }

 ==test.d==EOF=============






Mar 17 2005
prev sibling parent reply xs0 <xs0 xs0.com> writes:
Charles wrote:
 Yea we've been trying to get Walter to make this a compile time error
 forever, he stands alone on the 'shut-up code' argument last I read.
 
 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go further and
 say 'not-all control paths return a value' should be a compile time error.

Well, as far as I am concerned, Walter does have a point, although it still could check whether there is any return statement at all (like in OP's case), and produce an error in the case there isn't. As for the example of where it's not an error: Something[] things; Something get(int id) { int pos=0; for (int a=0; a<things.length; a++) if (things[a].id==id) { return things[a]; } else if (things[a] is null) { return (things[a]=new Something(id)); } } Now, when the compiler sees this it will figure that the for loop can end, and there is no return after it. I, however, know that things[] is always long enough to contain a null and so the error will never happen. OTOH, if I put "return null" at the end just to silence the compiler, if there is actually a bug and things[] doesn't contain a null, I won't get the error here, where I should, but somewhere else, and it will also be the wrong error "someVar is null" instead of "things[] didn't contain a null".. xs0
Mar 16 2005
parent Andy Friesen <andy ikagames.com> writes:
xs0 wrote:
 Charles wrote:
 
 Yea we've been trying to get Walter to make this a compile time error
 forever, he stands alone on the 'shut-up code' argument last I read.

 Can anyone give me a situation where no return is NOT an error, and
 therefore should not be caught at compile time ?  I'd even go further and
 say 'not-all control paths return a value' should be a compile time 
 error.

Well, as far as I am concerned, Walter does have a point, although it still could check whether there is any return statement at all (like in OP's case), and produce an error in the case there isn't. As for the example of where it's not an error: Something[] things; Something get(int id) { int pos=0; for (int a=0; a<things.length; a++) if (things[a].id==id) { return things[a]; } else if (things[a] is null) { return (things[a]=new Something(id)); } } Now, when the compiler sees this it will figure that the for loop can end, and there is no return after it. I, however, know that things[] is always long enough to contain a null and so the error will never happen. OTOH, if I put "return null" at the end just to silence the compiler, if there is actually a bug and things[] doesn't contain a null, I won't get the error here, where I should, but somewhere else, and it will also be the wrong error "someVar is null" instead of "things[] didn't contain a null"..

I think the correct way to "shut the compiler up" in this case is to add an "assert(false);" statement to the end of the function. This lets the compiler know that execution must never reach that point, and, even better, it lets the people reading the code know that execution must never reach that point. All that's necessary is for DMD's flow analysis stuff to check for assert(false); -- andy
Mar 16 2005
prev sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Andrew Fedoniouk" <news terrainformatica.com> wrote:

[...]
 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

Please describe an _algorithm_ that checks reliably for variables not initialized during runtime, because not having a `return' processed in a function during runtime is the same as leaving the implicit return value uninitialized. Otherwise just turn -w on for ever, if you want the compiler to nitpick on your code. -manfred
Mar 16 2005
parent reply "Andrew Fedoniouk" <news terrainformatica.com> writes:
 Please describe an _algorithm_ that checks reliably for variables not
 initialized during runtime, because not having a `return' processed
 in a function during runtime is the same as leaving the implicit
 return value uninitialized.

Theoretically such _algorithm_ does exist as each program is just a finite state automata, but practically full implementation is not feasible. D and Java deal with this by assigning implicitly null/0 to all variables (including return value). And this is good. My point is simple: if you can recognize "no return value" situation then this should not be a warning but just an error (which it is). I understand that for pre-0.117 versions there was only one way to deal with it - to place throw ErrorAssert at the end of function body block. But now this solution is obsolete I guess. Andrew. "Manfred Nowak" <svv1999 hotmail.com> wrote in message news:d1952k$s6n$1 digitaldaemon.com...
 "Andrew Fedoniouk" <news terrainformatica.com> wrote:

 [...]
 IMO, either this code must not compile at all or
 flag -w (warnings) should be 'on' by default.

Please describe an _algorithm_ that checks reliably for variables not initialized during runtime, because not having a `return' processed in a function during runtime is the same as leaving the implicit return value uninitialized. Otherwise just turn -w on for ever, if you want the compiler to nitpick on your code. -manfred

Mar 16 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Andrew Fedoniouk" <news terrainformatica.com> wrote:

 Theoretically such _algorithm_ does exist as each program is
 just a finite state automata,
 but practically full implementation is not feasible.

Agreed, but only because I did not express precisely, what I was talking of.
 D and Java deal with this by assigning implicitly null/0 to all
 variables (including return value).
 And this is good.

But this assignment is done at compile time, while my request was on checking for runtime assignements. But I admit that this might be nitpicking on my words: I wanted to ask for an _algorithm_ that checks if every variable is used at runtime or initialized to some useful value at runtime, thereby considering the value of the automatic initialization as not useful under every circumstances. Do you admit that the existence of any such _algorithm_ implies a solution to the halting problem?
 My point is simple: if you can recognize "no return value"
 situation then this should not be a warning but just an error
 (which it is). 

To issue the warning "no return value at the end of the function" the compiler has to check only the last statement of the function nothing else, and as it has been pointed out in this thread, the missing of such a `return' is not a sure indication for an error. And if you are content with automatic initializations you shouldn't demand a compile time error instead of a runtime error, but the automatic returning of a default value, if the end of the value returning function is reached. -manfred
Mar 16 2005
parent reply "Andrew Fedoniouk" <news terrainformatica.com> writes:
 To issue the warning "no return value at the end of the function"
 the compiler has to check only the last statement of the function
 nothing else, and as it has been pointed out in this thread, the
 missing of such a `return' is not a sure indication for an error.

As far as I can see Walter is already doing analysis of AST for exit points ( fallOffEnd() method ). Not sure though - just took a brief look. So detection of "not all control paths return a value" is already there. BTW: "not all control paths return a value" in C is a warning and in Java it is an error - will not compile at all. I cannot see any reasons to go C way here. Do you? Andrew. "Manfred Nowak" <svv1999 hotmail.com> wrote in message news:d1af1t$2ce7$1 digitaldaemon.com...
 "Andrew Fedoniouk" <news terrainformatica.com> wrote:

 Theoretically such _algorithm_ does exist as each program is
 just a finite state automata,
 but practically full implementation is not feasible.

Agreed, but only because I did not express precisely, what I was talking of.
 D and Java deal with this by assigning implicitly null/0 to all
 variables (including return value).
 And this is good.

But this assignment is done at compile time, while my request was on checking for runtime assignements. But I admit that this might be nitpicking on my words: I wanted to ask for an _algorithm_ that checks if every variable is used at runtime or initialized to some useful value at runtime, thereby considering the value of the automatic initialization as not useful under every circumstances. Do you admit that the existence of any such _algorithm_ implies a solution to the halting problem?
 My point is simple: if you can recognize "no return value"
 situation then this should not be a warning but just an error
 (which it is).

To issue the warning "no return value at the end of the function" the compiler has to check only the last statement of the function nothing else, and as it has been pointed out in this thread, the missing of such a `return' is not a sure indication for an error. And if you are content with automatic initializations you shouldn't demand a compile time error instead of a runtime error, but the automatic returning of a default value, if the end of the value returning function is reached. -manfred

Mar 16 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Andrew Fedoniouk" <news terrainformatica.com> wrote:

[...]
 BTW:
   "not all control paths return a value" in C is a warning
 and in Java it is an error - will not compile at all.
 
 I cannot see any reasons to go C way here. Do you?

I see at least one reason: distribution of return statements over several control paths increases computational complexity. Reasonings: increase of computational complexity ---> severe sign for increased needs on human factors in understanding the code. ---> sign of reduced maintainability ---> increased costs ---> contradiction to a main goal of the design of D Although cost reduction is a main goal in the design of D this NG has not evolved any cost model. So I cannot prove in an accepted way the increase of costs by introducing automatic checking of all control paths for the existence of a `return'. Conclusion: Having more than one return in a function is bad style and the compiler should not support bad style. -manfred
Mar 17 2005
next sibling parent reply Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Manfred Nowak schrieb am Thu, 17 Mar 2005 11:54:38 +0000 (UTC):
 "Andrew Fedoniouk" <news terrainformatica.com> wrote:

 [...]
 BTW:
   "not all control paths return a value" in C is a warning
 and in Java it is an error - will not compile at all.
 
 I cannot see any reasons to go C way here. Do you?

I see at least one reason: distribution of return statements over several control paths increases computational complexity. Reasonings: increase of computational complexity ---> severe sign for increased needs on human factors in understanding the code. ---> sign of reduced maintainability ---> increased costs ---> contradiction to a main goal of the design of D Although cost reduction is a main goal in the design of D this NG has not evolved any cost model. So I cannot prove in an accepted way the increase of costs by introducing automatic checking of all control paths for the existence of a `return'. Conclusion: Having more than one return in a function is bad style and the compiler should not support bad style.

Are your working on memory restrained devices? It's the only place where the one-function-one-return style is usefull. Unless your are solving fairly trivial problems your functions will get some complexity and trying to use one return per function can drastically increase the complexity further(-> goto). Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCOXQR3w+/yD4P9tIRAp1gAKC+7GREhS5N7mGTrAdhX1M4uMTdagCgpnlh f3rKp18jej4HeazWJusi6j0= =/vkK -----END PGP SIGNATURE-----
Mar 17 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> wrote:

[...]
 Are your working on memory restrained devices? It's the only
 place where the one-function-one-return style is usefull.

Please explain your statement. I do not see any correlation between the facts in your first sentence and the statement in your second sentence. But if you want to state, that memory is cheap and that this cheapness should have consequences to programming and therefore language design you might be right. For example the richness of types in C might stem from the fact that memory was expensive in the times when C was designed. Do we really need byte, short, int and long? If memory is cheap only one type will do: long. If memory is cheap we can easily get rid of the uninitialized/unused variable problem at least at runtime: accompany every variable with a state register capable of containing the states DECLARED, INITIALIZED, USED and make sure that every assignment toggles the state from DECLARED to INITIALIZED, that every lookup throws an exception if the state shows DECLARED and otherwise the state is set to USED. Finally, when the function/program terminates make sure, that for every variable the state is USED. -manfred
Mar 18 2005
parent Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Manfred Nowak schrieb am Fri, 18 Mar 2005 09:05:28 +0000 (UTC):
 Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> wrote:

 [...]
 Are your working on memory restrained devices? It's the only
 place where the one-function-one-return style is usefull.

Please explain your statement. I do not see any correlation between the facts in your first sentence and the statement in your second sentence.

Compare the unoptimized assembler outputs of a reasonable complex function with several potential return points using gotos or multiple returns. Depending on your very source code the one-return style usually saves you a few bytes in the executeable. If you don't have to count the bytes I'd recomend to use D's "nested" functions to clean up your code. Thomas
 For example the richness of types in C might stem from the fact 
 that memory was expensive in the times when C was designed. Do we 
 really need byte, short, int and long? If memory is cheap only one 
 type will do: long.

Memory isn't the only limited resource. Compare float+float, int+int, and long+long in a benchmark.
 If memory is cheap we can easily get rid of the 
 uninitialized/unused variable problem at least at runtime: 
 accompany every variable with a state register capable of 
 containing the states DECLARED, INITIALIZED, USED and make sure 
 that every assignment toggles the state from DECLARED to 
 INITIALIZED, that every lookup throws an exception if the state 
 shows DECLARED and otherwise the state is set to USED. Finally, 
 when the function/program terminates make sure, that for every 
 variable the state is USED.

This would be a nice feature for debug builds. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCOqGK3w+/yD4P9tIRAj/SAJ9fQlJ8MaTXfGiGhvWAZkAitGTcJACggY86 UGVCkUgN/DtbAv/UjEa173c= =aTVg -----END PGP SIGNATURE-----
Mar 18 2005
prev sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Manfred Nowak wrote:

 Conclusion: Having more than one return in a function is bad style 
 and the compiler should not support bad style.

I'm not sure that eg. adding a flag variable or using goto is better ? (being the usual workarounds, for languages with just one return path) Having several return statements is a very common form to use.... See: http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html http://c2.com/cgi/wiki?GuardClause Just because it *could* be bad style, does not mean that it always is ? Sometimes using "return" or "break" is the clearest way of expression. But I haven't seen many people, except Walter, use gotos beyond 90's :-) --anders PS. Pre-condition contracts could be used to check *programmer* params. This was just one example of when multiple returns could be useful.
Mar 17 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Anders F Björklund <afb algonet.se> wrote:

[...]
 I'm not sure that eg. adding a flag variable or using goto is
 better ? (being the usual workarounds, for languages with just
 one return path) 

You are right that my argument of increased computational complexity might be too short sighted, because my reasonings on increased computational complexity do not hold, when the increased computational complexity serves a task that must be done otherwise by the human factor. You are right that multiple `return's can be replaced by flag variables or gotos, thereby obfuscating the existence of multiple exit points. So the question arises whether multiple exit points are imposed on the code from the underlying problem, with the reasoning, that their existence is not a sign of bad style. And if they are imposed from the underlying problem how they are dealed with best.
 Having several return statements is a very common form to
 use.... See: 
 http://www.refactoring.com/catalog/replaceNestedConditionalWithGu
 ardClauses.html http://c2.com/cgi/wiki?GuardClause

As always it is not proved, that the use of this "refactoring" decreases the costs. I prefer another style than that suggested in the first example: <example> bit exceptions= _isDead || _isSeparated || _is Retired; if( ! exceptions ) result= normalPayAmount; else throw new exception( "not yet implemented"); return result; </example> as a first implementation and then filling out the cases for the exceptions.
 Just because it *could* be bad style, does not mean that it
 always is ? Sometimes using "return" or "break" is the clearest
 way of expression. 

Agreed, but how can you prove that multiple exit points are imposed on the code from the underlying problem?
 But I haven't seen many people, except Walter, use gotos beyond
 90's :-) 

gotos are not always a sign of bad style. Forward gotos may have their right of existance. Otherwise you have to declare multiple returns as bad style, because, as you stated yourself, multiple returns are just replacements of forward gotos to the one and only return at the end of a function. -manfred
Mar 18 2005
parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Manfred Nowak wrote:

Having several return statements is a very common form to
use.... See: 
http://www.refactoring.com/catalog/replaceNestedConditionalWithGu
ardClauses.html http://c2.com/cgi/wiki?GuardClause

As always it is not proved, that the use of this "refactoring" decreases the costs. I prefer another style than that suggested in the first example: <example> bit exceptions= _isDead || _isSeparated || _is Retired; if( ! exceptions ) result= normalPayAmount; else throw new exception( "not yet implemented"); return result; </example> as a first implementation and then filling out the cases for the exceptions.

Yes, you are right in that these refactorings usually swing both ways... For some code, it makes sense to convert from flags into single returns. And for other code, it is better to use flags and gotos - as suggested. This does not make either of them "bad" (in general) Just in some cases. So I still don't see how you say that "multiple returns are bad style" ? BTW; Refactoring is a good book to read, or at least brush up on the concept: http://martinfowler.com/books.html#refactoring
But I haven't seen many people, except Walter, use gotos beyond
90's :-)  

gotos are not always a sign of bad style. Forward gotos may have their right of existance. Otherwise you have to declare multiple returns as bad style, because, as you stated yourself, multiple returns are just replacements of forward gotos to the one and only return at the end of a function.

I didn't say that Walter's code is that bad... ( did I? :-) ) Just that some people can't stand the smell of "goto", and thus will have nothing to do with it - even if would help them a lot. Most compilers, and I believe also DMD, weighs the cost of: a) doing the return statement "inline" b) branching to an end return "block" Usually it depends on the return value, and the amount of cleanup. (including both exceptions, and tearing down stack frame and such) Fortunately, D - being a language for adults, let's *us* choose ? :-) Some times even TOO much... ("How would you like your strings, sir?" "UTF-8 or UTF-16?"; "What programming paradigm do you want today?" etc) --anders
Mar 18 2005