4390 lines
121 KiB
Plaintext
4390 lines
121 KiB
Plaintext
# SOME DESCRIPTIVE TITLE
|
|
# Copyright (C) YEAR The Rust Project Developers
|
|
# This file is distributed under the same license as the Rust package.
|
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
#
|
|
#, fuzzy
|
|
msgid ""
|
|
msgstr ""
|
|
"Project-Id-Version: Rust 0.8-pre\n"
|
|
"POT-Creation-Date: 2013-07-17 07:18+0900\n"
|
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
"Language: \n"
|
|
"MIME-Version: 1.0\n"
|
|
"Content-Type: text/plain; charset=CHARSET\n"
|
|
"Content-Transfer-Encoding: 8bit\n"
|
|
|
|
#. type: Plain text
|
|
#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
|
|
#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
|
|
#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
|
|
msgid "# Introduction"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/rust.md:1231 doc/tutorial.md:2177
|
|
msgid ""
|
|
"In type-parameterized functions, methods of the supertrait may be called on "
|
|
"values of subtrait-bound type parameters. Refering to the previous example "
|
|
"of `trait Circle : Shape`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/rust.md:1240 doc/tutorial.md:2186
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# trait Shape { fn area(&self) -> float; }\n"
|
|
"# trait Circle : Shape { fn radius(&self) -> float; }\n"
|
|
"fn radius_times_area<T: Circle>(c: T) -> float {\n"
|
|
" // `c` is both a Circle and a Shape\n"
|
|
" c.radius() * c.area()\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/rust.md:1242 doc/tutorial.md:2188
|
|
msgid "Likewise, supertrait methods may also be called on trait objects."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2
|
|
msgid "% The Rust Language Tutorial"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:13
|
|
msgid ""
|
|
"Rust is a programming language with a focus on type safety, memory safety, "
|
|
"concurrency and performance. It is intended for writing large-scale, high-"
|
|
"performance software that is free from several classes of common errors. "
|
|
"Rust has a sophisticated memory model that encourages efficient data "
|
|
"structures and safe concurrency patterns, forbidding invalid memory accesses "
|
|
"that would otherwise cause segmentation faults. It is statically typed and "
|
|
"compiled ahead of time."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:17
|
|
msgid ""
|
|
"As a multi-paradigm language, Rust supports writing code in procedural, "
|
|
"functional and object-oriented styles. Some of its pleasant high-level "
|
|
"features include:"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:30
|
|
msgid ""
|
|
"**Type inference.** Type annotations on local variable declarations are "
|
|
"optional."
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:30
|
|
msgid ""
|
|
"**Safe task-based concurrency.** Rust's lightweight tasks do not share "
|
|
"memory, instead communicating through messages."
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:30
|
|
msgid ""
|
|
"**Higher-order functions.** Efficient and flexible closures provide "
|
|
"iteration and other control structures"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:30
|
|
msgid ""
|
|
"**Pattern matching and algebraic data types.** Pattern matching on Rust's "
|
|
"enumeration types (a more powerful version of C's enums, similar to "
|
|
"algebraic data types in functional languages) is a compact and expressive "
|
|
"way to encode program logic."
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:30
|
|
msgid ""
|
|
"**Polymorphism.** Rust has type-parametric functions and types, type classes "
|
|
"and OO-style interfaces."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:32
|
|
msgid "## Scope"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:38
|
|
msgid ""
|
|
"This is an introductory tutorial for the Rust programming language. It "
|
|
"covers the fundamentals of the language, including the syntax, the type "
|
|
"system and memory model, generics, and modules. [Additional tutorials](#what-"
|
|
"next) cover specific language features in greater depth."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:42
|
|
msgid ""
|
|
"This tutorial assumes that the reader is already familiar with one or more "
|
|
"languages in the C family. Understanding of pointers and general memory "
|
|
"management techniques will help."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:44
|
|
msgid "## Conventions"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:47
|
|
msgid ""
|
|
"Throughout the tutorial, language keywords and identifiers defined in "
|
|
"example code are displayed in `code font`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:53
|
|
msgid ""
|
|
"Code snippets are indented, and also shown in a monospaced font. Not all "
|
|
"snippets constitute whole programs. For brevity, we'll often show fragments "
|
|
"of programs that don't compile on their own. To try them out, you might have "
|
|
"to wrap them in `fn main() { ... }`, and make sure they don't contain "
|
|
"references to names that aren't actually defined."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:57
|
|
msgid ""
|
|
"> ***Warning:*** Rust is a language under ongoing development. Notes > about "
|
|
"potential changes to the language, implementation > deficiencies, and other "
|
|
"caveats appear offset in blockquotes."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:59
|
|
msgid "# Getting started"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:63
|
|
msgid ""
|
|
"The Rust compiler currently must be built from a [tarball], unless you are "
|
|
"on Windows, in which case using the [installer][win-exe] is recommended."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:69
|
|
msgid ""
|
|
"Since the Rust compiler is written in Rust, it must be built by a "
|
|
"precompiled \"snapshot\" version of itself (made in an earlier state of "
|
|
"development). As such, source builds require a connection to the Internet, "
|
|
"to fetch snapshots, and an OS that can execute the available snapshot "
|
|
"binaries."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:71
|
|
msgid "Snapshot binaries are currently built and tested on several platforms:"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:75
|
|
msgid "Windows (7, Server 2008 R2), x86 only"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:75
|
|
msgid "Linux (various distributions), x86 and x86-64"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:75
|
|
msgid "OSX 10.6 (\"Snow Leopard\") or greater, x86 and x86-64"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:78
|
|
msgid ""
|
|
"You may find that other platforms work, but these are our \"tier 1\" "
|
|
"supported build environments that are most likely to work."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:85
|
|
msgid ""
|
|
"> ***Note:*** Windows users should read the detailed > \"[getting started]"
|
|
"[wiki-start]\" notes on the wiki. Even when using > the binary installer, "
|
|
"the Windows build requires a MinGW installation, > the precise details of "
|
|
"which are not discussed here. Finally, `rustc` may > need to be [referred to "
|
|
"as `rustc.exe`][bug-3319]. It's a bummer, we > know."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:88
|
|
msgid ""
|
|
"[bug-3319]: https://github.com/mozilla/rust/issues/3319 [wiki-start]:"
|
|
"\thttps://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:91
|
|
msgid ""
|
|
"To build from source you will also need the following prerequisite packages:"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:97
|
|
msgid "g++ 4.4 or clang++ 3.x"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:97
|
|
msgid "python 2.6 or later (but not 3.x)"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:97
|
|
msgid "perl 5.0 or later"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:97
|
|
msgid "gnu make 3.81 or later"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:97
|
|
msgid "curl"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:100
|
|
msgid ""
|
|
"If you've fulfilled those prerequisites, something along these lines should "
|
|
"work."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:108
|
|
msgid ""
|
|
"~~~~ {.notrust} $ curl -O http://static.rust-lang.org/dist/rust-0.7.tar.gz $ "
|
|
"tar -xzf rust-0.7.tar.gz $ cd rust-0.7 $ ./configure $ make && make install "
|
|
"~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:114
|
|
msgid ""
|
|
"You may need to use `sudo make install` if you do not normally have "
|
|
"permission to modify the destination directory. The install locations can be "
|
|
"adjusted by passing a `--prefix` argument to `configure`. Various other "
|
|
"options are also supported: pass `--help` for more information on them."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:120
|
|
msgid ""
|
|
"When complete, `make install` will place several programs into `/usr/local/"
|
|
"bin`: `rustc`, the Rust compiler; `rustdoc`, the API-documentation tool; "
|
|
"`rustpkg`, the Rust package manager; `rusti`, the Rust REPL; and `rust`, a "
|
|
"tool which acts both as a unified interface for them, and for a few common "
|
|
"command line scenarios."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:124
|
|
msgid ""
|
|
"[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-"
|
|
"developing-Rust [tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz "
|
|
"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:126
|
|
msgid "## Compiling your first program"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:129
|
|
msgid ""
|
|
"Rust program files are, by convention, given the extension `.rs`. Say we "
|
|
"have a file `hello.rs` containing this program:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:135
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn main() {\n"
|
|
" println(\"hello?\");\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:139
|
|
msgid ""
|
|
"If the Rust compiler was installed successfully, running `rustc hello.rs` "
|
|
"will produce an executable called `hello` (or `hello.exe` on Windows) which, "
|
|
"upon running, will likely do exactly what you expect."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:144
|
|
msgid ""
|
|
"The Rust compiler tries to provide useful information when it encounters an "
|
|
"error. If you introduce an error into the program (for example, by changing "
|
|
"`println` to some nonexistent function), and then compile it, you'll see an "
|
|
"error message like this:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:150
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.notrust}\n"
|
|
"hello.rs:2:4: 2:16 error: unresolved name: print_with_unicorns\n"
|
|
"hello.rs:2 print_with_unicorns(\"hello?\");\n"
|
|
" ^~~~~~~~~~~~~~~~~~~~~~~\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:157
|
|
msgid ""
|
|
"In its simplest form, a Rust program is a `.rs` file with some types and "
|
|
"functions defined in it. If it has a `main` function, it can be compiled to "
|
|
"an executable. Rust does not allow code that's not a declaration to appear "
|
|
"at the top level of the file: all statements must live inside a function. "
|
|
"Rust programs can also be compiled as libraries, and included in other "
|
|
"programs."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:159
|
|
msgid "## Using the rust tool"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:164
|
|
msgid ""
|
|
"While using `rustc` directly to generate your executables, and then running "
|
|
"them manually is a perfectly valid way to test your code, for smaller "
|
|
"projects, prototypes, or if you're a beginner, it might be more convenient "
|
|
"to use the `rust` tool."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:170
|
|
msgid ""
|
|
"The `rust` tool provides central access to the other rust tools, as well as "
|
|
"handy shortcuts for directly running source files. For example, if you have "
|
|
"a file `foo.rs` in your current directory, `rust run foo.rs` would attempt "
|
|
"to compile it and, if successful, directly run the resulting binary."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:173
|
|
msgid ""
|
|
"To get a list of all available commands, simply call `rust` without any "
|
|
"argument."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:175
|
|
msgid "## Editing Rust code"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:185
|
|
msgid ""
|
|
"There are vim highlighting and indentation scripts in the Rust source "
|
|
"distribution under `src/etc/vim/`. There is an emacs mode under `src/etc/"
|
|
"emacs/` called `rust-mode`, but do read the instructions included in that "
|
|
"directory. In particular, if you are running emacs 24, then using emacs's "
|
|
"internal package manager to install `rust-mode` is the easiest way to keep "
|
|
"it up to date. There is also a package for Sublime Text 2, available both "
|
|
"[standalone][sublime] and through [Sublime Package Control][sublime-pkg], "
|
|
"and support for Kate under `src/etc/kate`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:189
|
|
msgid ""
|
|
"There is ctags support via `src/etc/ctags.rust`, but many other tools and "
|
|
"editors are not yet supported. If you end up writing a Rust mode for your "
|
|
"favorite editor, let us know so that we can link to it."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:192
|
|
msgid ""
|
|
"[sublime]: http://github.com/dbp/sublime-rust [sublime-pkg]: http://wbond."
|
|
"net/sublime_packages/package_control"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:194
|
|
msgid "# Syntax basics"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:202
|
|
msgid ""
|
|
"Assuming you've programmed in any C-family language (C++, Java, JavaScript, "
|
|
"C#, or PHP), Rust will feel familiar. Code is arranged in blocks delineated "
|
|
"by curly braces; there are control structures for branching and looping, "
|
|
"like the familiar `if` and `while`; function calls are written `myfunc(arg1, "
|
|
"arg2)`; operators are written the same and mostly have the same precedence "
|
|
"as in C; comments are again like C; module names are separated with double-"
|
|
"colon (`::`) as with C++."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:207
|
|
msgid ""
|
|
"The main surface difference to be aware of is that the condition at the head "
|
|
"of control structures like `if` and `while` does not require parentheses, "
|
|
"while their bodies *must* be wrapped in braces. Single-statement, unbraced "
|
|
"bodies are not allowed."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:220
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# mod universe { pub fn recalibrate() -> bool { true } }\n"
|
|
"fn main() {\n"
|
|
" /* A simple loop */\n"
|
|
" loop {\n"
|
|
" // A tricky calculation\n"
|
|
" if universe::recalibrate() {\n"
|
|
" return;\n"
|
|
" }\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:224
|
|
msgid ""
|
|
"The `let` keyword introduces a local variable. Variables are immutable by "
|
|
"default. To introduce a local variable that you can re-assign later, use "
|
|
"`let mut` instead."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:228
|
|
msgid "~~~~ let hi = \"hi\"; let mut count = 0;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:234
|
|
#, no-wrap
|
|
msgid ""
|
|
"while count < 10 {\n"
|
|
" println(fmt!(\"count: %?\", count));\n"
|
|
" count += 1;\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:238
|
|
msgid ""
|
|
"Although Rust can almost always infer the types of local variables, you can "
|
|
"specify a variable's type by following it with a colon, then the type name. "
|
|
"Static items, on the other hand, always require a type annotation."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:244
|
|
msgid ""
|
|
"~~~~ static MONSTER_FACTOR: float = 57.8; let monster_size = MONSTER_FACTOR "
|
|
"* 10.0; let monster_size: int = 50; ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:253
|
|
msgid ""
|
|
"Local variables may shadow earlier declarations, as in the previous example: "
|
|
"`monster_size` was first declared as a `float`, and then a second "
|
|
"`monster_size` was declared as an `int`. If you were to actually compile "
|
|
"this example, though, the compiler would determine that the first "
|
|
"`monster_size` is unused and issue a warning (because this situation is "
|
|
"likely to indicate a programmer error). For occasions where unused variables "
|
|
"are intentional, their names may be prefixed with an underscore to silence "
|
|
"the warning, like `let _monster_size = 50;`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:259
|
|
msgid ""
|
|
"Rust identifiers start with an alphabetic character or an underscore, and "
|
|
"after that may contain any sequence of alphabetic characters, numbers, or "
|
|
"underscores. The preferred style is to write function, variable, and module "
|
|
"names with lowercase letters, using underscores where they help readability, "
|
|
"while writing types in camel case."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:264
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"let my_variable = 100;\n"
|
|
"type MyType = int; // primitive types are _not_ camel case\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:266
|
|
msgid "## Expressions and semicolons"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:272
|
|
msgid ""
|
|
"Though it isn't apparent in all code, there is a fundamental difference "
|
|
"between Rust's syntax and predecessors like C. Many constructs that are "
|
|
"statements in C are expressions in Rust, allowing code to be more concise. "
|
|
"For example, you might write a piece of code like this:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:284
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# let item = \"salad\";\n"
|
|
"let price;\n"
|
|
"if item == \"salad\" {\n"
|
|
" price = 3.50;\n"
|
|
"} else if item == \"muffin\" {\n"
|
|
" price = 2.25;\n"
|
|
"} else {\n"
|
|
" price = 2.00;\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:286
|
|
msgid "But, in Rust, you don't have to repeat the name `price`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:298
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# let item = \"salad\";\n"
|
|
"let price =\n"
|
|
" if item == \"salad\" {\n"
|
|
" 3.50\n"
|
|
" } else if item == \"muffin\" {\n"
|
|
" 2.25\n"
|
|
" } else {\n"
|
|
" 2.00\n"
|
|
" };\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:304
|
|
msgid ""
|
|
"Both pieces of code are exactly equivalent: they assign a value to `price` "
|
|
"depending on the condition that holds. Note that there are no semicolons in "
|
|
"the blocks of the second snippet. This is important: the lack of a semicolon "
|
|
"after the last statement in a braced block gives the whole block the value "
|
|
"of that last expression."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:310
|
|
msgid ""
|
|
"Put another way, the semicolon in Rust *ignores the value of an "
|
|
"expression*. Thus, if the branches of the `if` had looked like `{ 4; }`, "
|
|
"the above example would simply assign `()` (nil or void) to `price`. But "
|
|
"without the semicolon, each branch has a different value, and `price` gets "
|
|
"the value of the branch that was taken."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:315
|
|
msgid ""
|
|
"In short, everything that's not a declaration (declarations are `let` for "
|
|
"variables; `fn` for functions; and any top-level named items such as [traits]"
|
|
"(#traits), [enum types](#enums), and [constants](#constants)) is an "
|
|
"expression, including function bodies."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:323
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn is_four(x: int) -> bool {\n"
|
|
" // No need for a return statement. The result of the expression\n"
|
|
" // is used as the return value.\n"
|
|
" x == 4\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:325
|
|
msgid "## Primitive types and literals"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:332
|
|
msgid ""
|
|
"There are general signed and unsigned integer types, `int` and `uint`, as "
|
|
"well as 8-, 16-, 32-, and 64-bit variants, `i8`, `u16`, etc. Integers can "
|
|
"be written in decimal (`144`), hexadecimal (`0x90`), or binary "
|
|
"(`0b10010000`) base. Each integral type has a corresponding literal suffix "
|
|
"that can be used to indicate the type of a literal: `i` for `int`, `u` for "
|
|
"`uint`, `i8` for the `i8` type."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:338
|
|
msgid ""
|
|
"In the absence of an integer literal suffix, Rust will infer the integer "
|
|
"type based on type annotations and function signatures in the surrounding "
|
|
"program. In the absence of any type information at all, Rust will assume "
|
|
"that an unsuffixed integer literal has type `int`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:345
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let a = 1; // a is an int\n"
|
|
"let b = 10i; // b is an int, due to the 'i' suffix\n"
|
|
"let c = 100u; // c is a uint\n"
|
|
"let d = 1000i32; // d is an i32\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:350
|
|
msgid ""
|
|
"There are three floating-point types: `float`, `f32`, and `f64`. Floating-"
|
|
"point numbers are written `0.0`, `1e6`, or `2.1e-4`. Like integers, "
|
|
"floating-point literals are inferred to the correct type. Suffixes `f`, "
|
|
"`f32`, and `f64` can be used to create literals of a specific type."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:352
|
|
msgid "The keywords `true` and `false` produce literals of type `bool`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:359
|
|
msgid ""
|
|
"Characters, the `char` type, are four-byte Unicode codepoints, whose "
|
|
"literals are written between single quotes, as in `'x'`. Just like C, Rust "
|
|
"understands a number of character escapes, using the backslash character, "
|
|
"such as `\\n`, `\\r`, and `\\t`. String literals, written between double "
|
|
"quotes, allow the same escape sequences. More on strings [later](#vectors-"
|
|
"and-strings)."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:361
|
|
msgid "The nil type, written `()`, has a single value, also written `()`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:363
|
|
msgid "## Operators"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:368
|
|
msgid ""
|
|
"Rust's set of operators contains very few surprises. Arithmetic is done with "
|
|
"`*`, `/`, `%`, `+`, and `-` (multiply, quotient, remainder, add, and "
|
|
"subtract). `-` is also a unary prefix operator that negates numbers. As in "
|
|
"C, the bitwise operators `>>`, `<<`, `&`, `|`, and `^` are also supported."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:371
|
|
msgid ""
|
|
"Note that, if applied to an integer value, `!` flips all the bits (like `~` "
|
|
"in C)."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:375
|
|
msgid ""
|
|
"The comparison operators are the traditional `==`, `!=`, `<`, `>`, `<=`, and "
|
|
"`>=`. Short-circuiting (lazy) boolean operators are written `&&` (and) and "
|
|
"`||` (or)."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:380
|
|
msgid ""
|
|
"For type casting, Rust uses the binary `as` operator. It takes an "
|
|
"expression on the left side and a type on the right side and will, if a "
|
|
"meaningful conversion exists, convert the result of the expression to the "
|
|
"given type."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:386
|
|
msgid ""
|
|
"~~~~ let x: float = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:388
|
|
msgid "## Syntax extensions"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:395
|
|
#, no-wrap
|
|
msgid ""
|
|
"*Syntax extensions* are special forms that are not built into the language,\n"
|
|
"but are instead provided by the libraries. To make it clear to the reader when\n"
|
|
"a name refers to a syntax extension, the names of all syntax extensions end\n"
|
|
"with `!`. The standard library defines a few syntax extensions, the most\n"
|
|
"useful of which is `fmt!`, a `sprintf`-style text formatter that you will\n"
|
|
"often see in examples.\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:399
|
|
msgid ""
|
|
"`fmt!` supports most of the directives that [printf][pf] supports, but "
|
|
"unlike printf, will give you a compile-time error when the types of the "
|
|
"directives don't match the types of the arguments."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:402
|
|
msgid "~~~~ # let mystery_object = ();"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:404
|
|
msgid "println(fmt!(\"%s is %d\", \"the answer\", 43));"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:408
|
|
msgid ""
|
|
"// %? will conveniently print any type println(fmt!(\"what is this thing: %?"
|
|
"\", mystery_object)); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:410
|
|
msgid "[pf]: http://en.cppreference.com/w/cpp/io/c/fprintf"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:412
|
|
msgid ""
|
|
"You can define your own syntax extensions with the macro system. For "
|
|
"details, see the [macro tutorial][macros]."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:414
|
|
msgid "[macros]: tutorial-macros.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:416
|
|
msgid "# Control structures"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:418
|
|
msgid "## Conditionals"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:422
|
|
msgid ""
|
|
"We've seen `if` expressions a few times already. To recap, braces are "
|
|
"compulsory, an `if` can have an optional `else` clause, and multiple `if`/"
|
|
"`else` constructs can be chained together:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:432
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"if false {\n"
|
|
" println(\"that's odd\");\n"
|
|
"} else if true {\n"
|
|
" println(\"right\");\n"
|
|
"} else {\n"
|
|
" println(\"neither true nor false\");\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:437
|
|
msgid ""
|
|
"The condition given to an `if` construct *must* be of type `bool` (no "
|
|
"implicit conversion happens). If the arms are blocks that have a value, this "
|
|
"value must be of the same type for every arm in which control reaches the "
|
|
"end of the block:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:445
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn signum(x: int) -> int {\n"
|
|
" if x < 0 { -1 }\n"
|
|
" else if x > 0 { 1 }\n"
|
|
" else { return 0 }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:447
|
|
msgid "## Pattern matching"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:453
|
|
msgid ""
|
|
"Rust's `match` construct is a generalized, cleaned-up version of C's "
|
|
"`switch` construct. You provide it with a value and a number of *arms*, each "
|
|
"labelled with a pattern, and the code compares the value against each "
|
|
"pattern in order until one matches. The matching pattern executes its "
|
|
"corresponding arm."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:463
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# let my_number = 1;\n"
|
|
"match my_number {\n"
|
|
" 0 => println(\"zero\"),\n"
|
|
" 1 | 2 => println(\"one or two\"),\n"
|
|
" 3..10 => println(\"three to ten\"),\n"
|
|
" _ => println(\"something else\")\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:467
|
|
msgid ""
|
|
"Unlike in C, there is no \"falling through\" between arms: only one arm "
|
|
"executes, and it doesn't have to explicitly `break` out of the construct "
|
|
"when it is finished."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:477
|
|
msgid ""
|
|
"A `match` arm consists of a *pattern*, then an arrow `=>`, followed by an "
|
|
"*action* (expression). Literals are valid patterns and match only their own "
|
|
"value. A single arm may match multiple different patterns by combining them "
|
|
"with the pipe operator (`|`), so long as every pattern binds the same set of "
|
|
"variables. Ranges of numeric literal patterns can be expressed with two "
|
|
"dots, as in `M..N`. The underscore (`_`) is a wildcard pattern that matches "
|
|
"any single value. The asterisk (`*`) is a different wildcard that can match "
|
|
"one or more fields in an `enum` variant."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:482
|
|
msgid ""
|
|
"The patterns in a match arm are followed by a fat arrow, `=>`, then an "
|
|
"expression to evaluate. Each case is separated by commas. It's often "
|
|
"convenient to use a block expression for each case, in which case the commas "
|
|
"are optional."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:490
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# let my_number = 1;\n"
|
|
"match my_number {\n"
|
|
" 0 => { println(\"zero\") }\n"
|
|
" _ => { println(\"something else\") }\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:495
|
|
msgid ""
|
|
"`match` constructs must be *exhaustive*: they must have an arm covering "
|
|
"every possible case. For example, the typechecker would reject the previous "
|
|
"example if the arm with the wildcard pattern was omitted."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:499
|
|
msgid ""
|
|
"A powerful application of pattern matching is *destructuring*: matching in "
|
|
"order to bind names to the contents of data types."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:503
|
|
msgid ""
|
|
"> ***Note:*** The following code makes use of tuples (`(float, float)`) "
|
|
"which > are explained in section 5.3. For now you can think of tuples as a "
|
|
"list of > items."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:516
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::float;\n"
|
|
"# use std::num::atan;\n"
|
|
"fn angle(vector: (float, float)) -> float {\n"
|
|
" let pi = float::consts::pi;\n"
|
|
" match vector {\n"
|
|
" (0f, y) if y < 0f => 1.5 * pi,\n"
|
|
" (0f, y) => 0.5 * pi,\n"
|
|
" (x, y) => atan(y / x)\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:522
|
|
msgid ""
|
|
"A variable name in a pattern matches any value, *and* binds that name to the "
|
|
"value of the matched value inside of the arm's action. Thus, `(0f, y)` "
|
|
"matches any tuple whose first element is zero, and binds `y` to the second "
|
|
"element. `(x, y)` matches any two-element tuple, and binds both elements to "
|
|
"variables."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:529
|
|
msgid ""
|
|
"Any `match` arm can have a guard clause (written `if EXPR`), called a "
|
|
"*pattern guard*, which is an expression of type `bool` that determines, "
|
|
"after the pattern is found to match, whether the arm is taken or not. The "
|
|
"variables bound by the pattern are in scope in this guard expression. The "
|
|
"first arm in the `angle` example shows an example of a pattern guard."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:534
|
|
msgid ""
|
|
"You've already seen simple `let` bindings, but `let` is a little fancier "
|
|
"than you've been led to believe. It, too, supports destructuring patterns. "
|
|
"For example, you can write this to extract the fields from a tuple, "
|
|
"introducing two variables at once: `a` and `b`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:539
|
|
msgid ""
|
|
"~~~~ # fn get_tuple_of_two_ints() -> (int, int) { (1, 1) } let (a, b) = "
|
|
"get_tuple_of_two_ints(); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:543
|
|
msgid ""
|
|
"Let bindings only work with _irrefutable_ patterns: that is, patterns that "
|
|
"can never fail to match. This excludes `let` from matching literals and most "
|
|
"`enum` variants."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:545
|
|
msgid "## Loops"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:550
|
|
msgid ""
|
|
"`while` denotes a loop that iterates as long as its given condition (which "
|
|
"must have type `bool`) evaluates to `true`. Inside a loop, the keyword "
|
|
"`break` aborts the loop, and `loop` aborts the current iteration and "
|
|
"continues with the next."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:557
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let mut cake_amount = 8;\n"
|
|
"while cake_amount > 0 {\n"
|
|
" cake_amount -= 1;\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:559
|
|
msgid ""
|
|
"`loop` denotes an infinite loop, and is the preferred way of writing `while "
|
|
"true`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:569
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::int;\n"
|
|
"let mut x = 5;\n"
|
|
"loop {\n"
|
|
" x += x - 3;\n"
|
|
" if x % 5 == 0 { break; }\n"
|
|
" println(int::to_str(x));\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:572
|
|
msgid ""
|
|
"This code prints out a weird sequence of numbers and stops as soon as it "
|
|
"finds one that can be divided by five."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:577
|
|
msgid ""
|
|
"Rust also has a `for` construct. It's different from C's `for` and it works "
|
|
"best when iterating over collections. See the section on [closures]"
|
|
"(#closures) to find out how to use `for` and higher-order functions for "
|
|
"enumerating elements of a collection."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:579
|
|
msgid "# Data structures"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:581
|
|
msgid "## Structs"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:586
|
|
msgid ""
|
|
"Rust struct types must be declared before they are used using the `struct` "
|
|
"syntax: `struct Name { field1: T1, field2: T2 [, ...] }`, where `T1`, "
|
|
"`T2`, ... denote types. To construct a struct, use the same syntax, but "
|
|
"leave off the `struct`: for example: `Point { x: 1.0, y: 2.0 }`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:590
|
|
msgid ""
|
|
"Structs are quite similar to C structs and are even laid out the same way in "
|
|
"memory (so you can read from a Rust struct in C, and vice-versa). Use the "
|
|
"dot operator to access struct fields, as in `mypoint.x`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:597
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"struct Point {\n"
|
|
" x: float,\n"
|
|
" y: float\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:601
|
|
msgid ""
|
|
"Inherited mutability means that any field of a struct may be mutable, if the "
|
|
"struct is in a mutable slot (or a field of a struct in a mutable slot, and "
|
|
"so forth)."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:605
|
|
msgid ""
|
|
"With a value (say, `mypoint`) of such a type in a mutable location, you can "
|
|
"do `mypoint.y += 1.0`. But in an immutable location, such an assignment to a "
|
|
"struct without inherited mutability would result in a type error."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:610
|
|
msgid ""
|
|
"~~~~ {.xfail-test} # struct Point { x: float, y: float } let mut mypoint = "
|
|
"Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:614
|
|
msgid ""
|
|
"mypoint.y += 1.0; // mypoint is mutable, and its fields as well origin.y += "
|
|
"1.0; // ERROR: assigning to immutable field ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:617
|
|
msgid ""
|
|
"`match` patterns destructure structs. The basic syntax is `Name { fieldname: "
|
|
"pattern, ... }`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:626
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# let mypoint = Point { x: 0.0, y: 0.0 };\n"
|
|
"match mypoint {\n"
|
|
" Point { x: 0.0, y: yy } => { println(yy.to_str()); }\n"
|
|
" Point { x: xx, y: yy } => { println(xx.to_str() + \" \" + yy.to_str()); }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:633
|
|
msgid ""
|
|
"In general, the field names of a struct do not have to appear in the same "
|
|
"order they appear in the type. When you are not interested in all the fields "
|
|
"of a struct, a struct pattern may end with `, _` (as in `Name { field1, _ }"
|
|
"`) to indicate that you're ignoring all other fields. Additionally, struct "
|
|
"fields have a shorthand matching form that simply reuses the field name as "
|
|
"the binding name."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:641
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# let mypoint = Point { x: 0.0, y: 0.0 };\n"
|
|
"match mypoint {\n"
|
|
" Point { x, _ } => { println(x.to_str()) }\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:643
|
|
msgid "## Enums"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:646
|
|
msgid ""
|
|
"Enums are datatypes that have several alternate representations. For "
|
|
"example, consider the type shown earlier:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:654
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"enum Shape {\n"
|
|
" Circle(Point, float),\n"
|
|
" Rectangle(Point, Point)\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:660
|
|
msgid ""
|
|
"A value of this type is either a `Circle`, in which case it contains a "
|
|
"`Point` struct and a float, or a `Rectangle`, in which case it contains two "
|
|
"`Point` structs. The run-time representation of such a value includes an "
|
|
"identifier of the actual form that it holds, much like the \"tagged union\" "
|
|
"pattern in C, but with better static guarantees."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:666
|
|
msgid ""
|
|
"The above declaration will define a type `Shape` that can refer to such "
|
|
"shapes, and two functions, `Circle` and `Rectangle`, which can be used to "
|
|
"construct values of the type (taking arguments of the specified types). So "
|
|
"`Circle(Point { x: 0f, y: 0f }, 10f)` is the way to create a new circle."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:669
|
|
msgid ""
|
|
"Enum variants need not have parameters. This `enum` declaration, for "
|
|
"example, is equivalent to a C enum:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:678
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"enum Direction {\n"
|
|
" North,\n"
|
|
" East,\n"
|
|
" South,\n"
|
|
" West\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:681
|
|
msgid ""
|
|
"This declaration defines `North`, `East`, `South`, and `West` as constants, "
|
|
"all of which have type `Direction`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:685
|
|
msgid ""
|
|
"When an enum is C-like (that is, when none of the variants have parameters), "
|
|
"it is possible to explicitly set the discriminator values to a constant "
|
|
"value:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:693
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"enum Color {\n"
|
|
" Red = 0xff0000,\n"
|
|
" Green = 0x00ff00,\n"
|
|
" Blue = 0x0000ff\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:698
|
|
msgid ""
|
|
"If an explicit discriminator is not specified for a variant, the value "
|
|
"defaults to the value of the previous variant plus one. If the first variant "
|
|
"does not have a discriminator, it defaults to 0. For example, the value of "
|
|
"`North` is 0, `East` is 1, `South` is 2, and `West` is 3."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:701
|
|
msgid ""
|
|
"When an enum is C-like, you can apply the `as` cast operator to convert it "
|
|
"to its discriminator value as an `int`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:705
|
|
msgid ""
|
|
"For enum types with multiple variants, destructuring is the only way to get "
|
|
"at their contents. All variant constructors can be used as patterns, as in "
|
|
"this definition of `area`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:717
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::float;\n"
|
|
"# struct Point {x: float, y: float}\n"
|
|
"# enum Shape { Circle(Point, float), Rectangle(Point, Point) }\n"
|
|
"fn area(sh: Shape) -> float {\n"
|
|
" match sh {\n"
|
|
" Circle(_, size) => float::consts::pi * size * size,\n"
|
|
" Rectangle(Point { x, y }, Point { x: x2, y: y2 }) => (x2 - x) * (y2 - y)\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:722
|
|
msgid ""
|
|
"You can write a lone `_` to ignore an individual field, and can ignore all "
|
|
"fields of a variant like: `Circle(*)`. As in their introduction form, "
|
|
"nullary enum patterns are written without parentheses."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:735
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# enum Direction { North, East, South, West }\n"
|
|
"fn point_from_direction(dir: Direction) -> Point {\n"
|
|
" match dir {\n"
|
|
" North => Point { x: 0f, y: 1f },\n"
|
|
" East => Point { x: 1f, y: 0f },\n"
|
|
" South => Point { x: 0f, y: -1f },\n"
|
|
" West => Point { x: -1f, y: 0f }\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:737
|
|
msgid "Enum variants may also be structs. For example:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:755
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::float;\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# fn square(x: float) -> float { x * x }\n"
|
|
"enum Shape {\n"
|
|
" Circle { center: Point, radius: float },\n"
|
|
" Rectangle { top_left: Point, bottom_right: Point }\n"
|
|
"}\n"
|
|
"fn area(sh: Shape) -> float {\n"
|
|
" match sh {\n"
|
|
" Circle { radius: radius, _ } => float::consts::pi * square(radius),\n"
|
|
" Rectangle { top_left: top_left, bottom_right: bottom_right } => {\n"
|
|
" (bottom_right.x - top_left.x) * (bottom_right.y - top_left.y)\n"
|
|
" }\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:757
|
|
msgid "## Tuples"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:762
|
|
msgid ""
|
|
"Tuples in Rust behave exactly like structs, except that their fields do not "
|
|
"have names. Thus, you cannot access their fields with dot notation. Tuples "
|
|
"can have any arity except for 0 (though you may consider unit, `()`, as the "
|
|
"empty tuple if you like)."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:769
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let mytup: (int, int, float) = (10, 20, 30.0);\n"
|
|
"match mytup {\n"
|
|
" (a, b, c) => info!(a + b + (c as int))\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:771
|
|
msgid "## Tuple structs"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:776
|
|
msgid ""
|
|
"Rust also has _tuple structs_, which behave like both structs and tuples, "
|
|
"except that, unlike tuples, tuple structs have names (so `Foo(1, 2)` has a "
|
|
"different type from `Bar(1, 2)`), and tuple structs' _fields_ do not have "
|
|
"names."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:785
|
|
#, no-wrap
|
|
msgid ""
|
|
"For example:\n"
|
|
"~~~~\n"
|
|
"struct MyTup(int, int, float);\n"
|
|
"let mytup: MyTup = MyTup(10, 20, 30.0);\n"
|
|
"match mytup {\n"
|
|
" MyTup(a, b, c) => info!(a + b + (c as int))\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:787
|
|
msgid "<a name=\"newtype\"></a>"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:792
|
|
msgid ""
|
|
"There is a special case for tuple structs with a single field, which are "
|
|
"sometimes called \"newtypes\" (after Haskell's \"newtype\" feature). These "
|
|
"are used to define new types in such a way that the new name is not just a "
|
|
"synonym for an existing type but is rather its own distinct type."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:796
|
|
msgid "~~~~ struct GizmoId(int); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:799
|
|
msgid ""
|
|
"For convenience, you can extract the contents of such a struct with the "
|
|
"dereference (`*`) unary operator:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:805
|
|
msgid ""
|
|
"~~~~ # struct GizmoId(int); let my_gizmo_id: GizmoId = GizmoId(10); let "
|
|
"id_int: int = *my_gizmo_id; ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:808
|
|
msgid ""
|
|
"Types like this can be useful to differentiate between data that have the "
|
|
"same type but must be used in different ways."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:813
|
|
msgid "~~~~ struct Inches(int); struct Centimeters(int); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:816
|
|
msgid ""
|
|
"The above definitions allow for a simple way for programs to avoid confusing "
|
|
"numbers that correspond to different units."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:818
|
|
msgid "# Functions"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:826
|
|
msgid ""
|
|
"We've already seen several function definitions. Like all other static "
|
|
"declarations, such as `type`, functions can be declared both at the top "
|
|
"level and inside other functions (or in modules, which we'll come back to "
|
|
"[later](#modules-and-crates)). The `fn` keyword introduces a function. A "
|
|
"function has an argument list, which is a parenthesized list of `expr: type` "
|
|
"pairs separated by commas. An arrow `->` separates the argument list and the "
|
|
"function's return type."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:832
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn line(a: int, b: int, x: int) -> int {\n"
|
|
" return a * x + b;\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:837
|
|
msgid ""
|
|
"The `return` keyword immediately returns from the body of a function. It is "
|
|
"optionally followed by an expression to return. A function can also return a "
|
|
"value by having its top-level block produce an expression."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:843
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn line(a: int, b: int, x: int) -> int {\n"
|
|
" a * x + b\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:850
|
|
msgid ""
|
|
"It's better Rust style to write a return value this way instead of writing "
|
|
"an explicit `return`. The utility of `return` comes in when returning early "
|
|
"from a function. Functions that do not return a value are said to return "
|
|
"nil, `()`, and both the return type and the return value may be omitted from "
|
|
"the definition. The following two functions are equivalent."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:853
|
|
msgid "~~~~ fn do_nothing_the_hard_way() -> () { return (); }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:856
|
|
msgid "fn do_nothing_the_easy_way() { } ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:858
|
|
msgid ""
|
|
"Ending the function with a semicolon like so is equivalent to returning `()`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:862
|
|
msgid ""
|
|
"~~~~ fn line(a: int, b: int, x: int) -> int { a * x + b } fn oops(a: int, b: "
|
|
"int, x: int) -> () { a * x + b; }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:866
|
|
msgid "assert!(8 == line(5, 3, 1)); assert!(() == oops(5, 3, 1)); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:870
|
|
msgid ""
|
|
"As with `match` expressions and `let` bindings, function arguments support "
|
|
"pattern destructuring. Like `let`, argument patterns must be irrefutable, as "
|
|
"in this example that unpacks the first value from a tuple and returns it."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:874
|
|
msgid "~~~ fn first((value, _): (int, float)) -> int { value } ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:876 doc/tutorial-ffi.md:143
|
|
msgid "# Destructors"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:880
|
|
msgid ""
|
|
"A *destructor* is a function responsible for cleaning up the resources used "
|
|
"by an object when it is no longer accessible. Destructors can be defined to "
|
|
"handle the release of resources like files, sockets and heap memory."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:884
|
|
msgid ""
|
|
"Objects are never accessible after their destructor has been called, so "
|
|
"there are no dynamic failures from accessing freed resources. When a task "
|
|
"fails, the destructors of all objects in the task are called."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:886
|
|
msgid ""
|
|
"The `~` sigil represents a unique handle for a memory allocation on the heap:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:894
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"{\n"
|
|
" // an integer allocated on the heap\n"
|
|
" let y = ~10;\n"
|
|
"}\n"
|
|
"// the destructor frees the heap memory as soon as `y` goes out of scope\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:898
|
|
msgid ""
|
|
"Rust includes syntax for heap memory allocation in the language since it's "
|
|
"commonly used, but the same semantics can be implemented by a type with a "
|
|
"custom destructor."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:900
|
|
msgid "# Ownership"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:905
|
|
msgid ""
|
|
"Rust formalizes the concept of object ownership to delegate management of an "
|
|
"object's lifetime to either a variable or a task-local garbage collector. An "
|
|
"object's owner is responsible for managing the lifetime of the object by "
|
|
"calling the destructor, and the owner determines whether the object is "
|
|
"mutable."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:911
|
|
msgid ""
|
|
"Ownership is recursive, so mutability is inherited recursively and a "
|
|
"destructor destroys the contained tree of owned objects. Variables are top-"
|
|
"level owners and destroy the contained object when they go out of scope. A "
|
|
"box managed by the garbage collector starts a new ownership tree, and the "
|
|
"destructor is called when it is collected."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:915
|
|
msgid ""
|
|
"~~~~ // the struct owns the objects contained in the `x` and `y` fields "
|
|
"struct Foo { x: int, y: ~int }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:922
|
|
#, no-wrap
|
|
msgid ""
|
|
"{\n"
|
|
" // `a` is the owner of the struct, and thus the owner of the struct's fields\n"
|
|
" let a = Foo { x: 5, y: ~10 };\n"
|
|
"}\n"
|
|
"// when `a` goes out of scope, the destructor for the `~int` in the struct's\n"
|
|
"// field is called\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:927
|
|
msgid ""
|
|
"// `b` is mutable, and the mutability is inherited by the objects it owns "
|
|
"let mut b = Foo { x: 5, y: ~10 }; b.x = 10; ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:933
|
|
msgid ""
|
|
"If an object doesn't contain garbage-collected boxes, it consists of a "
|
|
"single ownership tree and is given the `Owned` trait which allows it to be "
|
|
"sent between tasks. Custom destructors can only be implemented directly on "
|
|
"types that are `Owned`, but garbage-collected boxes can still *contain* "
|
|
"types with custom destructors."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:935
|
|
msgid "# Boxes"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:942
|
|
msgid ""
|
|
"Many modern languages represent values as pointers to heap memory by "
|
|
"default. In contrast, Rust, like C and C++, represents such types directly. "
|
|
"Another way to say this is that aggregate data in Rust are *unboxed*. This "
|
|
"means that if you `let x = Point { x: 1f, y: 1f };`, you are creating a "
|
|
"struct on the stack. If you then copy it into a data structure, you copy the "
|
|
"entire struct, not just a pointer."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:947
|
|
msgid ""
|
|
"For small structs like `Point`, this is usually more efficient than "
|
|
"allocating memory and indirecting through a pointer. But for big structs, or "
|
|
"mutable state, it can be useful to have a single copy on the stack or on the "
|
|
"heap, and refer to that through a pointer."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:949
|
|
msgid "## Owned boxes"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:952
|
|
msgid ""
|
|
"An owned box (`~`) is a uniquely owned allocation on the heap. It inherits "
|
|
"the mutability and lifetime of the owner as it would if there was no box:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:957
|
|
msgid "~~~~ let x = 5; // immutable let mut y = 5; // mutable y += 2;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:962
|
|
msgid ""
|
|
"let x = ~5; // immutable let mut y = ~5; // mutable *y += 2; // the * "
|
|
"operator is needed to access the contained value ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:967
|
|
msgid ""
|
|
"The purpose of an owned box is to add a layer of indirection in order to "
|
|
"create recursive data structures or cheaply pass around an object larger "
|
|
"than a pointer. Since an owned box has a unique owner, it can only be used "
|
|
"to represent a tree data structure."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:970
|
|
msgid ""
|
|
"The following struct won't compile, because the lack of indirection would "
|
|
"mean it has an infinite size:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:976
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.xfail-test}\n"
|
|
"struct Foo {\n"
|
|
" child: Option<Foo>\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:980
|
|
msgid ""
|
|
"> ***Note:*** The `Option` type is an enum that represents an *optional* "
|
|
"value. > It's comparable to a nullable pointer in many other languages, but "
|
|
"stores the > contained value unboxed."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:984
|
|
msgid ""
|
|
"Adding indirection with an owned pointer allocates the child outside of the "
|
|
"struct on the heap, which makes it a finite size and won't result in a "
|
|
"compile-time error:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:990
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"struct Foo {\n"
|
|
" child: Option<~Foo>\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:992
|
|
msgid "## Managed boxes"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1000
|
|
msgid ""
|
|
"A managed box (`@`) is a heap allocation with the lifetime managed by a task-"
|
|
"local garbage collector. It will be destroyed at some point after there are "
|
|
"no references left to the box, no later than the end of the task. Managed "
|
|
"boxes lack an owner, so they start a new ownership tree and don't inherit "
|
|
"mutability. They do own the contained object, and mutability is defined by "
|
|
"the type of the shared box (`@` or `@mut`). An object containing a managed "
|
|
"box is not `Owned`, and can't be sent between tasks."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1003
|
|
msgid "~~~~ let a = @5; // immutable"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1006
|
|
msgid "let mut b = @5; // mutable variable, immutable box b = @10;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1009
|
|
msgid "let c = @mut 5; // immutable variable, mutable box *c = 10;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1014
|
|
msgid ""
|
|
"let mut d = @mut 5; // mutable variable, mutable box *d += 5; d = @mut 15; "
|
|
"~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1019
|
|
msgid ""
|
|
"A mutable variable and an immutable variable can refer to the same box, "
|
|
"given that their types are compatible. Mutability of a box is a property of "
|
|
"its type, however, so for example a mutable handle to an immutable box "
|
|
"cannot be assigned a reference to a mutable box."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1023
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let a = @1; // immutable box\n"
|
|
"let b = @mut 2; // mutable box\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1026
|
|
#, no-wrap
|
|
msgid ""
|
|
"let mut c : @int; // declare a variable with type managed immutable int\n"
|
|
"let mut d : @mut int; // and one of type managed mutable int\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1030
|
|
#, no-wrap
|
|
msgid ""
|
|
"c = a; // box type is the same, okay\n"
|
|
"d = b; // box type is the same, okay\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1035
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.xfail-test}\n"
|
|
"// but b cannot be assigned to c, or a to d\n"
|
|
"c = b; // error\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1037
|
|
msgid "# Move semantics"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1043
|
|
msgid ""
|
|
"Rust uses a shallow copy for parameter passing, assignment and returning "
|
|
"values from functions. A shallow copy is considered a move of ownership if "
|
|
"the ownership tree of the copied value includes an owned box or a type with "
|
|
"a custom destructor. After a value has been moved, it can no longer be used "
|
|
"from the source location and will not be destroyed there."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1049
|
|
msgid ""
|
|
"~~~~ let x = ~5; let y = x.clone(); // y is a newly allocated box let z = "
|
|
"x; // no new memory allocated, x can no longer be used ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1052
|
|
msgid ""
|
|
"Since in owned boxes mutability is a property of the owner, not the box, "
|
|
"mutable boxes may become immutable when they are moved, and vice-versa."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1059
|
|
msgid ""
|
|
"~~~~ let r = ~13; let mut s = r; // box becomes mutable *s += 1; let t = "
|
|
"s; // box becomes immutable ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1061
|
|
msgid "# Borrowed pointers"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1067
|
|
msgid ""
|
|
"Rust's borrowed pointers are a general purpose reference type. In contrast "
|
|
"with owned boxes, where the holder of an owned box is the owner of the "
|
|
"pointed-to memory, borrowed pointers never imply ownership. A pointer can be "
|
|
"borrowed to any object, and the compiler verifies that it cannot outlive the "
|
|
"lifetime of the object."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1069
|
|
msgid "As an example, consider a simple struct type, `Point`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1076
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"struct Point {\n"
|
|
" x: float,\n"
|
|
" y: float\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1080
|
|
msgid ""
|
|
"We can use this simple definition to allocate points in many different ways. "
|
|
"For example, in this code, each of these three local variables contains a "
|
|
"point, but allocated in a different location:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1087
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"let on_the_stack : Point = Point { x: 3.0, y: 4.0 };\n"
|
|
"let managed_box : @Point = @Point { x: 5.0, y: 1.0 };\n"
|
|
"let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1099
|
|
msgid ""
|
|
"Suppose we want to write a procedure that computes the distance between any "
|
|
"two points, no matter where they are stored. For example, we might like to "
|
|
"compute the distance between `on_the_stack` and `managed_box`, or between "
|
|
"`managed_box` and `owned_box`. One option is to define a function that takes "
|
|
"two arguments of type pointthat is, it takes the points by value. But this "
|
|
"will cause the points to be copied when we call the function. For points, "
|
|
"this is probably not so bad, but often copies are expensive or, worse, if "
|
|
"there are mutable fields, they can change the semantics of your program. So "
|
|
"wed like to define a function that takes the points by pointer. We can use "
|
|
"borrowed pointers to do this:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1109
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# fn sqrt(f: float) -> float { 0f }\n"
|
|
"fn compute_distance(p1: &Point, p2: &Point) -> float {\n"
|
|
" let x_d = p1.x - p2.x;\n"
|
|
" let y_d = p1.y - p2.y;\n"
|
|
" sqrt(x_d * x_d + y_d * y_d)\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1111 doc/tutorial-borrowed-ptr.md:72
|
|
msgid "Now we can call `compute_distance()` in various ways:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1121
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# struct Point{ x: float, y: float };\n"
|
|
"# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };\n"
|
|
"# let managed_box : @Point = @Point { x: 5.0, y: 1.0 };\n"
|
|
"# let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };\n"
|
|
"# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }\n"
|
|
"compute_distance(&on_the_stack, managed_box);\n"
|
|
"compute_distance(managed_box, owned_box);\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1128
|
|
msgid ""
|
|
"Here the `&` operator is used to take the address of the variable "
|
|
"`on_the_stack`; this is because `on_the_stack` has the type `Point` (that "
|
|
"is, a struct value) and we have to take its address to get a value. We also "
|
|
"call this _borrowing_ the local variable `on_the_stack`, because we are "
|
|
"creating an alias: that is, another route to the same data."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1134
|
|
msgid ""
|
|
"In the case of the boxes `managed_box` and `owned_box`, however, no explicit "
|
|
"action is necessary. The compiler will automatically convert a box like "
|
|
"`@point` or `~point` to a borrowed pointer like `&point`. This is another "
|
|
"form of borrowing; in this case, the contents of the managed/owned box are "
|
|
"being lent out."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1143
|
|
msgid ""
|
|
"Whenever a value is borrowed, there are some limitations on what you can do "
|
|
"with the original. For example, if the contents of a variable have been lent "
|
|
"out, you cannot send that variable to another task, nor will you be "
|
|
"permitted to take actions that might cause the borrowed value to be freed or "
|
|
"to change its type. This rule should make intuitive sense: you must wait for "
|
|
"a borrowed value to be returned (that is, for the borrowed pointer to go out "
|
|
"of scope) before you can make full use of it again."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1146
|
|
msgid ""
|
|
"For a more in-depth explanation of borrowed pointers, read the [borrowed "
|
|
"pointer tutorial][borrowtut]."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1148
|
|
msgid "[borrowtut]: tutorial-borrowed-ptr.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1150
|
|
msgid "## Freezing"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1153
|
|
msgid ""
|
|
"Borrowing an immutable pointer to an object freezes it and prevents "
|
|
"mutation. `Owned` objects have freezing enforced statically at compile-time."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1161
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let mut x = 5;\n"
|
|
"{\n"
|
|
" let y = &x; // x is now frozen, it cannot be modified\n"
|
|
"}\n"
|
|
"// x is now unfrozen again\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1165
|
|
msgid ""
|
|
"Mutable managed boxes handle freezing dynamically when any of their contents "
|
|
"are borrowed, and the task will fail if an attempt to modify them is made "
|
|
"while they are frozen:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1175
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let x = @mut 5;\n"
|
|
"let y = x;\n"
|
|
"{\n"
|
|
" let z = &*y; // the managed box is now frozen\n"
|
|
" // modifying it through x or y will cause a task failure\n"
|
|
"}\n"
|
|
"// the box is now unfrozen again\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1177
|
|
msgid "# Dereferencing pointers"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1180
|
|
msgid ""
|
|
"Rust uses the unary star operator (`*`) to access the contents of a box or "
|
|
"pointer, similarly to C."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1185
|
|
msgid "~~~ let managed = @10; let owned = ~20; let borrowed = &30;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1188
|
|
msgid "let sum = *managed + *owned + *borrowed; ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1192
|
|
msgid ""
|
|
"Dereferenced mutable pointers may appear on the left hand side of "
|
|
"assignments. Such an assignment modifies the value that the pointer points "
|
|
"to."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1196
|
|
msgid "~~~ let managed = @mut 10; let mut owned = ~20;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1199
|
|
msgid "let mut value = 30; let borrowed = &mut value;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1204
|
|
#, no-wrap
|
|
msgid ""
|
|
"*managed = *owned + 10;\n"
|
|
"*owned = *borrowed + 100;\n"
|
|
"*borrowed = *managed + 1000;\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1208
|
|
msgid ""
|
|
"Pointers have high operator precedence, but lower precedence than the dot "
|
|
"operator used for field and method access. This precedence order can "
|
|
"sometimes make code awkward and parenthesis-filled."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1218
|
|
msgid ""
|
|
"~~~ # struct Point { x: float, y: float } # enum Shape { Rectangle(Point, "
|
|
"Point) } # impl Shape { fn area(&self) -> int { 0 } } let start = @Point "
|
|
"{ x: 10f, y: 20f }; let end = ~Point { x: (*start).x + 100f, y: (*start).y + "
|
|
"100f }; let rect = &Rectangle(*start, *end); let area = (*rect).area(); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1222
|
|
msgid ""
|
|
"To combat this ugliness the dot operator applies _automatic pointer "
|
|
"dereferencing_ to the receiver (the value on the left-hand side of the dot), "
|
|
"so in most cases, explicitly dereferencing the receiver is not necessary."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1232
|
|
msgid ""
|
|
"~~~ # struct Point { x: float, y: float } # enum Shape { Rectangle(Point, "
|
|
"Point) } # impl Shape { fn area(&self) -> int { 0 } } let start = @Point "
|
|
"{ x: 10f, y: 20f }; let end = ~Point { x: start.x + 100f, y: start.y + "
|
|
"100f }; let rect = &Rectangle(*start, *end); let area = rect.area(); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1236
|
|
msgid ""
|
|
"You can write an expression that dereferences any number of pointers "
|
|
"automatically. For example, if you feel inclined, you could write something "
|
|
"silly like"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1242
|
|
msgid ""
|
|
"~~~ # struct Point { x: float, y: float } let point = &@~Point { x: 10f, y: "
|
|
"20f }; println(fmt!(\"%f\", point.x)); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1244
|
|
msgid "The indexing operator (`[]`) also auto-dereferences."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1246
|
|
msgid "# Vectors and strings"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1251
|
|
msgid ""
|
|
"A vector is a contiguous section of memory containing zero or more values of "
|
|
"the same type. Like other types in Rust, vectors can be stored on the stack, "
|
|
"the local heap, or the exchange heap. Borrowed pointers to vectors are also "
|
|
"called 'slices'."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1261
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# enum Crayon {\n"
|
|
"# Almond, AntiqueBrass, Apricot,\n"
|
|
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
|
"# BananaMania, Beaver, Bittersweet,\n"
|
|
"# Black, BlizzardBlue, Blue\n"
|
|
"# }\n"
|
|
"// A fixed-size stack vector\n"
|
|
"let stack_crayons: [Crayon, ..3] = [Almond, AntiqueBrass, Apricot];\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1264
|
|
msgid ""
|
|
"// A borrowed pointer to stack-allocated vector let stack_crayons: &[Crayon] "
|
|
"= &[Aquamarine, Asparagus, AtomicTangerine];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1267
|
|
msgid ""
|
|
"// A local heap (managed) vector of crayons let local_crayons: @[Crayon] = "
|
|
"@[BananaMania, Beaver, Bittersweet];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1271
|
|
msgid ""
|
|
"// An exchange heap (owned) vector of crayons let exchange_crayons: "
|
|
"~[Crayon] = ~[Black, BlizzardBlue, Blue]; ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1273
|
|
msgid "The `+` operator means concatenation when applied to vector types."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1278
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
|
|
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
|
"# BananaMania, Beaver, Bittersweet };\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1281
|
|
msgid ""
|
|
"let my_crayons = ~[Almond, AntiqueBrass, Apricot]; let your_crayons = "
|
|
"~[BananaMania, Beaver, Bittersweet];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1284
|
|
msgid ""
|
|
"// Add two vectors to create a new one let our_crayons = my_crayons + "
|
|
"your_crayons;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1289
|
|
msgid ""
|
|
"// .push_all() will append to a vector, provided it lives in a mutable slot "
|
|
"let mut my_crayons = my_crayons; my_crayons.push_all(your_crayons); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1294
|
|
msgid ""
|
|
"> ***Note:*** The above examples of vector addition use owned > vectors. "
|
|
"Some operations on slices and stack vectors are > not yet well-supported. "
|
|
"Owned vectors are often the most > usable."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1296
|
|
msgid "Square brackets denote indexing into a vector:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1308
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
|
|
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
|
"# BananaMania, Beaver, Bittersweet };\n"
|
|
"# fn draw_scene(c: Crayon) { }\n"
|
|
"let crayons: [Crayon, ..3] = [BananaMania, Beaver, Bittersweet];\n"
|
|
"match crayons[0] {\n"
|
|
" Bittersweet => draw_scene(crayons[0]),\n"
|
|
" _ => ()\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1310
|
|
msgid "A vector can be destructured using pattern matching:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1320
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"let numbers: [int, ..3] = [1, 2, 3];\n"
|
|
"let score = match numbers {\n"
|
|
" [] => 0,\n"
|
|
" [a] => a * 10,\n"
|
|
" [a, b] => a * 6 + b * 4,\n"
|
|
" [a, b, c, ..rest] => a * 5 + b * 3 + c * 2 + rest.len() as int\n"
|
|
"};\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1324
|
|
msgid ""
|
|
"The elements of a vector _inherit the mutability of the vector_, and as "
|
|
"such, individual elements may not be reassigned when the vector lives in an "
|
|
"immutable slot."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1330
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~ {.xfail-test}\n"
|
|
"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
|
|
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
|
"# BananaMania, Beaver, Bittersweet };\n"
|
|
"let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1333
|
|
msgid "crayons[0] = Apricot; // ERROR: Can't assign to immutable vector ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1335
|
|
msgid "Moving it into a mutable slot makes the elements assignable."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1341
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
|
|
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
|
"# BananaMania, Beaver, Bittersweet };\n"
|
|
"let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1344
|
|
msgid ""
|
|
"// Put the vector into a mutable slot let mut mutable_crayons = crayons;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1348
|
|
msgid "// Now it's mutable to the bone mutable_crayons[0] = Apricot; ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1351
|
|
msgid ""
|
|
"This is a simple example of Rust's _dual-mode data structures_, also "
|
|
"referred to as _freezing and thawing_."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1359
|
|
msgid ""
|
|
"Strings are implemented with vectors of `u8`, though they have a distinct "
|
|
"type. They support most of the same allocation options as vectors, though "
|
|
"the string literal without a storage sigil (for example, `\"foo\"`) is "
|
|
"treated differently than a comparable vector (`[foo]`). Whereas plain "
|
|
"vectors are stack-allocated fixed-length vectors, plain strings are borrowed "
|
|
"pointers to read-only (static) memory. All strings are immutable."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1363
|
|
msgid ""
|
|
"~~~ // A plain string is a slice to read-only (static) memory let "
|
|
"stack_crayons: &str = \"Almond, AntiqueBrass, Apricot\";"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1366
|
|
msgid ""
|
|
"// The same thing, but with the `&` let stack_crayons: &str = &\"Aquamarine, "
|
|
"Asparagus, AtomicTangerine\";"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1369
|
|
msgid ""
|
|
"// A local heap (managed) string let local_crayons: @str = @\"BananaMania, "
|
|
"Beaver, Bittersweet\";"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1373
|
|
msgid ""
|
|
"// An exchange heap (owned) string let exchange_crayons: ~str = ~\"Black, "
|
|
"BlizzardBlue, Blue\"; ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1377
|
|
msgid ""
|
|
"Both vectors and strings support a number of useful [methods](#functions-and-"
|
|
"methods), defined in [`std::vec`] and [`std::str`]. Here are some examples."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1380
|
|
msgid "[`std::vec`]: std/vec.html [`std::str`]: std/str.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1391
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# enum Crayon {\n"
|
|
"# Almond, AntiqueBrass, Apricot,\n"
|
|
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
|
"# BananaMania, Beaver, Bittersweet\n"
|
|
"# }\n"
|
|
"# fn unwrap_crayon(c: Crayon) -> int { 0 }\n"
|
|
"# fn eat_crayon_wax(i: int) { }\n"
|
|
"# fn store_crayon_in_nasal_cavity(i: uint, c: Crayon) { }\n"
|
|
"# fn crayon_to_str(c: Crayon) -> &str { \"\" }\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1393
|
|
msgid "let crayons = [Almond, AntiqueBrass, Apricot];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1397
|
|
msgid ""
|
|
"// Check the length of the vector assert!(crayons.len() == 3); assert!(!"
|
|
"crayons.is_empty());"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1404
|
|
#, no-wrap
|
|
msgid ""
|
|
"// Iterate over a vector, obtaining a pointer to each element\n"
|
|
"// (`for` is explained in the next section)\n"
|
|
"for crayons.iter().advance |crayon| {\n"
|
|
" let delicious_crayon_wax = unwrap_crayon(*crayon);\n"
|
|
" eat_crayon_wax(delicious_crayon_wax);\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1408
|
|
msgid ""
|
|
"// Map vector elements let crayon_names = crayons.map(|v| "
|
|
"crayon_to_str(*v)); let favorite_crayon_name = crayon_names[0];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1411
|
|
msgid ""
|
|
"// Remove whitespace from before and after the string let "
|
|
"new_favorite_crayon_name = favorite_crayon_name.trim();"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1417
|
|
#, no-wrap
|
|
msgid ""
|
|
"if favorite_crayon_name.len() > 5 {\n"
|
|
" // Create a substring\n"
|
|
" println(favorite_crayon_name.slice_chars(0, 5));\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1419
|
|
msgid "# Closures"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1424
|
|
msgid ""
|
|
"Named functions, like those we've seen so far, may not refer to local "
|
|
"variables declared outside the function: they do not close over their "
|
|
"environment (sometimes referred to as \"capturing\" variables in their "
|
|
"environment). For example, you couldn't write the following:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1427
|
|
msgid "~~~~ {.ignore} let foo = 10;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1432
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn bar() -> int {\n"
|
|
" return foo; // `bar` cannot refer to `foo`\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1435
|
|
msgid ""
|
|
"Rust also supports _closures_, functions that can access variables in the "
|
|
"enclosing scope."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1438
|
|
msgid "~~~~ fn call_closure_with_ten(b: &fn(int)) { b(10); }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1441
|
|
msgid ""
|
|
"let captured_var = 20; let closure = |arg| println(fmt!(\"captured_var=%d, "
|
|
"arg=%d\", captured_var, arg));"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1444
|
|
msgid "call_closure_with_ten(closure); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1450
|
|
msgid ""
|
|
"Closures begin with the argument list between vertical bars and are followed "
|
|
"by a single expression. Remember that a block, `{ <expr1>; <expr2>; ... }`, "
|
|
"is considered a single expression: it evaluates to the result of the last "
|
|
"expression it contains if that expression is not followed by a semicolon, "
|
|
"otherwise the block evaluates to `()`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1455
|
|
msgid ""
|
|
"The types of the arguments are generally omitted, as is the return type, "
|
|
"because the compiler can almost always infer them. In the rare case where "
|
|
"the compiler needs assistance, though, the arguments and return types may be "
|
|
"annotated."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1459
|
|
msgid "~~~~ let square = |x: int| -> uint { x * x as uint }; ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1463
|
|
msgid ""
|
|
"There are several forms of closure, each with its own role. The most common, "
|
|
"called a _stack closure_, has type `&fn` and can directly access local "
|
|
"variables in the enclosing scope."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1468
|
|
msgid "~~~~ let mut max = 0; [1, 2, 3].map(|x| if *x > max { max = *x }); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1477
|
|
msgid ""
|
|
"Stack closures are very efficient because their environment is allocated on "
|
|
"the call stack and refers by pointer to captured locals. To ensure that "
|
|
"stack closures never outlive the local variables to which they refer, stack "
|
|
"closures are not first-class. That is, they can only be used in argument "
|
|
"position; they cannot be stored in data structures or returned from "
|
|
"functions. Despite these limitations, stack closures are used pervasively in "
|
|
"Rust code."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1479
|
|
msgid "## Managed closures"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1485
|
|
msgid ""
|
|
"When you need to store a closure in a data structure, a stack closure will "
|
|
"not do, since the compiler will refuse to let you store it. For this "
|
|
"purpose, Rust provides a type of closure that has an arbitrary lifetime, "
|
|
"written `@fn` (boxed closure, analogous to the `@` pointer type described "
|
|
"earlier). This type of closure *is* first-class."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1490
|
|
msgid ""
|
|
"A managed closure does not directly access its environment, but merely "
|
|
"copies out the values that it closes over into a private data structure. "
|
|
"This means that it can not assign to these variables, and cannot observe "
|
|
"updates to them."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1493
|
|
msgid ""
|
|
"This code creates a closure that adds a given string to its argument, "
|
|
"returns it from a function, and then calls it:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1499
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str {\n"
|
|
" // The compiler knows that we intend this closure to be of type @fn\n"
|
|
" return |s| s + suffix;\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1505
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn main() {\n"
|
|
" let shout = mk_appender(~\"!\");\n"
|
|
" println(shout(~\"hey ho, let's go\"));\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1507
|
|
msgid "## Owned closures"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1514
|
|
msgid ""
|
|
"Owned closures, written `~fn` in analogy to the `~` pointer type, hold on to "
|
|
"things that can safely be sent between processes. They copy the values they "
|
|
"close over, much like managed closures, but they also own them: that is, no "
|
|
"other code can access them. Owned closures are used in concurrent code, "
|
|
"particularly for spawning [tasks][tasks]."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1516
|
|
msgid "[tasks]: tutorial-tasks.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1518
|
|
msgid "## Closure compatibility"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1525
|
|
msgid ""
|
|
"Rust closures have a convenient subtyping property: you can pass any kind of "
|
|
"closure (as long as the arguments and return types match) to functions that "
|
|
"expect a `&fn()`. Thus, when writing a higher-order function that only calls "
|
|
"its function argument, and does nothing else with it, you should almost "
|
|
"always declare the type of that argument as `&fn()`. That way, callers may "
|
|
"pass any kind of closure."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1533
|
|
msgid ""
|
|
"~~~~ fn call_twice(f: &fn()) { f(); f(); } let closure = || { \"I'm a "
|
|
"closure, and it doesn't matter what type I am\"; }; fn function() { \"I'm a "
|
|
"normal function\"; } call_twice(closure); call_twice(function); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1537
|
|
msgid ""
|
|
"> ***Note:*** Both the syntax and the semantics will be changing > in small "
|
|
"ways. At the moment they can be unsound in some > scenarios, particularly "
|
|
"with non-copyable types."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1539
|
|
msgid "## Do syntax"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1542
|
|
msgid ""
|
|
"The `do` expression provides a way to treat higher-order functions "
|
|
"(functions that take closures as arguments) as control structures."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1545
|
|
msgid ""
|
|
"Consider this function that iterates over a vector of integers, passing in a "
|
|
"pointer to each integer in the vector:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1555
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn each(v: &[int], op: &fn(v: &int)) {\n"
|
|
" let mut n = 0;\n"
|
|
" while n < v.len() {\n"
|
|
" op(&v[n]);\n"
|
|
" n += 1;\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1559
|
|
msgid ""
|
|
"As a caller, if we use a closure to provide the final operator argument, we "
|
|
"can write it in a way that has a pleasant, block-like structure."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1567
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# fn each(v: &[int], op: &fn(v: &int)) { }\n"
|
|
"# fn do_some_work(i: &int) { }\n"
|
|
"each([1, 2, 3], |n| {\n"
|
|
" do_some_work(n);\n"
|
|
"});\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1570
|
|
msgid ""
|
|
"This is such a useful pattern that Rust has a special form of function call "
|
|
"that can be written more like a built-in control structure:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1578
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# fn each(v: &[int], op: &fn(v: &int)) { }\n"
|
|
"# fn do_some_work(i: &int) { }\n"
|
|
"do each([1, 2, 3]) |n| {\n"
|
|
" do_some_work(n);\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1583
|
|
msgid ""
|
|
"The call is prefixed with the keyword `do` and, instead of writing the final "
|
|
"closure inside the argument list, it appears outside of the parentheses, "
|
|
"where it looks more like a typical block of code."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1588
|
|
msgid ""
|
|
"`do` is a convenient way to create tasks with the `task::spawn` function. "
|
|
"`spawn` has the signature `spawn(fn: ~fn())`. In other words, it is a "
|
|
"function that takes an owned closure that takes no arguments."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1591
|
|
msgid "~~~~ use std::task::spawn;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1596
|
|
#, no-wrap
|
|
msgid ""
|
|
"do spawn() || {\n"
|
|
" debug!(\"I'm a task, whatever\");\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1600
|
|
msgid ""
|
|
"Look at all those bars and parentheses -- that's two empty argument lists "
|
|
"back to back. Since that is so unsightly, empty argument lists may be "
|
|
"omitted from `do` expressions."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1607
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::task::spawn;\n"
|
|
"do spawn {\n"
|
|
" debug!(\"Kablam!\");\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1610
|
|
msgid ""
|
|
"If you want to see the output of `debug!` statements, you will need to turn "
|
|
"on `debug!` logging. To enable `debug!` logging, set the RUST_LOG "
|
|
"environment variable to the name of your crate, which, for a file named `foo."
|
|
"rs`, will be `foo` (e.g., with bash, `export RUST_LOG=foo`)."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1612
|
|
msgid "# Methods"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1618
|
|
msgid ""
|
|
"Methods are like functions except that they always begin with a special "
|
|
"argument, called `self`, which has the type of the method's receiver. The "
|
|
"`self` argument is like `this` in C++ and many other languages. Methods are "
|
|
"called with dot notation, as in `my_vec.len()`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1622
|
|
msgid ""
|
|
"_Implementations_, written with the `impl` keyword, can define methods on "
|
|
"most Rust types, including structs and enums. As an example, let's define a "
|
|
"`draw` method on our `Shape` enum."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1630
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# fn draw_circle(p: Point, f: float) { }\n"
|
|
"# fn draw_rectangle(p: Point, p: Point) { }\n"
|
|
"struct Point {\n"
|
|
" x: float,\n"
|
|
" y: float\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1635
|
|
#, no-wrap
|
|
msgid ""
|
|
"enum Shape {\n"
|
|
" Circle(Point, float),\n"
|
|
" Rectangle(Point, Point)\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1644
|
|
#, no-wrap
|
|
msgid ""
|
|
"impl Shape {\n"
|
|
" fn draw(&self) {\n"
|
|
" match *self {\n"
|
|
" Circle(p, f) => draw_circle(p, f),\n"
|
|
" Rectangle(p1, p2) => draw_rectangle(p1, p2)\n"
|
|
" }\n"
|
|
" }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1648
|
|
msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f); s.draw(); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1652
|
|
msgid ""
|
|
"This defines an _implementation_ for `Shape` containing a single method, "
|
|
"`draw`. In most respects the `draw` method is defined like any other "
|
|
"function, except for the name `self`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1657
|
|
msgid ""
|
|
"The type of `self` is the type on which the method is implemented, or a "
|
|
"pointer thereof. As an argument it is written either `self`, `&self`, "
|
|
"`@self`, or `~self`. A caller must in turn have a compatible pointer type "
|
|
"to call the method."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1672
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# fn draw_circle(p: Point, f: float) { }\n"
|
|
"# fn draw_rectangle(p: Point, p: Point) { }\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# enum Shape {\n"
|
|
"# Circle(Point, float),\n"
|
|
"# Rectangle(Point, Point)\n"
|
|
"# }\n"
|
|
"impl Shape {\n"
|
|
" fn draw_borrowed(&self) { ... }\n"
|
|
" fn draw_managed(@self) { ... }\n"
|
|
" fn draw_owned(~self) { ... }\n"
|
|
" fn draw_value(self) { ... }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1674
|
|
msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f);"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1680
|
|
msgid ""
|
|
"(@s).draw_managed(); (~s).draw_owned(); (&s).draw_borrowed(); s."
|
|
"draw_value(); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1684
|
|
msgid ""
|
|
"Methods typically take a borrowed pointer self type, so the compiler will go "
|
|
"to great lengths to convert a callee to a borrowed pointer."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1702
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# fn draw_circle(p: Point, f: float) { }\n"
|
|
"# fn draw_rectangle(p: Point, p: Point) { }\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# enum Shape {\n"
|
|
"# Circle(Point, float),\n"
|
|
"# Rectangle(Point, Point)\n"
|
|
"# }\n"
|
|
"# impl Shape {\n"
|
|
"# fn draw_borrowed(&self) { ... }\n"
|
|
"# fn draw_managed(@self) { ... }\n"
|
|
"# fn draw_owned(~self) { ... }\n"
|
|
"# fn draw_value(self) { ... }\n"
|
|
"# }\n"
|
|
"# let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
|
|
"// As with typical function arguments, managed and owned pointers\n"
|
|
"// are automatically converted to borrowed pointers\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1705
|
|
msgid "(@s).draw_borrowed(); (~s).draw_borrowed();"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1709
|
|
msgid ""
|
|
"// Unlike typical function arguments, the self value will // automatically "
|
|
"be referenced ... s.draw_borrowed();"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1712
|
|
msgid "// ... and dereferenced (& &s).draw_borrowed();"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1716
|
|
msgid "// ... and dereferenced and borrowed (&@~s).draw_borrowed(); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1720
|
|
msgid ""
|
|
"Implementations may also define standalone (sometimes called \"static\") "
|
|
"methods. The absence of a `self` parameter distinguishes such methods. "
|
|
"These methods are the preferred way to define constructor functions."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1727
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.xfail-test}\n"
|
|
"impl Circle {\n"
|
|
" fn area(&self) -> float { ... }\n"
|
|
" fn new(area: float) -> Circle { ... }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1729
|
|
msgid ""
|
|
"To call such a method, just prefix it with the type name and a double colon:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1738
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::float::consts::pi;\n"
|
|
"struct Circle { radius: float }\n"
|
|
"impl Circle {\n"
|
|
" fn new(area: float) -> Circle { Circle { radius: (area / pi).sqrt() } }\n"
|
|
"}\n"
|
|
"let c = Circle::new(42.5);\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1740
|
|
msgid "# Generics"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1748
|
|
msgid ""
|
|
"Throughout this tutorial, we've been defining functions that act only on "
|
|
"specific data types. With type parameters we can also define functions whose "
|
|
"arguments have generic types, and which can be invoked with a variety of "
|
|
"types. Consider a generic `map` function, which takes a function `function` "
|
|
"and a vector `vector` and returns a new vector consisting of the result of "
|
|
"applying `function` to each element of `vector`:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1758
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"fn map<T, U>(vector: &[T], function: &fn(v: &T) -> U) -> ~[U] {\n"
|
|
" let mut accumulator = ~[];\n"
|
|
" for vector.iter().advance |element| {\n"
|
|
" accumulator.push(function(element));\n"
|
|
" }\n"
|
|
" return accumulator;\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1763
|
|
msgid ""
|
|
"When defined with type parameters, as denoted by `<T, U>`, this function can "
|
|
"be applied to any type of vector, as long as the type of `function`'s "
|
|
"argument and the type of the vector's contents agree with each other."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1773
|
|
msgid ""
|
|
"Inside a generic function, the names of the type parameters (capitalized by "
|
|
"convention) stand for opaque types. All you can do with instances of these "
|
|
"types is pass them around: you can't apply any operations to them or pattern-"
|
|
"match on them. Note that instances of generic types are often passed by "
|
|
"pointer. For example, the parameter `function()` is supplied with a pointer "
|
|
"to a value of type `T` and not a value of type `T` itself. This ensures that "
|
|
"the function works with the broadest set of types possible, since some types "
|
|
"are expensive or illegal to copy and pass by value."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1775
|
|
msgid ""
|
|
"Generic `type`, `struct`, and `enum` declarations follow the same pattern:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1779
|
|
msgid "~~~~ # use std::hashmap::HashMap; type Set<T> = HashMap<T, ()>;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1783
|
|
#, no-wrap
|
|
msgid ""
|
|
"struct Stack<T> {\n"
|
|
" elements: ~[T]\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1789
|
|
#, no-wrap
|
|
msgid ""
|
|
"enum Option<T> {\n"
|
|
" Some(T),\n"
|
|
" None\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1792
|
|
msgid ""
|
|
"These declarations can be instantiated to valid types like `Set<int>`, "
|
|
"`Stack<int>`, and `Option<int>`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1798
|
|
msgid ""
|
|
"The last type in that example, `Option`, appears frequently in Rust code. "
|
|
"Because Rust does not have null pointers (except in unsafe code), we need "
|
|
"another way to write a function whose result isn't defined on every possible "
|
|
"combination of arguments of the appropriate types. The usual way is to write "
|
|
"a function that returns `Option<T>` instead of `T`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1809
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# enum Shape { Circle(Point, float), Rectangle(Point, Point) }\n"
|
|
"fn radius(shape: Shape) -> Option<float> {\n"
|
|
" match shape {\n"
|
|
" Circle(_, radius) => Some(radius),\n"
|
|
" Rectangle(*) => None\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1817
|
|
msgid ""
|
|
"The Rust compiler compiles generic functions very efficiently by "
|
|
"*monomorphizing* them. *Monomorphization* is a fancy name for a simple idea: "
|
|
"generate a separate copy of each generic function at each call site, a copy "
|
|
"that is specialized to the argument types and can thus be optimized "
|
|
"specifically for them. In this respect, Rust's generics have similar "
|
|
"performance characteristics to C++ templates."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1819
|
|
msgid "## Traits"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1829
|
|
msgid ""
|
|
"Within a generic function the operations available on generic types are very "
|
|
"limited. After all, since the function doesn't know what types it is "
|
|
"operating on, it can't safely modify or query their values. This is where "
|
|
"_traits_ come into play. Traits are Rust's most powerful tool for writing "
|
|
"polymorphic code. Java developers will see them as similar to Java "
|
|
"interfaces, and Haskellers will notice their similarities to type classes. "
|
|
"Rust's traits are a form of *bounded polymorphism*: a trait is a way of "
|
|
"limiting the set of possible types that a type parameter could refer to."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1836
|
|
msgid ""
|
|
"As motivation, let us consider copying in Rust. The `copy` operation is not "
|
|
"defined for all Rust types. One reason is user-defined destructors: copying "
|
|
"a type that has a destructor could result in the destructor running multiple "
|
|
"times. Therefore, types with user-defined destructors cannot be copied, "
|
|
"either implicitly or explicitly, and neither can types that own other types "
|
|
"containing destructors."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1840
|
|
msgid ""
|
|
"This complicates handling of generic functions. If you have a type parameter "
|
|
"`T`, can you copy values of that type? In Rust, you can't, and if you try to "
|
|
"run the following code the compiler will complain."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1847
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.xfail-test}\n"
|
|
"// This does not compile\n"
|
|
"fn head_bad<T>(v: &[T]) -> T {\n"
|
|
" v[0] // error: copying a non-copyable value\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1852
|
|
msgid ""
|
|
"However, we can tell the compiler that the `head` function is only for "
|
|
"copyable types: that is, those that have the `Copy` trait. In that case, we "
|
|
"can explicitly create a second copy of the value we are returning using the "
|
|
"`copy` keyword:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1859
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"// This does\n"
|
|
"fn head<T: Copy>(v: &[T]) -> T {\n"
|
|
" copy v[0]\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1867
|
|
msgid ""
|
|
"This says that we can call `head` on any type `T` as long as that type "
|
|
"implements the `Copy` trait. When instantiating a generic function, you can "
|
|
"only instantiate it with types that implement the correct trait, so you "
|
|
"could not apply `head` to a type with a destructor. (`Copy` is a special "
|
|
"trait that is built in to the compiler, making it possible for the compiler "
|
|
"to enforce this restriction.)"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1871
|
|
msgid ""
|
|
"While most traits can be defined and implemented by user code, three traits "
|
|
"are automatically derived and implemented for all applicable types by the "
|
|
"compiler, and may not be overridden:"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:1875
|
|
msgid ""
|
|
"`Copy` - Types that can be copied, either implicitly, or explicitly with the "
|
|
"`copy` operator. All types are copyable unless they have destructors or "
|
|
"contain types with destructors."
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:1879
|
|
msgid ""
|
|
"`Owned` - Owned types. Types are owned unless they contain managed boxes, "
|
|
"managed closures, or borrowed pointers. Owned types may or may not be "
|
|
"copyable."
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:1882
|
|
msgid ""
|
|
"`Const` - Constant (immutable) types. These are types that do not contain "
|
|
"mutable fields."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1885
|
|
msgid ""
|
|
"> ***Note:*** These three traits were referred to as 'kinds' in earlier > "
|
|
"iterations of the language, and often still are."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1891
|
|
msgid ""
|
|
"Additionally, the `Drop` trait is used to define destructors. This trait "
|
|
"defines one method called `drop`, which is automatically called when a value "
|
|
"of the type that implements this trait is destroyed, either because the "
|
|
"value went out of scope or because the garbage collector reclaimed it."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1896
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"struct TimeBomb {\n"
|
|
" explosivity: uint\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1905
|
|
#, no-wrap
|
|
msgid ""
|
|
"impl Drop for TimeBomb {\n"
|
|
" fn drop(&self) {\n"
|
|
" for self.explosivity.times {\n"
|
|
" println(\"blam!\");\n"
|
|
" }\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1908
|
|
msgid ""
|
|
"It is illegal to call `drop` directly. Only code inserted by the compiler "
|
|
"may call it."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1910
|
|
msgid "## Declaring and implementing traits"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1915
|
|
msgid ""
|
|
"A trait consists of a set of methods, without bodies, or may be empty, as is "
|
|
"the case with `Copy`, `Owned`, and `Const`. For example, we could declare "
|
|
"the trait `Printable` for things that can be printed to the console, with a "
|
|
"single method:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1921
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"trait Printable {\n"
|
|
" fn print(&self);\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1926
|
|
msgid ""
|
|
"Traits may be implemented for specific types with [impls]. An impl that "
|
|
"implements a trait includes the name of the trait at the start of the "
|
|
"definition, as in the following impls of `Printable` for `int` and `~str`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1928
|
|
msgid "[impls]: #functions-and-methods"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1934
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# trait Printable { fn print(&self); }\n"
|
|
"impl Printable for int {\n"
|
|
" fn print(&self) { println(fmt!(\"%d\", *self)) }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1938
|
|
#, no-wrap
|
|
msgid ""
|
|
"impl Printable for ~str {\n"
|
|
" fn print(&self) { println(*self) }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1942
|
|
msgid "# 1.print(); # (~\"foo\").print(); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1947
|
|
msgid ""
|
|
"Methods defined in an implementation of a trait may be called just like any "
|
|
"other method, using dot notation, as in `1.print()`. Traits may themselves "
|
|
"contain type parameters. A trait for generalized sequence types might look "
|
|
"like the following:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1952
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"trait Seq<T> {\n"
|
|
" fn length(&self) -> uint;\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1957
|
|
#, no-wrap
|
|
msgid ""
|
|
"impl<T> Seq<T> for ~[T] {\n"
|
|
" fn length(&self) -> uint { self.len() }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1964
|
|
msgid ""
|
|
"The implementation has to explicitly declare the type parameter that it "
|
|
"binds, `T`, before using it to specify its trait type. Rust requires this "
|
|
"declaration because the `impl` could also, for example, specify an "
|
|
"implementation of `Seq<int>`. The trait type (appearing between `impl` and "
|
|
"`for`) *refers* to a type, rather than defining one."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1969
|
|
msgid ""
|
|
"The type parameters bound by a trait are in scope in each of the method "
|
|
"declarations. So, re-declaring the type parameter `T` as an explicit type "
|
|
"parameter for `len`, in either the trait or the impl, would be a compile-"
|
|
"time error."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1974
|
|
msgid ""
|
|
"Within a trait definition, `Self` is a special type that you can think of as "
|
|
"a type parameter. An implementation of the trait for any given type `T` "
|
|
"replaces the `Self` type parameter with `T`. The following trait describes "
|
|
"types that support an equality operation:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1981
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"// In a trait, `self` refers to the self argument.\n"
|
|
"// `Self` refers to the type implementing the trait.\n"
|
|
"trait Eq {\n"
|
|
" fn equals(&self, other: &Self) -> bool;\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1987
|
|
#, no-wrap
|
|
msgid ""
|
|
"// In an impl, `self` refers just to the value of the receiver\n"
|
|
"impl Eq for int {\n"
|
|
" fn equals(&self, other: &int) -> bool { *other == *self }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1992
|
|
msgid ""
|
|
"Notice that in the trait definition, `equals` takes a second parameter of "
|
|
"type `Self`. In contrast, in the `impl`, `equals` takes a second parameter "
|
|
"of type `int`, only using `self` as the name of the receiver."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:1997
|
|
msgid ""
|
|
"Just as in type implementations, traits can define standalone (static) "
|
|
"methods. These methods are called by prefixing the method name with the "
|
|
"trait name and a double colon. The compiler uses type inference to decide "
|
|
"which implementation to use."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2003
|
|
msgid ""
|
|
"~~~~ # use std::float::consts::pi; trait Shape { fn new(area: float) -> "
|
|
"Self; } struct Circle { radius: float } struct Square { length: float }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2010
|
|
#, no-wrap
|
|
msgid ""
|
|
"impl Shape for Circle {\n"
|
|
" fn new(area: float) -> Circle { Circle { radius: (area / pi).sqrt() } }\n"
|
|
"}\n"
|
|
"impl Shape for Square {\n"
|
|
" fn new(area: float) -> Square { Square { length: (area).sqrt() } }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2015
|
|
msgid ""
|
|
"let area = 42.5; let c: Circle = Shape::new(area); let s: Square = Shape::"
|
|
"new(area); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2017
|
|
msgid "## Bounded type parameters and static method dispatch"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2022
|
|
msgid ""
|
|
"Traits give us a language for defining predicates on types, or abstract "
|
|
"properties that types can have. We can use this language to define _bounds_ "
|
|
"on type parameters, so that we can then operate on generic types."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2031
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# trait Printable { fn print(&self); }\n"
|
|
"fn print_all<T: Printable>(printable_things: ~[T]) {\n"
|
|
" for printable_things.iter().advance |thing| {\n"
|
|
" thing.print();\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2037
|
|
msgid ""
|
|
"Declaring `T` as conforming to the `Printable` trait (as we earlier did with "
|
|
"`Copy`) makes it possible to call methods from that trait on values of type "
|
|
"`T` inside the function. It will also cause a compile-time error when anyone "
|
|
"tries to call `print_all` on an array whose element type does not have a "
|
|
"`Printable` implementation."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2040
|
|
msgid ""
|
|
"Type parameters can have multiple bounds by separating them with `+`, as in "
|
|
"this version of `print_all` that copies elements."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2052
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"# trait Printable { fn print(&self); }\n"
|
|
"fn print_all<T: Printable + Copy>(printable_things: ~[T]) {\n"
|
|
" let mut i = 0;\n"
|
|
" while i < printable_things.len() {\n"
|
|
" let copy_of_thing = copy printable_things[i];\n"
|
|
" copy_of_thing.print();\n"
|
|
" i += 1;\n"
|
|
" }\n"
|
|
"}\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2056
|
|
msgid ""
|
|
"Method calls to bounded type parameters are _statically dispatched_, "
|
|
"imposing no more overhead than normal function invocation, so are the "
|
|
"preferred way to use traits polymorphically."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2058
|
|
msgid "This usage of traits is similar to Haskell type classes."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2060
|
|
msgid "## Trait objects and dynamic method dispatch"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2064
|
|
msgid ""
|
|
"The above allows us to define functions that polymorphically act on values "
|
|
"of a single unknown type that conforms to a given trait. However, consider "
|
|
"this function:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2070
|
|
msgid ""
|
|
"~~~~ # type Circle = int; type Rectangle = int; # impl Drawable for int { fn "
|
|
"draw(&self) {} } # fn new_circle() -> int { 1 } trait Drawable { fn "
|
|
"draw(&self); }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2077
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn draw_all<T: Drawable>(shapes: ~[T]) {\n"
|
|
" for shapes.iter().advance |shape| { shape.draw(); }\n"
|
|
"}\n"
|
|
"# let c: Circle = new_circle();\n"
|
|
"# draw_all(~[c]);\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2083
|
|
msgid ""
|
|
"You can call that on an array of circles, or an array of rectangles "
|
|
"(assuming those have suitable `Drawable` traits defined), but not on an "
|
|
"array containing both circles and rectangles. When such behavior is needed, "
|
|
"a trait name can alternately be used as a type, called an _object_."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2090
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# trait Drawable { fn draw(&self); }\n"
|
|
"fn draw_all(shapes: &[@Drawable]) {\n"
|
|
" for shapes.iter().advance |shape| { shape.draw(); }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2095
|
|
msgid ""
|
|
"In this example, there is no type parameter. Instead, the `@Drawable` type "
|
|
"denotes any managed box value that implements the `Drawable` trait. To "
|
|
"construct such a value, you use the `as` operator to cast a value to an "
|
|
"object:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2102
|
|
msgid ""
|
|
"~~~~ # type Circle = int; type Rectangle = bool; # trait Drawable { fn "
|
|
"draw(&self); } # fn new_circle() -> Circle { 1 } # fn new_rectangle() -> "
|
|
"Rectangle { true } # fn draw_all(shapes: &[@Drawable]) {}"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2105
|
|
msgid ""
|
|
"impl Drawable for Circle { fn draw(&self) { ... } } impl Drawable for "
|
|
"Rectangle { fn draw(&self) { ... } }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2110
|
|
msgid ""
|
|
"let c: @Circle = @new_circle(); let r: @Rectangle = @new_rectangle(); "
|
|
"draw_all([c as @Drawable, r as @Drawable]); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2118
|
|
msgid ""
|
|
"We omit the code for `new_circle` and `new_rectangle`; imagine that these "
|
|
"just return `Circle`s and `Rectangle`s with a default size. Note that, like "
|
|
"strings and vectors, objects have dynamic size and may only be referred to "
|
|
"via one of the pointer types. Other pointer types work as well. Casts to "
|
|
"traits may only be done with compatible pointers so, for example, an "
|
|
"`@Circle` may not be cast to an `~Drawable`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2132
|
|
msgid ""
|
|
"~~~ # type Circle = int; type Rectangle = int; # trait Drawable { fn "
|
|
"draw(&self); } # impl Drawable for int { fn draw(&self) {} } # fn "
|
|
"new_circle() -> int { 1 } # fn new_rectangle() -> int { 2 } // A managed "
|
|
"object let boxy: @Drawable = @new_circle() as @Drawable; // An owned object "
|
|
"let owny: ~Drawable = ~new_circle() as ~Drawable; // A borrowed object let "
|
|
"stacky: &Drawable = &new_circle() as &Drawable; ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2137
|
|
msgid ""
|
|
"Method calls to trait types are _dynamically dispatched_. Since the compiler "
|
|
"doesn't know specifically which functions to call at compile time, it uses a "
|
|
"lookup table (also known as a vtable or dictionary) to select the method to "
|
|
"call at runtime."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2139
|
|
msgid "This usage of traits is similar to Java interfaces."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2141
|
|
msgid "## Trait inheritance"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2146
|
|
msgid ""
|
|
"We can write a trait declaration that _inherits_ from other traits, called "
|
|
"_supertraits_. Types that implement a trait must also implement its "
|
|
"supertraits. For example, we can define a `Circle` trait that inherits from "
|
|
"`Shape`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2151
|
|
msgid ""
|
|
"~~~~ trait Shape { fn area(&self) -> float; } trait Circle : Shape { fn "
|
|
"radius(&self) -> float; } ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2153
|
|
msgid ""
|
|
"Now, we can implement `Circle` on a type only if we also implement `Shape`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2168
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"# use std::float::consts::pi;\n"
|
|
"# trait Shape { fn area(&self) -> float; }\n"
|
|
"# trait Circle : Shape { fn radius(&self) -> float; }\n"
|
|
"# struct Point { x: float, y: float }\n"
|
|
"# fn square(x: float) -> float { x * x }\n"
|
|
"struct CircleStruct { center: Point, radius: float }\n"
|
|
"impl Circle for CircleStruct {\n"
|
|
" fn radius(&self) -> float { (self.area() / pi).sqrt() }\n"
|
|
"}\n"
|
|
"impl Shape for CircleStruct {\n"
|
|
" fn area(&self) -> float { pi * square(self.radius) }\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2173
|
|
msgid ""
|
|
"Notice that methods of `Circle` can call methods on `Shape`, as our `radius` "
|
|
"implementation calls the `area` method. This is a silly way to compute the "
|
|
"radius of a circle (since we could just return the `radius` field), but you "
|
|
"get the idea."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2197
|
|
msgid ""
|
|
"~~~ {.xfail-test} # use std::float::consts::pi; # trait Shape { fn "
|
|
"area(&self) -> float; } # trait Circle : Shape { fn radius(&self) -> "
|
|
"float; } # struct Point { x: float, y: float } # struct CircleStruct "
|
|
"{ center: Point, radius: float } # impl Circle for CircleStruct { fn "
|
|
"radius(&self) -> float { (self.area() / pi).sqrt() } } # impl Shape for "
|
|
"CircleStruct { fn area(&self) -> float { pi * square(self.radius) } }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2202
|
|
msgid ""
|
|
"let concrete = @CircleStruct{center:Point{x:3f,y:4f},radius:5f}; let "
|
|
"mycircle: Circle = concrete as @Circle; let nonsense = mycircle.radius() * "
|
|
"mycircle.area(); ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2204
|
|
msgid "> ***Note:*** Trait inheritance does not actually work with objects yet"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2206
|
|
msgid "## Deriving implementations for traits"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2213
|
|
msgid ""
|
|
"A small number of traits in `std` and `extra` can have implementations that "
|
|
"can be automatically derived. These instances are specified by placing the "
|
|
"`deriving` attribute on a data type declaration. For example, the following "
|
|
"will mean that `Circle` has an implementation for `Eq` and can be used with "
|
|
"the equality operators, and that a value of type `ABC` can be randomly "
|
|
"generated and converted to a string:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2217
|
|
msgid "~~~ #[deriving(Eq)] struct Circle { radius: float }"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2221
|
|
msgid "#[deriving(Rand, ToStr)] enum ABC { A, B, C } ~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2225
|
|
msgid ""
|
|
"The full list of derivable traits is `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
|
|
"`Encodable` `Decodable`, `Clone`, `DeepClone`, `IterBytes`, `Rand`, `Zero`, "
|
|
"and `ToStr`."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2227
|
|
msgid "# Modules and crates"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2231
|
|
msgid ""
|
|
"The Rust namespace is arranged in a hierarchy of modules. Each source (.rs) "
|
|
"file represents a single module and may in turn contain additional modules."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2237
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~\n"
|
|
"mod farm {\n"
|
|
" pub fn chicken() -> &str { \"cluck cluck\" }\n"
|
|
" pub fn cow() -> &str { \"mooo\" }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2242
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn main() {\n"
|
|
" println(farm::chicken());\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2247
|
|
msgid ""
|
|
"The contents of modules can be imported into the current scope with the "
|
|
"`use` keyword, optionally giving it an alias. `use` may appear at the "
|
|
"beginning of crates, `mod`s, `fn`s, and other blocks."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2253
|
|
msgid ""
|
|
"~~~ # mod farm { pub fn chicken() { } } # fn main() { // Bring `chicken` "
|
|
"into scope use farm::chicken;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2263
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn chicken_farmer() {\n"
|
|
" // The same, but name it `my_chicken`\n"
|
|
" use my_chicken = farm::chicken;\n"
|
|
" ...\n"
|
|
"# my_chicken();\n"
|
|
"}\n"
|
|
"# chicken();\n"
|
|
"# }\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2270
|
|
msgid ""
|
|
"These farm animal functions have a new keyword, `pub`, attached to them. The "
|
|
"`pub` keyword modifies an item's visibility, making it visible outside its "
|
|
"containing module. An expression with `::`, like `farm::chicken`, can name "
|
|
"an item outside of its containing module. Items, such as those declared with "
|
|
"`fn`, `struct`, `enum`, `type`, or `static`, are module-private by default."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2277
|
|
msgid ""
|
|
"Visibility restrictions in Rust exist only at module boundaries. This is "
|
|
"quite different from most object-oriented languages that also enforce "
|
|
"restrictions on objects themselves. That's not to say that Rust doesn't "
|
|
"support encapsulation: both struct fields and methods can be private. But "
|
|
"this encapsulation is at the module level, not the struct level. Note that "
|
|
"fields and methods are _public_ by default."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2290
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~\n"
|
|
"pub mod farm {\n"
|
|
"# pub type Chicken = int;\n"
|
|
"# type Cow = int;\n"
|
|
"# struct Human(int);\n"
|
|
"# impl Human { fn rest(&self) { } }\n"
|
|
"# pub fn make_me_a_farm() -> Farm { Farm { chickens: ~[], cows: ~[], farmer: Human(0) } }\n"
|
|
" pub struct Farm {\n"
|
|
" priv chickens: ~[Chicken],\n"
|
|
" priv cows: ~[Cow],\n"
|
|
" farmer: Human\n"
|
|
" }\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2296
|
|
#, no-wrap
|
|
msgid ""
|
|
" impl Farm {\n"
|
|
" priv fn feed_chickens(&self) { ... }\n"
|
|
" priv fn feed_cows(&self) { ... }\n"
|
|
" pub fn add_chicken(&self, c: Chicken) { ... }\n"
|
|
" }\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2302
|
|
#, no-wrap
|
|
msgid ""
|
|
" pub fn feed_animals(farm: &Farm) {\n"
|
|
" farm.feed_chickens();\n"
|
|
" farm.feed_cows();\n"
|
|
" }\n"
|
|
"}\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2312
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn main() {\n"
|
|
" let f = make_me_a_farm();\n"
|
|
" f.add_chicken(make_me_a_chicken());\n"
|
|
" farm::feed_animals(&f);\n"
|
|
" f.farmer.rest();\n"
|
|
"}\n"
|
|
"# fn make_me_a_farm() -> farm::Farm { farm::make_me_a_farm() }\n"
|
|
"# fn make_me_a_chicken() -> farm::Chicken { 0 }\n"
|
|
"~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2314
|
|
msgid "## Crates"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2318
|
|
msgid ""
|
|
"The unit of independent compilation in Rust is the crate: rustc compiles a "
|
|
"single crate at a time, from which it produces either a library or an "
|
|
"executable."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2323
|
|
msgid ""
|
|
"When compiling a single `.rs` source file, the file acts as the whole "
|
|
"crate. You can compile it with the `--lib` compiler switch to create a "
|
|
"shared library, or without, provided that your file contains a `fn main` "
|
|
"somewhere, to create an executable."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2328
|
|
msgid ""
|
|
"Larger crates typically span multiple files and are, by convention, compiled "
|
|
"from a source file with the `.rc` extension, called a *crate file*. The "
|
|
"crate file extension distinguishes source files that represent crates from "
|
|
"those that do not, but otherwise source files and crate files are identical."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2337
|
|
msgid ""
|
|
"A typical crate file declares attributes associated with the crate that may "
|
|
"affect how the compiler processes the source. Crate attributes specify "
|
|
"metadata used for locating and linking crates, the type of crate (library or "
|
|
"executable), and control warning and error behavior, among other things. "
|
|
"Crate files additionally declare the external crates they depend on as well "
|
|
"as any modules loaded from other files."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2341
|
|
msgid ""
|
|
"~~~~ { .xfail-test } // Crate linkage metadata #[link(name = \"farm\", vers "
|
|
"= \"2.5\", author = \"mjh\")];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2344
|
|
msgid "// Make a library (\"bin\" is the default) #[crate_type = \"lib\"];"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2347
|
|
msgid "// Turn on a warning #[warn(non_camel_case_types)]"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2350
|
|
msgid "// Link to the standard library extern mod std;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2355
|
|
msgid "// Load some modules from other files mod cow; mod chicken; mod horse;"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2360
|
|
#, no-wrap
|
|
msgid ""
|
|
"fn main() {\n"
|
|
" ...\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2367
|
|
msgid ""
|
|
"Compiling this file will cause `rustc` to look for files named `cow.rs`, "
|
|
"`chicken.rs`, and `horse.rs` in the same directory as the `.rc` file, "
|
|
"compile them all together, and, based on the presence of the `crate_type = "
|
|
"\"lib\"` attribute, output a shared library or an executable. (If the line "
|
|
"`#[crate_type = \"lib\"];` was omitted, `rustc` would create an executable.)"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2371
|
|
msgid ""
|
|
"The `#[link(...)]` attribute provides meta information about the module, "
|
|
"which other crates can use to load the right module. More about that later."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2374
|
|
msgid ""
|
|
"To have a nested directory structure for your source files, you can nest "
|
|
"mods:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2381
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.ignore}\n"
|
|
"mod poultry {\n"
|
|
" mod chicken;\n"
|
|
" mod turkey;\n"
|
|
"}\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2386
|
|
msgid ""
|
|
"The compiler will now look for `poultry/chicken.rs` and `poultry/turkey.rs`, "
|
|
"and export their content in `poultry::chicken` and `poultry::turkey`. You "
|
|
"can also provide a `poultry.rs` to add content to the `poultry` module "
|
|
"itself."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2388
|
|
msgid "## Using other crates"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2396
|
|
msgid ""
|
|
"The `extern mod` directive lets you use a crate (once it's been compiled "
|
|
"into a library) from inside another crate. `extern mod` can appear at the "
|
|
"top of a crate file or at the top of modules. It will cause the compiler to "
|
|
"look in the library search path (which you can extend with the `-L` switch) "
|
|
"for a compiled Rust library with the right name, then add a module with that "
|
|
"crate's name into the local scope."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2398
|
|
msgid "For example, `extern mod std` links the [standard library]."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2400
|
|
msgid "[standard library]: std/index.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2407
|
|
msgid ""
|
|
"When a comma-separated list of name/value pairs appears after `extern mod`, "
|
|
"the compiler front-end matches these pairs against the attributes provided "
|
|
"in the `link` attribute of the crate file. The front-end will only select "
|
|
"this crate for use if the actual pairs match the declared attributes. You "
|
|
"can provide a `name` value to override the name used to search for the crate."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2409
|
|
msgid "Our example crate declared this set of `link` attributes:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2413
|
|
msgid "~~~~ #[link(name = \"farm\", vers = \"2.5\", author = \"mjh\")]; ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2415
|
|
msgid "Which you can then link with any (or all) of the following:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2421
|
|
msgid ""
|
|
"~~~~ {.xfail-test} extern mod farm; extern mod my_farm (name = \"farm\", "
|
|
"vers = \"2.5\"); extern mod my_auxiliary_farm (name = \"farm\", author = "
|
|
"\"mjh\"); ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2424
|
|
msgid ""
|
|
"If any of the requested metadata do not match, then the crate will not be "
|
|
"compiled successfully."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2426
|
|
msgid "## A minimal example"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2429
|
|
msgid ""
|
|
"Now for something that you can actually compile yourself, we have these two "
|
|
"files:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2435
|
|
msgid ""
|
|
"~~~~ // world.rs #[link(name = \"world\", vers = \"1.0\")]; pub fn explore() "
|
|
"-> &str { \"world\" } ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2441
|
|
msgid ""
|
|
"~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello "
|
|
"\" + world::explore()); } ~~~~"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2443
|
|
msgid "Now compile and run like this (adjust to your platform if necessary):"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2450
|
|
#, no-wrap
|
|
msgid ""
|
|
"~~~~ {.notrust}\n"
|
|
"> rustc --lib world.rs # compiles libworld-94839cbfe144198-1.0.so\n"
|
|
"> rustc main.rs -L . # compiles main\n"
|
|
"> ./main\n"
|
|
"\"hello world\"\n"
|
|
"~~~~\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2455
|
|
msgid ""
|
|
"Notice that the library produced contains the version in the filename as "
|
|
"well as an inscrutable string of alphanumerics. These are both part of "
|
|
"Rust's library versioning scheme. The alphanumerics are a hash representing "
|
|
"the crate metadata."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2457
|
|
msgid "## The standard library"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2462
|
|
msgid ""
|
|
"The Rust standard library provides runtime features required by the "
|
|
"language, including the task scheduler and memory allocators, as well as "
|
|
"library support for Rust built-in types, platform abstractions, and other "
|
|
"commonly used features."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2473
|
|
msgid ""
|
|
"[`std`] includes modules corresponding to each of the integer types, each of "
|
|
"the floating point types, the [`bool`] type, [tuples], [characters], "
|
|
"[strings], [vectors], [managed boxes], [owned boxes], and unsafe and "
|
|
"borrowed [pointers]. Additionally, `std` provides some pervasive types "
|
|
"([`option`] and [`result`]), [task] creation and [communication] primitives, "
|
|
"platform abstractions ([`os`] and [`path`]), basic I/O abstractions "
|
|
"([`io`]), [containers] like [`hashmap`], common traits ([`kinds`], [`ops`], "
|
|
"[`cmp`], [`num`], [`to_str`], [`clone`]), and complete bindings to the C "
|
|
"standard library ([`libc`])."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2475
|
|
msgid "### Standard Library injection and the Rust prelude"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2478
|
|
msgid ""
|
|
"`std` is imported at the topmost level of every crate by default, as if the "
|
|
"first line of each crate was"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2480
|
|
#, no-wrap
|
|
msgid " extern mod std;\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2484
|
|
msgid ""
|
|
"This means that the contents of std can be accessed from from any context "
|
|
"with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, "
|
|
"etc."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2489
|
|
msgid ""
|
|
"Additionally, `std` contains a `prelude` module that reexports many of the "
|
|
"most common standard modules, types and traits. The contents of the prelude "
|
|
"are imported into every *module* by default. Implicitly, all modules behave "
|
|
"as if they contained the following prologue:"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2491
|
|
#, no-wrap
|
|
msgid " use std::prelude::*;\n"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2517
|
|
msgid ""
|
|
"[`std`]: std/index.html [`bool`]: std/bool.html [tuples]: std/tuple.html "
|
|
"[characters]: std/char.html [strings]: std/str.html [vectors]: std/vec.html "
|
|
"[managed boxes]: std/managed.html [owned boxes]: std/owned.html [pointers]: "
|
|
"std/ptr.html [`option`]: std/option.html [`result`]: std/result.html [task]: "
|
|
"std/task.html [communication]: std/comm.html [`os`]: std/os.html [`path`]: "
|
|
"std/path.html [`io`]: std/io.html [containers]: std/container.html "
|
|
"[`hashmap`]: std/hashmap.html [`kinds`]: std/kinds.html [`ops`]: std/ops."
|
|
"html [`cmp`]: std/cmp.html [`num`]: std/num.html [`to_str`]: std/to_str.html "
|
|
"[`clone`]: std/clone.html [`libc`]: std/libc.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2519
|
|
msgid "# What next?"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2522
|
|
msgid ""
|
|
"Now that you know the essentials, check out any of the additional tutorials "
|
|
"on individual topics."
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:2528
|
|
msgid "[Borrowed pointers][borrow]"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:2528
|
|
msgid "[Tasks and communication][tasks]"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:2528
|
|
msgid "[Macros][macros]"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:2528
|
|
msgid "[The foreign function interface][ffi]"
|
|
msgstr ""
|
|
|
|
#. type: Bullet: '* '
|
|
#: doc/tutorial.md:2528
|
|
msgid "[Containers and iterators](tutorial-container.html)"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2530
|
|
msgid "There is further documentation on the [wiki]."
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2535
|
|
msgid ""
|
|
"[borrow]: tutorial-borrowed-ptr.html [tasks]: tutorial-tasks.html [macros]: "
|
|
"tutorial-macros.html [ffi]: tutorial-ffi.html"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2541
|
|
msgid ""
|
|
"[wiki]: https://github.com/mozilla/rust/wiki/Docs [unit testing]: https://"
|
|
"github.com/mozilla/rust/wiki/Doc-unit-testing [rustdoc]: https://github.com/"
|
|
"mozilla/rust/wiki/Doc-using-rustdoc [cargo]: https://github.com/mozilla/rust/"
|
|
"wiki/Doc-using-cargo-to-manage-packages [attributes]: https://github.com/"
|
|
"mozilla/rust/wiki/Doc-attributes"
|
|
msgstr ""
|
|
|
|
#. type: Plain text
|
|
#: doc/tutorial.md:2542
|
|
msgid ""
|
|
"[pound-rust]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust"
|
|
msgstr ""
|