© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
C. MilanesiBeginning Rusthttps://doi.org/10.1007/978-1-4842-7208-4_1

1. Getting Started

Carlo Milanesi1  
(1)
Bergamo, Italy
 
In this chapter, you will learn:
  • How to write and run your first program in the Rust language

  • How to print text and numbers on the terminal

  • How to write comments in your code

How to Start

The smallest valid Rust program is this:
fn main(){}

Of course, it does nothing. It just defines an empty function named “main.” By “function” we mean a set of instructions that does something, and that has been given a name.

fn is shorthand for “function,” while main is the name of this function. The round parentheses contain the function’s possible arguments; in this case, there are no arguments. To close, the braces contain the possible statements that comprise the body of the function; in this case there are no statements.

When a program written in Rust is run, its main function is executed. If there is no main function, then it isn’t a complete program; it may be a library, though. Any Rust library may contain several entry points; instead, any Rust program has just one entry point, and its name must be main.

To run this program, first you must install the Rust toolset. The official Rust toolset can be downloaded for free from the website www.rust-lang.org. Linux, Windows, and macOS platforms are supported. For each platform, there are three versions: stable, beta, and nightly. The stable version is recommended; it is the oldest, but also the most tested one and the one less likely to change. All of these program versions should be used from the command line of a console. After installation, to check which version is installed, type at a command line (with uppercase V): rustc -V. The code in this book has been checked using version 1.56.0, but probably later versions will be OK too.

When you have a working installation, you can perform the following actions:
  • Create or choose a folder where your Rust exercises will be stored and, using any text editor, create in that folder a file named main.rs, having as contents the example program shown at the beginning of this chapter.

  • At a command line, in that folder, type: rustc main.rs . The prompt should be printed almost immediately, after having created a file named main (in a Windows environment, it will be named main.exe). Actually, the rustc command has correctly compiled the specified file. That is, it has read it, it has generated the corresponding machine code, and it has stored this machine code in a file in the same folder.

  • At the command line, if in a Windows environment, type: main

For other operating systems, type:

./main

You just run the program generated before. The prompt should be printed immediately, as this program does nothing.

Hello, World!

Let’s see how to print some text on the terminal. Change the program of the previous section to the following one:
fn main() {
    print!("Hello, world!");
}

If such code is compiled and run as before, it will print: Hello, world!.

Notice that the newly added line contains eight syntax items, aka tokens. Let’s examine them:
  • print: It is the name of a macro defined in the Rust standard library.

  • !: This character specifies that the preceding name indicates a macro. Without such a symbol, print would instead indicate a function. There is no such function in the Rust standard library, so you would get a compilation error. A macro is a thing similar to a function—it’s some Rust code, having a name. By using this name, you ask to insert such code at this point. The main difference between a function call and a macro invocation is that a function call executes at runtime the code of the function definition, which is located in another part of the program, so the control of execution is transferred elsewhere, while a macro invocation asks the compiler to replace the macro invocation with the body of the macro definition.

  • (: It starts the list of arguments of the macro.

  • ": It starts the literal string.

  • Hello, world!: It is the content of the literal string.

  • ": It ends the literal string.

  • ): It ends the list of the arguments of the macro.

  • ;: It ends the statement.

Let’s examine the meaning of the literal string phrase. The word string means finite sequence of characters, possibly including spaces and punctuation. The word literal means specified directly in source code. Therefore a literal string is a finite sequence of characters (possibly including spaces and punctuation) specified directly in source code. A nonliteral string, instead, is a variable whose value at runtime is a string. Such a string could be read from a file, or typed by the user, or copied from a literal string, as we will see when string variables are explained.

The print macro simply inserts into the program some code that prints on the terminal the text that it has received as an argument.

Rust always distinguishes between uppercase and lowercase letters—it’s case sensitive. For all characters that are outside literal strings and comments, if you replace an uppercase letter with a lowercase one or conversely, typically you get a compilation error, or anyway a program with a different behavior. Instead, making such changes inside literal strings always allows a successful compilation, but it’s likely the behavior of the program will be different.

For example:
fn Main() {}

If you compile this program, you get the compilation error main function not found, as no main function (with a lowercase m) is defined in the program.

From now on, except when specified, we will assume the example code will be inside the braces of the main function, so the braces and the text preceding them will be omitted.

Printing Combinations of Literal Strings

Instead of using a single literal string, you can print several of them, even in a single statement, in this way:
print!("{}, {}!", "Hello", "world");

