Sunday 7 July 2013

Away from the line: echo in D

edit: spot the bug :) Thanks to Andrei Alexandrescu for pointing out my stupidity.

So... This is going to be a blog about the D programming language. I've been involved in the D community for a while over a year now; with their friendly and patient help I've managed to become quite familiar with the language. I'm not going to attempt to teach you the language in any rigorous manner, for this I would recommend either Ali Çehreli's online book Programming in D (starts from the very basics of programming. Free) or Andrei's tour de force The D Programming Language (for the more experienced reader. Totally worth the money). Instead I'm going to dive in to building some simple programs in D, introducing syntax and features in an entirely ad-hoc manner, the meaning of which will hopefully become obvious by context if not by my explanations. Those coming from C or a related language will likely find the whole experience familiar.

So, without further ado, let's write a "real" program!

import std.stdio : write, writeln;
void main(string[] args)
{
    foreach(arg; args[1..$])
    {
        write(arg, ' ');
    }
    writeln();
}

Remind you of anything? Of course it's the famous utility 
echo
, albeight a very simplified version. We'll build on it later to get a fully-featured implementation. Firstly, let's take a line-by-line look at what we've got so far:

First, we import 
write
and
writeln
from
std.stdio
. We could just write
import std.stdio;
and import the whole module, but it's nice to keep things a little more hygienic.

import std.stdio : write, writeln;

Then comes 
main
, the entry point to the program. Seeing as we're writing
echo
, we're going to need the arguments to the program, so we're including the optional
string[]
argument to
main
to capture them.

void main(string[] args)

We want to print out all the arguments, barring the first argument which is always the executable name, separated by spaces. To iterate over the arguments we are using a 
foreach
loop, accessing each argument in turn through the variable
arg
. In order to skip the first argument, we are actually iterating over a slice of
args
, from index
1
to the end of the array (automatically provided by
$
). This isn't affecting
args
itself, but simply providing us with a narrowed window on to it. For more on slices, see here. We then - for each
arg
  -  
write
the argument followed by a space.

    foreach(arg; args[1..$])
    {
        write(arg, ' ');
    }

finally, we finish things off with a new line, courtesy of 
writeln
.

    writeln();

Hooray! We have a fully working D program that actually does something (vaguely) useful. For those of you who found that a little too obvious, here's an equivalent D program with a lazy functional flavour:

import std.stdio : writeln;
import std.algorithm : joiner;
void main(string[] args)
{
    args[1 .. $].joiner(" ").writeln();
}

If you squint right and don't think too hard, you should be able to get what's happening there (Hint: 
foo(x)
can be rewritten as
x.foo()
). Next time, we'll look at how we can implement some of the command line options to echo, moving towards a fully compliant implementation.

2 comments: