Chapter 1. First Steps

The D programming language is a strongly typed, natively compiled computer language. If you're familiar with C, C++, or Java, you'll find that you're very much at home with D, as it retains most of the constructs with which many programmers are already comfortable. At the same time, D is different in ways both subtle and striking, successfully combining a number of programming styles while managing to retain a succinct and reasonably simple grammar.

D is designed as a systems language, although it is suitable for a wide range of projects, from small programs developed by one person to large-scale, commercial applications worked on by dozens of developers. We were going to tell you all about the advantages of D right here, but Walter Bright stated those so eloquently in the foreword to this book, that we dropped the idea. If you have not yet read the foreword, we highly recommend doing so.

Tango is a general-purpose companion library that provides a rich variety of practical functionality. The Tango library is open source software, with a strong following and an increasingly large number of compatible add-ons available. Tango's design is intended to satisfy a desire for both efficiency and flexibility, mirroring two principal attributes of D itself. The application programming interface (API) offers many services you would expect to find in a modern software development toolkit, such as containers, compression algorithms, threads, fibers, networking, and text manipulation.

This book, Learn to Tango with D, is an introduction to both the D language and the Tango library. The key features of both are presented in a condensed and fast-paced format, where the goal is to give you sufficient information to become productive quickly and effectively.

This chapter will give you an overview of the language fundamentals, so bear with us. It demonstrates how to compile and execute programs, and how to install the library and compiler. It also discusses how the language addresses modular development in terms of modules and packages. Subsequent chapters will delve into both language and library specifics. Let's get started!

Hello World

How about a simple program to output "hello world" to the console? Copy this example into a file called hello.d and save it:

1.  import tango.io.Stdout;
2.  void main()
3.  {
4.    Stdout ("hello world").newline;
5.  }

One of the D language's strengths is that it is familiar to many programmers at a rudimentary level. If you can describe what this example does, you're well on your way to understanding D. Let's take a look at the relevant attributes:

  • Line 1 instructs the compiler to enable symbolic access to console output, via the import keyword. This operates in a manner roughly equivalent to #include in the C++ language or import in Java, for those of you familiar with these languages.

  • The entry point of this example is defined by a main() signature on line 2, which the compiler recognizes and treats accordingly. This entry point is considered to be a function, or subroutine, and is invoked during program startup. All functions in the D language must declare a return type. As this example does not actually return a value, line 2 declares the return type to be void (effectively, nothing).

  • Curly braces {} delimit code blocks and functions in the D programming language, in a manner similar to other languages such as C++ and Java.

  • Within the Tango library, Stdout represents a generic console-output formatter and serves a similar purpose as printf() in C or System.out.print() in Java. Line 4 uses Stdout exposed via import to output the greeting to the console, appending a newline for good measure.

  • The import of symbols uses dot notation to identify and locate specific functionality within a hierarchy. This example imports Stdout, which belongs to the io subset of the tango library. The hierarchy helps you modularize functionality, and it will be familiar to Java programmers.

  • D supports the notion of discrete or modular compilation, demonstrated here through the import keyword. We'll discuss this further in the next two sections on modules and packages.

Note

Your D compiler may need to be configured in some manner. For now, we assume this has been completed during compiler installation. See the "Installation" section later in this chapter for details.

To execute this program, you must compile it, link it with library support, and run it. The first two steps are almost always combined into one step by the compiler itself, which simplifies things. Compilation of D is often managed by a code editor, a dependency program, or an integrated development environment (IDE), but we'll invoke the compiler directly (from the command line) for our examples:

dmd hello.d

Compilation results in a program called hello.exe on a Windows platform, which you can execute by typing hello on the command line:

> hello
hello world

Moving on, it is quite common to pass one or more arguments to a command-line program, so let's modify the example to support multiple greetings.

1.  import tango.io.Stdout;
2.  void main (char[][] args)
3.  {
4.      if (args.length < 2)
5.          Stdout ("usage is: hello name [name] ... [name]").newline;
6.      else
7.         foreach (name; args[1..$])
8.                  Stdout.formatln ("hello {}", name);
9.  }

We've introduced a number of additional notions here and are now beginning to show some core features of the language. From the top, this example contains the following:

  • Line 2 contains an alternate entry-point signature: main(char[][] args).

  • Line 2 uses an array. Command-line arguments are passed to a D program as an array of character arrays, or an array of strings, if you like.

  • Arrays expose a number of properties. On line 4, we test the length property to see if command-line arguments have been provided. By convention, the first argument provided via main(char[][] args) is the name of the program itself, which we will ignore.

  • Array slicing allows an array subset to be addressed in exactly the same manner as the superset. On line 7, we slice away the first (conventional) command-line argument since it is of no value to us here. Array slices are covered in detail in Chapter 2.

  • Line 7 also introduces a foreach mechanism to iterate across a collection. Briefly, foreach exposes elements of the rightmost argument via the left-hand argument(s). This example iterates across a subset of command-line arguments, excluding the element at index zero. The foreach loop is also discussed in Chapter 2.

  • Line 8 shows a variation on Stdout that enables formatted output, using {} to indicate positional arguments. The formatting syntax used will be familiar to C# programmers.

Compile and run the modified example with some command-line arguments:

> dmd hello.d
> hello Jim Sally
hello Jim
hello Sally

Now let's move on to modular compilation. We'll use the same example to demonstrate how to tease things apart, while retaining a relationship.

Source Modules

Source files in the D programming language are known as modules, and they represent the primary unit of compilation. When you compile a D program, the compiler operates on modules and will generate an object file representing each one. Modules should typically be named with a file extension of .d and identified internally via the module keyword. For example, if we were to split hello.d into two modules, it might take the following form:

1.  module greetings;
2.  import tango.io.Stdout;
3.  void hello (char[][] names)
4.  {
5.      foreach (name; names)
6.               Stdout.formatln ("hello {}", name);
7.  }

Here, we've migrated console output into a separate module called greetings.d, and identified the module as such on line 1 using the module keyword. On line 3, we've declared a function called hello, which accepts an array of strings and outputs each of them to the console (via lines 5 and 6). Function hello does not return anything at all.

Our main module remains within print.d, although it is modified to look like this:

1.  import greetings;
2.  void main(char[][] args)
3.  {
4.      hello (args[1..$]);
5.  }

On line 1, we import the greetings module in order to gain access to the contained hello function. Then, on line 4, we pass the same set of arguments to hello as we used in our earlier example. Compilation now requires that both modules be handed to the compiler:

> dmd hello.d greetings.d
> hello Jim Sally
hello Jim
hello Sally

Package, Import, and Symbol Visibility

As noted in the previous section, a single D source file is known as a D module. A collection of related modules within the same directory is known as a package. The notion of modules and packages is related to the visibility of code, declarations, and identifiers among modules. In other words, packages and modules together determine which symbols can and cannot be seen by other modules in the program (where symbol is a generic term for named program elements such as functions, constants, enumerations, structs, classes, and so on).

When you import a module, you're asking for access to the symbols it contains. Where those symbols have been implicitly or explicitly made public, they will be visible to any other importing module. On the other hand, symbols marked as package, private, or protected will not be visible to every other module importing them. Here's how these visibility attributes operate, when applied to module symbols:

  • public: Any module importing another can access all symbols marked as public.

  • package: Only those modules within the same directory, or package, can access symbols marked as package.

  • protected: Symbols marked as protected are visible only to other modules that derive (subclass) a class encapsulating such attributes

  • private: Symbols marked as private are visible only within the enclosing module, and are not visible to any outsiders.

To demonstrate, here's a module that exposes various symbols in different ways:

1.  module MyModule;
2.  private int x = 10;
3.  package char[] str = "hello";
4.  public void myFunction () {}
5.  public class MyClass {
6.      protected bool yes;
7.  }

On line 1, we declare the module name, which must match the file name (without the file extension). Line 2 declares a private integer, which is visible only within this specific module. Line 3 declares package visibility for a string, so it can be seen only by modules within the same directory (the same package). Line 4 declares a public function, which is visible to everyone importing this module.

Lines 5 through 7 declare a public class named MyClass, with a protected Boolean attribute. The class itself is visible to any module importing this module, but the protected attribute is visible only to those modules that derive from MyClass.

