Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] [ANN] The Missing Library
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Nicolas Cannasse <warplayer@f...>
Subject: Re: [Caml-list] Re: Common IO structure
[...]
> I guess you mean this one from a previous mail:
>
> class ['a,'b] input = object
>     method read : 'a
>     method nread :  int -> 'b
>     method close_in : unit
> end
>
> class ['a,'b,'c] output = object
>     method write : 'a
>     method nwrite : 'b
>     method close_out : 'c
> end
>
> I doubt this is very practical. Consider you want to write Unicode
> characters into a file (I think a common example). The file as such is a
> byte stream, but you want an additional Unicode interface that converts
> implicitly to, say UTF-8. With your idea of generalised channel, the
> only way to do this is to build layers, something like
>
> let file_as_byte_channel = new file_out_channel "name" in
> let file_as_uni_channel = new convert_utf8_to_byte file_as_byte_channel
>
> Call file_as_byte_channel # write to output a byte, and call
> file_as_uni_channel # write to output a Unicode character. You don't
> have a single object that can do both, however. Even worse: If you want
> to use both interfaces alternately, you have to be careful to flush
> buffers at the right time (in the case there are buffers).

I don't know so much about UTF-8, but does it accept normal bytes ? For
example, ANSI chars are converted to identity by UTF-8, aren't they ? So to
write text only you only need to keep the second instance. Of course if
you're dealing with a channel that can write both binary data (without any
conversion) and text data (with UTF-8) the best is to write an adaptator
that will enable you to do the both, and flush the buffers for you. But
we're already out of the common example you're describing.

Layered IO are powerful. This is how it works in Java : you create for
example a ZipOutputStream with an existing OutputStream. Of course it's
possible that the ZipOutputStream have its own internal buffer, so you have
to be very careful to flush it before writing something directly to the
underlying OutputStream.

Pseudo code :
    use my ouputstream
        create a new zip outputstream wrapped on my outputstream
        write contents to it
        flush
    continue using my outputstream

That's same for UTF-8/binary streams.
More interesting, for example in Java you have a CRC32OutputStream, you can
put in at any layer you want, and at any time extract the CRC32 calculated
from all the data that went through it.

> I think it is better to have two methods, one for the polymorphic case,
> and one for strings. The latter plays a special role, simply because all
> I/O finally is string I/O.

I don't agree with this.
Most of IO are (char,string) IO that's true but some are not, I already show
example that were (bool,(int * int)) output.
Of course, you can always define the following :

class type ['a,'b] abstract_input = object
        method read : 'a
        method read_buf : 'b
        ....
end

class type ['a] input = ['a,string] abstract_input

So having one more polymorphic parameter is not so troublesome, and can
actually help.

Regards,
Nicolas Cannasse

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners