www.digitalmars.com         C & C++   DMDScript  

D - eof, or EofException?

reply "Kris" <someidiot earthlink.net> writes:
As part of a D Servlet container, I'm putting together yet-another IO
package that follows the Java approach more closely (separate input and
output streams, with decorator-style filters).

I'd like to solicit opinion on whether it should remain "traditional"
regarding an eof (-1) return from the read() methods, or whether it should
migrate to an EofException strategy?

Boundary-condition examples would be particularly appreciated.
Feb 27 2004
next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Exceptions should be reserved for exceptional conditions.

An eof condition is not exceptional; it is expected any time one reads from
an input stream, so I would say it does not warrant an exception.

"Kris" <someidiot earthlink.net> wrote in message
news:c1o3dk$2mr1$1 digitaldaemon.com...
 As part of a D Servlet container, I'm putting together yet-another IO
 package that follows the Java approach more closely (separate input and
 output streams, with decorator-style filters).

 I'd like to solicit opinion on whether it should remain "traditional"
 regarding an eof (-1) return from the read() methods, or whether it should
 migrate to an EofException strategy?

 Boundary-condition examples would be particularly appreciated.
Feb 27 2004
next sibling parent reply Sean Kelly <sean ffwd.cx> writes:
Matthew wrote:
 Exceptions should be reserved for exceptional conditions.
 
 An eof condition is not exceptional; it is expected any time one reads from
 an input stream, so I would say it does not warrant an exception.
Definately. Java is slightly broken in this respect, as it tends to want to use exceptions for flow control. Sean
Feb 27 2004
parent reply Stephan Wienczny <wienczny web.de> writes:
Sean Kelly wrote:
 Matthew wrote:
 
 Exceptions should be reserved for exceptional conditions.

 An eof condition is not exceptional; it is expected any time one reads 
 from
 an input stream, so I would say it does not warrant an exception.
Definately. Java is slightly broken in this respect, as it tends to want to use exceptions for flow control. Sean
Exceptions should be exceptions and have not to appear in normal control flow. Maybe we should invent something new.....
Feb 27 2004
parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Stephan Wienczny wrote:

 Exceptions should be exceptions and have not to appear in normal control 
 flow. Maybe we should invent something new.....
In what extent? EOF is something a user *MUST* check, as opposed to an exception which can be passed upwards. So i would believe a return value is most desirable. If the user tries to read past EOF, he should get an exception anyway. :> The difference is probably in the fact that Java's exceptions *must* be caught, or if they are promoted, then explicitly. -eye
Feb 27 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Ilya Minkov wrote:

 Stephan Wienczny wrote:

 Exceptions should be exceptions and have not to appear in normal 
 control flow. Maybe we should invent something new.....
In what extent? EOF is something a user *MUST* check, as opposed to an exception which can be passed upwards.
Actually, if the user is apsolutly sure that they know the size of the file, they don't need to check for EOF. For example if they are just reading of the first few lines. Actually in that case the overflow exception is useful.
 So i would believe a return value is most desirable. If the user tries 
 to read past EOF, he should get an exception anyway. :>
Sure, because you are not forced to check the return value. But that does bring up a point. Parhaps in some cases you should be forced to check the return value (use). ie checked int func() { } int x = func(); //ok func(); //error
 The difference is probably in the fact that Java's exceptions *must* 
 be caught, or if they are promoted, then explicitly.

 -eye
-- -Anderson: http://badmama.com.au/~anderson/
Feb 27 2004
parent reply Sean Kelly <sean ffwd.cx> writes:
J Anderson wrote:
 Sure, because you are not forced to check the return value.  But that 
 does bring up a point. Parhaps in some cases you should be forced to 
 check the return value (use).  ie
 
 checked int func() { }
 
 int x = func(); //ok
 func(); //error