These visibility attributes are optional, and they are exclusive of one another (it doesn't make sense to combine them). Where visibility is not explicitly indicated, the default for all these cases is public.

Unsurprisingly, import statements themselves have visibility and follow rules similar to those just described for module symbols. A public import of module A into module B will expose the visible symbols of A to module C, where C imports B. Conversely, a private import of module A into module B will not expose symbols of A any further. The package and protected declarations operate in a related manner. The one distinction is that the default visibility of import is actually private, in order to help minimize namespace pollution among modules in a nontrivial project. You will learn more advanced ways to use the import statement in Chapter 3.

Throughout the coming chapters, you will see code examples that include something similar to import tango.io.Stdout. In each of these cases, the compiler will expect to locate a module called Stdout.d within a tango/io/ directory, relevant to the -I flag. To make this easier on you, most D compilers will peek into a configuration file, which can dictate what the -I flag (among others) should contain. We'll discuss this configuration file in the next section, which covers compiler installation.

Installation

In this section, we'll look at installing the compiler and configuring it so that it can locate the files it needs to operate effectively.

At the time of writing, the principal compiler for both Windows and Linux operating systems is the reference compiler named DMD (http://digitalmars.com/d/index.html). Also available is a well-supported front-end for the GNU compiler tools, called GDC (http://dgcc.sourceforge.net/), which emulates the command-line options of DMD. All current D compilers combine both compilation and linking in one step where desired.

D has a very strong online presence, and you can obtain a cutting-edge compiler by visiting the relevant site. However, in the interests of simplifying installation, the most effective approach is to download both the compiler and library as one bundle from the Tango web site (http://www.dsource.org/projects/tango/wiki/Download). The pages there are updated on a regular basis, and the bundled packages cover both the very latest tested combination of compiler and library, along with what is considered to be a solid and stable release.

We're going to install the Windows version of Tango and DMD (the process is similar for the bundled version of the related Linux combination). First, visit the Tango download page at http://www.dsource.org/projects/tango/wiki/DmdDownloads and grab the Windows .zip file. Open the .zip file and expand the content to your disk. For this installation, you should save to a new directory; let's use one called /d. Once the downloaded file is unzipped, examining its content via Windows Explorer or the command line should expose the following list of entries (or similar):

Directory of C:d
             bin
             example
             import
             lib
   1,484     LICENSE
     217     README.txt

Now set the Windows path to contain /d/bin, so that the compiler and related tools can be located. For example, from the Windows command line, enter the following:

> set path=din

After you've set the path, you should be able to enter the command dmd and have the compiler respond.

Now, let's compile and execute an example. Start off by switching to the directory /d/example/console:

> cd dexampleconsole

Next, compile and execute the program there called hello.d:

> dmd hello.d
> hello
   hello, sweetheart 
Installation

Congratulations, you've just successfully installed both Tango and D! If you explore a little, you'll find all the Tango source code within /d/import. This is one of the nice things about Tango: all of the source code is readily available.

If you look in /d/bin, you'll find a configuration file, called sc.ini, which is where this particular compiler looks for its default setup and configuration. Open this file with a text editor, and you should see something like the following (abbreviated) content:

DFLAGS="-I%@P%..import" -version=Tango -L+tango.lib

This is where a number of default settings are configured for the DMD compiler you just installed. It includes a -I command pointing at the import directory, a version indicator (-version), and a linker command (-L+) specifying the library tango.lib. You can modify this line as needed, or provide specific flags to the compiler for a particular use case.

Note

Each specific D compiler may have a different set of options available.

Looking further, you'll also notice a license file and a readme.txt file. Please read them both, as they contain important information. Tango is dual-licensed, with an Academic Free License v2.1 and a BSD License. In a nutshell, this means that you can use Tango and D to construct software for your own use or for commercial use without hindrance.

Compilation Tools

You've seen an example of compiling with more than one source module, but what happens when your project expands to the point where many modules are involved? Several tools are available to assist with this task, such as Make and Ant. The D community felt these could be improved upon in specific ways and has come up with a selection of alternatives, called Jake, Bud, and Rebuild. While you can certainly use traditional automated build tools, it would be worthwhile to consider these alternatives.

Each of the tools is based on a notion that you can compile just a single source module, and the rest of the dependencies will automatically be added to the compilation and linkage task. For example, our earlier hello.d example became split into two modules, and thus both needed to be provided to the compiler in order to satisfy the link step. Instead of that approach, we could have used one of these tools, like so:

jake hello.d

In this scenario, the dependencies within hello.d would be added on our behalf, just as though we had explicitly provided them to the compiler. In fact, you can work with the Tango library in this manner if you so choose.

Though Jake, Bud, and Rebuild support a similar strategy, they actually play different roles in the overall process, so choose the one that best suits your task:

Bud: This is a full-featured build engine for generating D-based executables, libraries, and dynamic link libraries (DLLs). It has a significant variety of options and was the first tool available. Bud supports Windows and Linux platforms. See http://dsource.org/projects/build for more information.
Rebuild: This is also a full-featured build tool, with the distinction of being part of a larger source-management, packaging, and installation system called the D Shared Software System (DSSS). It uses the same parser as the compiler itself and runs on a variety of platforms. See http://dsource.org/projects/dsss for more information.
Jake: This tool is limited to Windows only, and it cannot build libraries. In fact, it doesn't even have any command-line options of its own (you use the same options as the compiler itself). The sole benefit of using Jake is efficiency. It supports extremely fast full compilations, as it causes all modules to be compiled at one time, which can be great with larger projects. Jake is supplied as part of the Tango+D bundle for Windows.

This completes our overview of Tango with D. We've identified some of the key syntax of the D language, introduced a little of the Tango library, and shown how to install Tango and D in a Windows environment. We've also introduced the notion of modules and packages as the mechanism D uses to modularize software development, and how symbols within are exposed through visibility. In the next chapter, we'll dig into the language constructs at a deeper level.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.61.81