|Home | About | Partners | Contact Us|
XLR: Extensible Language and Runtime
At first sight, text I/O in XL looks very similar to Pascal. Here is an example of a program containing very simple text I/O:
import IO = XL.UI.CONSOLE IO.WriteLn "List of 10 first squares:" for I in 1..10 loop IO.WriteLn I, " squared is ", I * I
The approach of featuring a WriteLn procedure as in Pascal was selected because it is the most natural way to display characters. It is convenient (you can display as many items as you want in a single statement), safe (there are no risks of type mismatch as in C), easy to use (there is no need for some complex formatting syntax).
There was a main drawback in Pascal: you could not define WriteLn yourself in Pascal, because there was no way to define procedures taking a variable number of arguments, or arguments of variable types. These problem don't exist in XL.
XL text I/O is implemented in two different packages: XL.TEXT_IO and XL.UI.CONSOLE. The first package deals with text formatting and conversions (for example, converting integers to text). The second package deals with a common form of user interface (UI), which is a text console with three I/O streams (input, output and error), as commonly found in Unix, Linux and many other operating systems supporting the C programming language.
Thread safety: There are more subtle benefits to this approach. For instance, a given I/O is performed using a single function call. By contrast, the C++ approach (using operator<<) requires one call per item being printed. In addition to the obvious code bloat, there is another annoying side effect: it is practically impossible to make C++ text I/O behave well in a multi-threaded environment. A programmer might expect something like cout << "I=" << I << ' ' appear as a sequence of consecutive characters on the output.
However, the best the runtime library can do is keep the character of a single call to an operator<< together, or alternatively wait until the end of line for each thread, which might delay characters for a very long time (and so nobody does that). Of course, C++ programmers believe that leaving the locking responsibility to the caller is the right thing to do. But this is clearly wrong, as illustrated by the locking required to keep internal buffers consistent when emitting individual characters. It would be more efficient to lock once for multiple characters.
By contrast, it is very easy for the characters emitted by a single call to WriteLn (or Write) to be kept consecutive.
Definition of text lines: Another interesting thing with text I/O as implemented in C (and later derived languages such as C++, Java) is that it is built around a rather annoying concept cast, where the concept of line is blurred and replaced with the related concept of end-of-line character. Why does it matter? Because there isn't always an end-of-line character. A line can be represented by records in a database, or the line length may be encoded before each line.
A consequence of this particular cast can be found on the Windows platform, where the end of a line is traditionally represented not with one, but with two characters. On this platform, you can open files in "text mode" or in "binary mode", and the C runtime library has to perform on-the-fly conversion of line endings. Fortunately, this particular conversion is not too complicated.