Why? The user should always have the option of ignoring error conditions, even to his own detriment. Besides, with exceptions I could always do this: try{ funcThatThrows(); } catch( ... ) {} Using exceptions for flow control creates difficult situations as it prevents the user from easily separating expected failure conditions from exceptional ones. The extreme example of this is the bit of code above where every function call is wrapped in a try block in order to preserve execution flow, and consequently might ignore truly diastorous errors, like out of memory conditions. Sean
Feb 27 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Sean Kelly wrote:

 J Anderson wrote:

 Sure, because you are not forced to check the return value.  But that 
 does bring up a point. Parhaps in some cases you should be forced to 
 check the return value (use).  ie

 checked int func() { }

 int x = func(); //ok
 func(); //error
Why? The user should always have the option of ignoring error conditions, even to his own detriment. Besides, with exceptions I could always do this:
The return value may not nessarily be an error condition (note that I'm not talking about exceptions here). ie checked int func() { } int x = func(); //ok func(); //error int func() { } int x = func(); //ok func(); //ok
 try{ funcThatThrows(); }
 catch( ... ) {}

 Using exceptions for flow control creates difficult situations as it 
 prevents the user from easily separating expected failure conditions 
 from exceptional ones.  The extreme example of this is the bit of code 
 above where every function call is wrapped in a try block in order to 
 preserve execution flow, and consequently might ignore truly 
 diastorous errors, like out of memory conditions.
Exactly, your just amplifying my point. Exceptions are not good for flow of control (most of the time).
 Sean
Well it would still be possible to ignore (well type some extra code) it is just a kinda double check for cases where most of the time you need to check/use the value and where exceptions are not appropriate. -- -Anderson: http://badmama.com.au/~anderson/
Feb 27 2004
prev sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
Sean Kelly wrote:

 int x = func(); //ok
 func(); //error
Why? The user should always have the option of ignoring error conditions, even to his own detriment.
They still would: cast(void) func();
  Besides, with exceptions I could always do this:
 try{ funcThatThrows(); }
 catch( ... ) {}
Yes, but at least it makes it verbose.
 Using exceptions for flow control creates difficult situations as it 
 prevents the user from easily separating expected failure conditions 
 from exceptional ones.  The extreme example of this is the bit of code 
 above where every function call is wrapped in a try block in order to 
 preserve execution flow, and consequently might ignore truly diastorous 
 errors, like out of memory conditions.
That would be good to avoid. :> -eye
Feb 28 2004
prev sibling parent reply "Jan-Eric Duden" <jeduden whisset.com> writes:
Consider following pseude-code :

try
{
    read(&b,4);
    read(&c,10);
    read(&d,13);
    read(&e,3);
    read(&f,14);
}
catch(readexception)
{

}

and:
    if(!read(&b,4))
        return false;
    if(!read(&c,10))
        return false;
    if(!read(&d,13))
        return false;
    if(!read(&e,3))
        return false;
    if(!read(&f,14))
        return false;


I would say the first variant looks more elegant and behaves better when
changes need to be made to the code.

-- 
Jan-Eric Duden
"Ilya Minkov" <minkov cs.tum.edu> wrote in message
news:c1oe20$9b3$1 digitaldaemon.com...
 Stephan Wienczny wrote:

 Exceptions should be exceptions and have not to appear in normal control
 flow. Maybe we should invent something new.....
In what extent? EOF is something a user *MUST* check, as opposed to an exception which can be passed upwards. So i would believe a return value is most desirable. If the user tries to read past EOF, he should get an exception anyway. :> The difference is probably in the fact that Java's exceptions *must* be caught, or if they are promoted, then explicitly. -eye
Feb 27 2004
next sibling parent reply Sean Kelly <sean ffwd.cx> writes:
What about:

if( !read(&b,4) ||
     !read(&c,10) ||
     !read(&d,13) ||
     !read(&e,3) ||
     !read(&f,14) )
{
     return false;
}
Feb 27 2004
parent reply "Jan-Eric Duden" <jeduden whisset.com> writes:
It is not clear in what order the reads are being executed.

And may be you want to do some stuff in between .

-- 
Jan-Eric Duden
"Sean Kelly" <sean ffwd.cx> wrote in message
news:c1om5f$oas$1 digitaldaemon.com...
 What about:

 if( !read(&b,4) ||
      !read(&c,10) ||
      !read(&d,13) ||
      !read(&e,3) ||
      !read(&f,14) )
 {
      return false;
 }
Feb 28 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Jan-Eric Duden wrote:

It is not clear in what order the reads are being executed.

  
It is perfectly clear.
And may be you want to do some stuff in between.
  
That is a good point. -- -Anderson: http://badmama.com.au/~anderson/
Feb 28 2004
parent reply "Jan-Eric Duden" <jeduden whisset.com> writes:
if( !read(&b,4) ||
     !read(&c,10) ||
     !read(&d,13) ||
     !read(&e,3) ||
     !read(&f,14) )
{
     return false;
}
It is not clear in what order the reads are being executed.
It is perfectly clear.
Is that order defined in the language specification? -- Jan-Eric Duden "J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c1qhut$umj$4 digitaldaemon.com...
 Jan-Eric Duden wrote:

It is not clear in what order the reads are being executed.
It is perfectly clear.
And may be you want to do some stuff in between.
That is a good point. -- -Anderson: http://badmama.com.au/~anderson/
Feb 29 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Jan-Eric Duden wrote:

if( !read(&b,4) ||
    !read(&c,10) ||
    !read(&d,13) ||
    !read(&e,3) ||
    !read(&f,14) )
{
    return false;
}
    

It is not clear in what order the reads are being executed.



      
It is perfectly clear.
Is that order defined in the language specification?
Yep (part of the C specification which is carried on to D), the || is a short circuit, so it must go in the order given. If !read(&b,4), it must stop there. However, if you used | then it would need to test everything in the sequence regardless. If there wasn't this certainly, the short circuit would be useless. Note that in some cases the compiler can optimise short circuits, but only when it can be absolutely sure that there will be no side effect, so that is no problem. -- -Anderson: http://badmama.com.au/~anderson/
Feb 29 2004
parent reply "Jan-Eric Duden" <jeduden whisset.com> writes:
I didn't no that there was a difference between || and | in terms of the
evaluation order.
I just remembered that for most of the time there is no defined order. :)

