fble-0.5 (2025-07-13,fble-0.4-212-ga8f8ad0f)
In this tutorial we'll learn how to write command line programs that interact with the environment.
Until now we've been writing fble programs that use
/Core/Stdio/StringO%.Run
to output a string:
String@ output = Str|'hello, world'; /Core/Stdio/StringO%.Run(output);
The /Core/Stdio%
library provides a more general interface for writing
fble programs that allows you to access command line arguments, access
standard input, output, and error streams, read and write files, read
environment variables, and return an exit status.
The /Core/Stdio/IO%.Run
function takes a Main@
function with the
following type:
<<@>@>@ Main@ = <<@>@ M@>(Stdio@<M@>, Monad@<M@>, List@<String@>) { M@<Bool@>; };
Here is an example hello world program using this more general interface:
# A hello world program using the Stdio@ interface. Main@ Main = <<@>@ M@>(Stdio@<M@> stdio, Monad@<M@> m, List@<String@> _args) { % O = /Core/Stream/OStream%(m); Unit@ _ <- m.do(O.PutLine(stdio.out, Str|'hello, world')); m.return(True); }; /Core/Stdio/IO%.Run(Main);
Let's break this down
<<@>@ M@>
The Main@
function is polymorphic, parameterized by type M@
. The
first two arguments to the function are stdio
and m
, which are
interfaces supported by the abstract type M@
.
This says your main function can be used with any type M@
that
implements the Stdio@
and Monad@
interfaces. The
/Core/Stdio/IO%.Run
function provides a concrete type of M@
for use
with the fble-stdio
program.
The reason Main@
is polymorphic instead of hard coding the concrete type
for M@
provided by /Core/Stdio/IO%.Run
is to make your main function
more general than just for use with fble-stdio
. For example, you can
write test cases for your main function using a simulated environment.
Stdio@<M@> stdio
The Stdio@<M@>
interface is defined as follows:
<<@>@>@ Stdio@ = <<@>@ M@> { *( # stdin stream IStream@<M@> in, # stdout stream OStream@<M@> out, # stderr stream OStream@<M@> err, # Open the named file for reading. # Returns an input stream for reading. Nothing if unable to open the file. (String@) { M@<Maybe@<IStream@<M@>>>; } read, # Open the named file for writing. # Returns an output stream for writing. Nothing if unable to open the file. (String@) { M@<Maybe@<OStream@<M@>>>; } write, # Gets an environment variable value. (String@) { M@<Maybe@<String@>>; } getenv ); };
The IStream@
and OStream@
are types for reading a sequence of bytes.
The Stdio@
interface represents bytes using the Int@
type:
<<@>@>@ IStream@ = <<@>@ M@> { M@<Maybe@<Int@>>; }; <<@>@>@ OStream@ = <<@>@ M@>(Int@) { M@<Unit@>; };
The fields in
, out
, and err
let you read and write standard
input and output streams.
The fields read
and write
let you open files for reading and writing
respectively.
The field getenv
lets you access the value of an environment variable.
Monad@<M@> m
The Monad@<M@>
interface m
provides a way to sequence operations.
This is needed to have a well defined order of operations when interacting
with input and output streams and files.
List@<String@> args
The args
argument is the list of command line arguments passed when
invoking the program. For example, if you ran your program as:
fble-stdio -p core -I . -m /Foo% -- hello there now
Then the value of args
would be:
List[Str|'hello', Str|'there', Str|'now']
M@<Bool@>;
The result of the Main@
program has type M@<Bool@>
. If you return
True
using m.return(True)
, your program will have exit status 0.
Otherwise your program will have exit status 1.
Write an fble program that prints out a sorted list of the command line arguments passed to it.
Write an fble program that outputs the length of a given file. Try passing the file via standard input and as a file path.
Write an fble program that repeatedly prompts the user for a number and outputs the largest number input so far.
This completes this tutorial series on the fble language. You now understand all the fble language features and can write interesting programs that interact with the environment on the command line. Go forth now and program.
Or you can head back to the Tutorials
page for links
to debug and profiling guides.