Stream mixins?

BCS ao at pathlink.com
Sun Nov 11 14:12:42 PST 2007


Reply to Janice,

> On 11/11/07, BCS <ao at pathlink.com> wrote:
> 
>> What you seem to want
>> is to pass a chunk of data. For this you should use the lower level
>> functions.
>
> No, a stream of data. A property of hash functions is that you can
> pass the data all in one chunk, or you can pass it in lots of little
> chunks, but either way you'll get the same answer. If you can accept
> the data a byte at a time, then it should be trivial to turn it into a
> stream.

that is in no way contrdictory with what I sugested. The lowlevel stuff just 
says "here is a lump of bytes to write" the high level stuff says "here is 
an array of uints to incode and write"

> 
>> However, you may have a point in that the write functions may cause
>> issues for some cases. Maybe there should be a WriteStreamLL that
>> just has the non implementation specific stuff. and then have
>> WriteStream extend it with the high level stuff.
>> 
> I may have been misunderstood. I have no problem with a /class/ doing
> high level (or low level) stuff. Putting it all into a class makes
> thing easier for the implementor, because all you have to do is derive
> from the class.
> 
> My complaint was that these functions exist in an /interface/. This
> means that implementers aren't being told exactly what they need to
> implement, and functions which accept such interfaces won't know what
> to expect.
> 
> If it's in an interface, we really need to nail down exactly what the
> functions are supposed to do.

IMHO, they are nailed down exactly:

The write functions will take the given data and convert it to a bit pattern 
that can be sent through a stream and then, with a corresponding call to 
a read, converted back to the original data. This /is/ exact provided that 
you consider the "data on the wire" to be below the level of abstraction 
you are working at. And I think that assumption is valid in most cases.

> 
>> I think it all derives from a design choice of "don't say you will do
>> more than you have to". As an example, if the format was specified,
>> what big-vs.-little endian? Do you pick one and let the other side
>> suffer the overhead? As soon as you start nailing things down,
>> where do you stop? The only logical choices I see are no spec
>> and full spec. At the base level, full spec doesn't work to well.
>
> Again, none of this is a problem for classes. The base class could, if
> desired, implement writeBigEndian() and writeLittleEndian(), and then
> they'd be available for all subclasses.
> 

if you have a writeBigEndian() and writeLittleEndian() what do you do when 
you need to pass something to a function that shouldn't known what enden 
is being used?

void WriteWhateverEndean(OutputStream str)
{
   str. // what here??????
}

really what is needs is something like multiple inheritance but without the 
problems.


> But the minute you put stuff like that into an interface, with no
> handy class to derive from, you just make w-a-y too much work (and
> potential for errors) for the implementor.
>

interface WithLotsOfStuff
{...}

template LotsOfStuff() {...}

class Use : WithLotsOfStuff
{
 mixin LotsOfStuff!();
}
 
That's not much work. If they want something different than one of the defaults, 
then they need to do the work anyway

>> You still can get all the benefits of nailing down the format with,
>> as you pointed out, a mixin.
>> 
> Yes. That's what I was asking for.
> 
> Although, even in that case, it would still be advisable to change the
> docs for those interfaces from "this is implementation specific" to
> "here is exactly what it must do".
> 

Ok. Big or little endian? when sending an array should the length be 16, 
32, 64 or 128 bits? when sending floats, should they be sent in IEEE format 
(Note some systems don't use IEEE) What about real, 80bit  or 128bit floats?

My point is not that this should not be defined, my point is that the INTERFACE 
is the wrong place to define it. The correct place is the code (in a mixin) 
that implements it. The questions mentioned above only scratch the surface 
of the issue. If you nail them down in the interface than immediately someone 
is out in the cold where what you picked doesn't work. The correct solution 
IMHO, as glossed over in the code example above, is to define this in the 
implementing code and then have the code using the interface ignore the differences. 
This does require that the user be carful to keep things paired up properly 
but that is no more of an issue with my solution than it is with yours.

> you should not
> be expected to have hand-code your own printf()!
> 

No objection there :)





More information about the Digitalmars-d mailing list