-- 
Jan-Eric Duden
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:c1sq61$1ukb$1 digitaldaemon.com...
 Jan-Eric Duden wrote:

if( !read(&b,4) ||
    !read(&c,10) ||
    !read(&d,13) ||
    !read(&e,3) ||
    !read(&f,14) )
{
    return false;
}


It is not clear in what order the reads are being executed.
It is perfectly clear.
Is that order defined in the language specification?
Yep (part of the C specification which is carried on to D), the || is a short circuit, so it must go in the order given. If !read(&b,4), it must stop there. However, if you used | then it would need to test everything in the sequence regardless. If there wasn't this certainly, the short circuit would be useless. Note that in some cases the compiler can optimise short circuits, but only when it can be absolutely sure that there will be no side effect, so that is no problem. -- -Anderson: http://badmama.com.au/~anderson/
Feb 29 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Jan-Eric Duden wrote:

I didn't no that there was a difference between || and | in terms of the
evaluation order.


  
Also what is important is that | is used for binary operations where as || is not. The same applies to & and && as in the following example: int a = 2; int b = 4; if ( a & b ) printf("a & b\n"); //if a AND b != 0 if ( a && b ) printf("a && b\n"); //if a != 0 and then if b != 0 Outputs: a && b
I just remembered that for most of the time there is no defined order. :)
Either your memory is faulty (I'd take it back for a replacement ;) ) or your thinking of a different language. -- -Anderson: http://badmama.com.au/~anderson/
Feb 29 2004
parent "Jan-Eric Duden" <jeduden whisset.com> writes:
-- 
Jan-Eric Duden
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:c1t883$2mpg$1 digitaldaemon.com...
 Jan-Eric Duden wrote:

I didn't no that there was a difference between || and | in terms of the
evaluation order.
Also what is important is that | is used for binary operations where as || is not. The same applies to & and && as in the following example: int a = 2; int b = 4; if ( a & b ) printf("a & b\n"); //if a AND b != 0 if ( a && b ) printf("a && b\n"); //if a != 0 and then if b != 0 Outputs: a && b
yep, that's the obvious difference between || and |. | is bitwise and || is logical.
I just remembered that for most of the time there is no defined order. :)
Either your memory is faulty (I'd take it back for a replacement ;) ) or
your thinking of a different language. There is no defined order for all the other operators. , || and && are the exception. so my assumption was just the safe one. :)
Feb 29 2004
prev sibling parent reply larry cowan <larry_member pathlink.com> writes:
These are short-circuit || ops.  If the left side is true, the right side is not
executed - entire expression must be evaluated left to right, and the first
true stops evaluation and if is satisfied so false is returned.

