(* Welcome! In this program, we'll take a look at the Reader module found
* inside Async.Std. The Reader module defines an abstract type t, where an
* instance of type Reader.t represents an entity that's capable of reading
* from something like a file or TCP connection. For example, you can construct
* a reader for stdin and read from the user (that's what we'll do in this
* program). Or, you can construct a reader from a file and read the contents
* file (we'll do this soon). Or, you can construct a reader from a TCP
* connection and read messages from another process (we'll do this in a later
* chapter).
*
* You may notice that an object of type Reader.t is very similar to an
* instance of type Pipe.Reader.t. That's because they are very similar. A
* Reader.t is like the reader end of the pipe, except that the writer end of
* the pipe may be something like a file or TCP connection. In fact, the two
* are so similar, there are functions in the Reader module for converting the
* reader end of a pipe into a Reader.t and for converting a Reader.t into the
* reader end of a pipe!
*
* In this chapter, we'll see a very short example of how to use the Reader
* module by reading a line from standard in and printing it to the screen. *)
open Core.Std
open Async.Std
let main () : unit Deferred.t =
(* First up, we create a Reader.t from stdin. Luckily, the Reader module has
* exactly this already! The only hiccup is that Reader.stdin is of type
* `Reader.t Core.Std.Lazy.t`. It's not too important what that means; all we
* have to do is call Lazy.force to get the Reader.t we're looking for. *)
let stdin = Lazy.force Reader.stdin in
(* The Reader module has a lot of functions to read from a Reader.t:
* Reader.read, Reader.read_char, Reader.really_read, etc. For now, we just
* want to read a single from the user, so we'll use Reader.read_line. As
* the name suggests, it reads all the data up to and including the newline
* character.
*
* Of course, reading could go wrong. For example, we could read from a file
* that's been deleted or read from a TCP connection that's been closed. So,
* Reader.read_line, and all the other reading functions in the Reader
* module, return a Read_result.t. A Read_result.t is either `Eof (signifying
* we've hit the end of the reader) or an `Ok x, where the x is the data
* we're after. If our read here doesn't work, we'll just print "error".
* Otherwise, we'll print whatever line the user typed in. *)
Reader.read_line stdin >>| function
| `Eof -> print_endline "error"
| `Ok x -> print_endline x
(* Go ahead and run this program, then type something in and hit enter! *)
let () =
Command.(run (async ~summary:"" Spec.empty main))