This statement, put inside the braces of the main function , will print again: Hello, world!.

In this case, the print macro receives three arguments, separated by commas. All three arguments are literal strings. The first string, though, contains two pairs of braces ({}). They are placeholders, indicating the positions in which to insert the other two strings.

So, the macro scans the arguments after the first one, and for each of them it looks inside the first argument for a pair of braces and replaces that pair of braces with the current argument.

This resembles the following C language statement:
printf("%s, %s!", "Hello", "world");
But there is an important difference. If you try to compile:
print!("{}, !", "Hello", "world");

you get the compilation error argument never used, as the first argument contains just one placeholder, but after the first argument, there are two other arguments to print. So, there is one argument that doesn’t have any corresponding placeholder.

And if you try to compile:
print!("{}, {}!", "Hello");

you get a compilation error too, as the first argument contains two placeholders, but after the first argument there is only one argument to print. So, there is a placeholder that doesn’t have any corresponding argument.

Instead, the corresponding statements in C language usually raise just a warning, and then they generate a compiled program that will misbehave.

Printing Several Lines of Text

So far, we wrote programs that print only one line, but a single statement can print several lines. It is done in this way:
print!("First line Second line Third line ");
This will print:
First line
Second line
Third line

The sequence of characters (where n stands for new line) is transformed by the compiler into the character sequence that represents the line terminator for the currently used operating system.

Actually, it is very common to go to a new line exactly once for every printing statement. You can do this by adding the two characters at the end of the line; you can also use another macro of the standard library, println, whose name is to be read “print line.” It’s used in this way:
println!("text of the line");
This statement is equivalent to:
print!("text of the line ");

Printing Integer Numbers

If you want to print My number: 140, you can type:
print!("My number: 140");
or, using a placeholder and an additional argument:
print!("My number: {}", "140");
or, removing the quotes around the second argument:
print!("My number: {}", 140);

In the last statement, the second argument is not a literal string, but it is a literal integer number, or, for short, a literal integer.

The integers are another data type, with respect to strings.

The print macro is also able to use integer numbers to replace the corresponding placeholder inside its first argument.

In fact, the compiler interprets the string 140 contained in the source code as a number expressed in decimal format. It generates the equivalent number in binary format, and then it saves that binary number into the executable program.

At run time, the program takes that binary number; it transforms it into the string "140", using the decimal notation; then it replaces the placeholder with that string, therefore generating the string to print; and finally it sends the string to the terminal.

This procedure explains, for example, why if the following program is written:
print!("My number: {}", 000140);

the compiler generates exactly the same executable program generated before. Actually, when the source string 000140 is converted to the binary format, the leading zeros are ignored.

The argument types may be mixed too. This statement:
print!("{}: {}", "My number", 140);

will print the same line as before. Here the first placeholder corresponds to a literal string, while the second one corresponds to a literal integer.

Comments

As any other programming language, Rust allows comments embedded in code:

The following code:
// This program
// prints a number.
print!("{}", 34); // thirty-four
/* print!("{}", 80);
*/

will print 34.

The first two lines start with a pair of slashes (//). Such a pair of characters indicates the start of a line comment, which is a comment ending at the end of the line. To write a comment on several lines, the pair of slashes must be repeated at every line of the comment, as in the second line of the preceding program.

Rust programmers use to leave a space character just after the double slash, to improve readability.

As it appears in the third line, a line comment may start after a statement, usually separated by at least one space character.

There is another kind of comment, exemplified in the fourth and fifth lines. Such a comment starts with the character pair /* and ends with the pair */; it may extend on several lines, so it is named multi-line comment.

Rust programmers usually avoid the multi-line comment in production code, using only single line comments, and use multi-line comments only to temporarily exclude some code from compilation. This is because single-line comments have some advantages: when extracting source lines using a search tool, or when comparing different versions of a code base, it is immediately clear which lines are comments and which are not.

Rust comments look identical to modern C language comments. In fact, there is an important difference between Rust comments and C comments: Rust comments may be nested, and they must be nested correctly. In this way, you can first exclude some portions of a source file from compilation, and then exclude a larger portion that contains the smaller portions.

Here is a valid comment:
/* This is /* a valid*/
comment, even /* if /* it contains
comments*/ inside */itself.  */
And here is some code that generates the compilation error: unterminated block comment.
/* This /* instead is not allowed in Rust,
while in C is tolerated (but it may generate a warning).*/
..................Content has been hidden....................

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