In article <c1sd0l$18ut$1 digitaldaemon.com>, Jan-Eric Duden says...
if( !read(&b,4) ||
     !read(&c,10) ||
     !read(&d,13) ||
     !read(&e,3) ||
     !read(&f,14) )
{
     return false;
}
It is not clear in what order the reads are being executed.
It is perfectly clear.
Is that order defined in the language specification? -- Jan-Eric Duden "J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c1qhut$umj$4 digitaldaemon.com...
 Jan-Eric Duden wrote:

It is not clear in what order the reads are being executed.
It is perfectly clear.
And may be you want to do some stuff in between.
That is a good point. -- -Anderson: http://badmama.com.au/~anderson/
Feb 29 2004
parent larry cowan <larry_member pathlink.com> writes:
Sorry - my messages were out of order - this was already answered.

In article <c1tu8e$qq8$1 digitaldaemon.com>, larry cowan says...
These are short-circuit || ops.  If the left side is true, the right side is not
executed - entire expression must be evaluated left to right, and the first
true stops evaluation and if is satisfied so false is returned.

In article <c1sd0l$18ut$1 digitaldaemon.com>, Jan-Eric Duden says...
if( !read(&b,4) ||
     !read(&c,10) ||
     !read(&d,13) ||
     !read(&e,3) ||
     !read(&f,14) )
{
     return false;
}
It is not clear in what order the reads are being executed.
It is perfectly clear.
Is that order defined in the language specification? -- Jan-Eric Duden "J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c1qhut$umj$4 digitaldaemon.com...
 Jan-Eric Duden wrote:

It is not clear in what order the reads are being executed.
It is perfectly clear.
And may be you want to do some stuff in between.
That is a good point. -- -Anderson: http://badmama.com.au/~anderson/
Feb 29 2004
prev sibling parent reply X Bunny <xbunny eidosnet.co.uk> writes:
Jan-Eric Duden wrote:

 Consider following pseude-code :
 
 try
 {
     read(&b,4);
     read(&c,10);
     read(&d,13);
     read(&e,3);
     read(&f,14);
 }
 catch(readexception)
 {
 
 }
 
 and:
     if(!read(&b,4))
         return false;
     if(!read(&c,10))
         return false;
     if(!read(&d,13))
         return false;
     if(!read(&e,3))
         return false;
     if(!read(&f,14))
         return false;
 
 
 I would say the first variant looks more elegant and behaves better when
 changes need to be made to the code.
 
could you not justwrite a myread function which wraps read and throws your exception if its required and then call that instead of read directly?
Feb 28 2004
parent reply "Jan-Eric Duden" <jeduden whisset.com> writes:
Of course, i could write my own 'non-standard' stream library...
which fixes all the problems but then it is not the standard stream library
and won't help other people
to prevent bugs.
-- 
Jan-Eric Duden
"X Bunny" <xbunny eidosnet.co.uk> wrote in message
news:c1rjmu$2r77$1 digitaldaemon.com...
 Jan-Eric Duden wrote:

 Consider following pseude-code :

 try
 {
     read(&b,4);
     read(&c,10);
     read(&d,13);
     read(&e,3);
     read(&f,14);
 }
 catch(readexception)
 {

 }

 and:
     if(!read(&b,4))
         return false;
     if(!read(&c,10))
         return false;
     if(!read(&d,13))
         return false;
     if(!read(&e,3))
         return false;
     if(!read(&f,14))
         return false;


 I would say the first variant looks more elegant and behaves better when
 changes need to be made to the code.
