OutputRange should be infinite?

Steven Schveighoffer schveiguy at yahoo.com
Tue Oct 9 08:03:45 PDT 2012


On Tue, 09 Oct 2012 09:39:32 -0400, monarch_dodra <monarchdodra at gmail.com>  
wrote:

> On Tuesday, 9 October 2012 at 13:22:28 UTC, Steven Schveighoffer wrote:
>> [SNIP]
>
> I tend to disagree with your examples, because, you are mixing the  
> notion of run-time failure with logic error.

They are one and the same.

Putting into a file that runs out of disk space, and putting into an array  
that runs out of memory.

Take the viewpoint of std.algorithm.copy.  It's been asked to copy from A  
to B, and B cannot accept it.  What does it do?  Saying it has to just  
return success doesn't make any sense.

> For example: "new" New can fail. And you don't know unless you try.
> But new will throw an exception to tell you it failed..
>
> An appender, as you say, is finite in memory, and will end up throwing  
> an exception, yes. You also have a chance to try to catch it and react.

No, these are Errors, not (supposed to be) catchable.

> Over-putting into a finite slice, on the other end, will *assert*. Game  
> over. It is a catch 22: You can't know unless you try, you crash if you  
> do.

I agree, this could have a better interface.  However, I think in terms of  
what to do (assuming we add some way of checking for fullness), if someone  
calls put on an output buffer and that range is not able to handle it, it  
should be an Error/assert as it is now, just like calling front on an  
empty array is an assert.

>
>> I'm not against defining a standard way to say "I'm full", but  
>> proposing it *can't* say that is not the solution.  Clearly, we could  
>> do better in defining a standard way to test for fullness (full  
>> property akin to empty?).  Even so, putting into a non-full range could  
>> generate an error.
>
> Hum... I'm just kind of wondering here: Couldn't we simply have put  
> throw an actual exception? Something along the lines of  
> "OutputRangFullException"? That would be a pretty good compromise.

I think it would work, but I think we still need a way to check for  
fullness.

Here is what I propose:

OutputRange is defined as an entity that consumes data.   If you put data  
into an OutputRange that cannot accept the data, the range has the option  
of asserting or throwing an exception.

TerminatingOutputRange is an extension of OutputRange, but defines bool  
@property full().  R.full returns true if it cannot accept any new data.   
It should assert if you try to put data into a full  
TerminatingOutputRange.  In other words the following sequence should  
always assert or not compile:

static assert(isTerminatingOutputRange!(typeof(r)));
assert(r.full);
r.put(x);

If you try and put into a TerminatingOutputRange that is *not* full,  
behavior reverts to OutputRange (can either assert or throw an exception),  
depending on the assumptions that can be made for that condition.

>>> However, I really don't like having a range tell me "yeah, I'm an  
>>> Output Range", just to choke on the first call to put.
>>
>> What about an input range that is immediately empty?  These are corner  
>> cases, but certainly valid.
>
> Wouldn't "empty" simply answer "true" before even starting? At least it  
> is being honest.

Right, but you seem to be saying the condition that an OutputRange might  
throw on the first call to put is an invalid reaction.  I don't think it  
is any less valid than throwing on the first call to front on an empty  
range.

-Steve


More information about the Digitalmars-d mailing list