could you not justwrite a myread function which wraps read and throws your exception if its required and then call that instead of read
directly?

Feb 29 2004
next sibling parent X Bunny <xbunny eidosnet.co.uk> writes:
Jan-Eric Duden wrote:

 Of course, i could write my own 'non-standard' stream library...
 which fixes all the problems but then it is not the standard stream library
 and won't help other people
 to prevent bugs.
Thats the crux of it really. You think by having this feature it will help people to prevent bugs. I disagree because it introduces yet another level of complexity were it isnt required leading to bugs that way. I agree that if that addition complexity is required then it could be part of another library not the standard streams.
Feb 29 2004
prev sibling parent reply Sean Kelly <sean ffwd.cx> writes:
Jan-Eric Duden wrote:
 Of course, i could write my own 'non-standard' stream library...
 which fixes all the problems but then it is not the standard stream library
 and won't help other people to prevent bugs.
I guess it's a matter of background. I'm used to C++ where there's no hand-holding at all and I like it that way. Others from a Java background might have a different opinion. I personally hate the Java standard library and would code my own rather than use a re-packaged duplicate in D :) Sean
Feb 29 2004
parent "Jan-Eric Duden" <jeduden whisset.com> writes:
I guess you can't make everyone happy. :)
You can just hope that you make the majority happy and I guess that's
already difficult enough. :)

-- 
Jan-Eric Duden
"Sean Kelly" <sean ffwd.cx> wrote in message
news:c1t9s4$2pb8$1 digitaldaemon.com...
 Jan-Eric Duden wrote:
 Of course, i could write my own 'non-standard' stream library...
 which fixes all the problems but then it is not the standard stream
library
 and won't help other people to prevent bugs.
I guess it's a matter of background. I'm used to C++ where there's no hand-holding at all and I like it that way. Others from a Java background might have a different opinion. I personally hate the Java standard library and would code my own rather than use a re-packaged duplicate in D :) Sean
Feb 29 2004
prev sibling parent Hauke Duden <H.NS.Duden gmx.net> writes:
Matthew wrote:
 Exceptions should be reserved for exceptional conditions.
 
 An eof condition is not exceptional; it is expected any time one reads from
 an input stream, so I would say it does not warrant an exception.
Actually EOF is often an exceptional condition. In most binary file formats you know exactly how much data you need/want to read, since they often follow a pretty strict protocol. For example, there are often length fields describing how many bytes of data follow. So if less bytes are read then it means that the file is corrupted and an exception should be thrown. Also, speaking from my own experiences, lots of porgrammers never bother to check the return value of a read. If read throws an exception at least the caller can catch it and know that the function failed instead of getting a random result caused by uninitialized memory. My stream classes all have two kinds of read functions: one that throws an exception if less bytes are read (which I use most of the time) and one that returns the number of bytes read. The latter one is usually only used for files with a "loose" structure, i.e. files that have points where futher data might or might not follow. Hauke
Feb 28 2004
prev sibling parent Andy Friesen <andy ikagames.com> writes:
Kris wrote:
 As part of a D Servlet container, I'm putting together yet-another IO
 package that follows the Java approach more closely (separate input and
 output streams, with decorator-style filters).
 
 I'd like to solicit opinion on whether it should remain "traditional"
 regarding an eof (-1) return from the read() methods, or whether it should
 migrate to an EofException strategy?
 
 Boundary-condition examples would be particularly appreciated.
I kind of like how the current std.stream handles this. read works like the C fread, returning the number of bytes read. readExact raises an exception if the number of bytes read is not equal to the number asked for. This way you're given the freedom to deal with it however you like. Maybe a 'strict' decorator that achieves this functionality is in order. -- andy
Feb 27 2004