mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
4353 lines
119 KiB
Plaintext
4353 lines
119 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\n"
|
||
"POT-Creation-Date: 2013-08-12 02:06+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=UTF-8\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:1277 doc/tutorial.md:2176
|
||
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:1286 doc/tutorial.md:2185
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# trait Shape { fn area(&self) -> f64; }\n"
|
||
"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
|
||
"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
|
||
" // `c` is both a Circle and a Shape\n"
|
||
" c.radius() * c.area()\n"
|
||
"}\n"
|
||
"~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/rust.md:1288 doc/tutorial.md:2187
|
||
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]: "
|
||
"https://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.8.tar.gz $ "
|
||
"tar -xzf rust-0.8.tar.gz $ cd rust-0.8 $ ./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; "
|
||
"and `rustpkg`, the Rust package manager."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:123
|
||
msgid ""
|
||
"[tarball]: http://static.rust-lang.org/dist/rust-0.8.tar.gz [win-exe]: "
|
||
"http://static.rust-lang.org/dist/rust-0.8-install.exe"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:125
|
||
msgid "## Compiling your first program"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:128
|
||
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:134
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"fn main() {\n"
|
||
" println(\"hello?\");\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:138
|
||
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:143
|
||
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:149
|
||
#, 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:156
|
||
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:158
|
||
msgid "## Using the rust tool"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:163
|
||
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:169
|
||
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:172
|
||
msgid ""
|
||
"To get a list of all available commands, simply call `rust` without any "
|
||
"argument."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:174
|
||
msgid "## Editing Rust code"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:184
|
||
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:188
|
||
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:191
|
||
msgid ""
|
||
"[sublime]: http://github.com/dbp/sublime-rust [sublime-pkg]: http://wbond."
|
||
"net/sublime_packages/package_control"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:193
|
||
msgid "# Syntax basics"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:201
|
||
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:206
|
||
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:219
|
||
#, 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:223
|
||
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:227
|
||
msgid "~~~~ let hi = \"hi\"; let mut count = 0;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:233
|
||
#, no-wrap
|
||
msgid ""
|
||
"while count < 10 {\n"
|
||
" println(fmt!(\"count: %?\", count));\n"
|
||
" count += 1;\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:237
|
||
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:243
|
||
msgid ""
|
||
"~~~~ static MONSTER_FACTOR: f64 = 57.8; let monster_size = MONSTER_FACTOR "
|
||
"* 10.0; let monster_size: int = 50; ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:252
|
||
msgid ""
|
||
"Local variables may shadow earlier declarations, as in the previous example: "
|
||
"`monster_size` was first declared as a `f64`, 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:258
|
||
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:263
|
||
#, 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:265
|
||
msgid "## Expressions and semicolons"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:271
|
||
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:283
|
||
#, 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:285
|
||
msgid "But, in Rust, you don't have to repeat the name `price`:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:297
|
||
#, 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:303
|
||
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:309
|
||
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:314
|
||
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 static items) is an expression, "
|
||
"including function bodies."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:322
|
||
#, 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:324
|
||
msgid "## Primitive types and literals"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:331
|
||
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`), octal (`0o70`), 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:337
|
||
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:344
|
||
#, 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:349
|
||
msgid ""
|
||
"There are two floating-point types: `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 "
|
||
"`f32` and `f64` can be used to create literals of a specific type."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:351
|
||
msgid "The keywords `true` and `false` produce literals of type `bool`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:358
|
||
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:360
|
||
msgid "The nil type, written `()`, has a single value, also written `()`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:362
|
||
msgid "## Operators"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:367
|
||
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:370
|
||
msgid ""
|
||
"Note that, if applied to an integer value, `!` flips all the bits (like `~` "
|
||
"in C)."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:374
|
||
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:379
|
||
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:385
|
||
msgid ""
|
||
"~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:387
|
||
msgid "## Syntax extensions"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:394
|
||
#, 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:398
|
||
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:401
|
||
msgid "~~~~ # let mystery_object = ();"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:403
|
||
msgid "println(fmt!(\"%s is %d\", \"the answer\", 43));"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:407
|
||
msgid ""
|
||
"// %? will conveniently print any type println(fmt!(\"what is this thing: %?"
|
||
"\", mystery_object)); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:409
|
||
msgid "[pf]: http://en.cppreference.com/w/cpp/io/c/fprintf"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:411
|
||
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:413
|
||
msgid "# Control structures"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:415
|
||
msgid "## Conditionals"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:419
|
||
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:429
|
||
#, 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:434
|
||
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:442
|
||
#, 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:444
|
||
msgid "## Pattern matching"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:450
|
||
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:460
|
||
#, 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:464
|
||
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:474
|
||
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:479
|
||
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:487
|
||
#, 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:492
|
||
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:496
|
||
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:500
|
||
msgid ""
|
||
"> ***Note:*** The following code makes use of tuples (`(f64, f64)`) "
|
||
"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:513
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"use std::f64;\n"
|
||
"use std::num::atan;\n"
|
||
"fn angle(vector: (f64, f64)) -> f64 {\n"
|
||
" let pi = f64::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:519
|
||
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:526
|
||
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:531
|
||
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:536
|
||
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:540
|
||
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:542
|
||
msgid "## Loops"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:547
|
||
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:554
|
||
#, 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:556
|
||
msgid ""
|
||
"`loop` denotes an infinite loop, and is the preferred way of writing `while "
|
||
"true`:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:566
|
||
#, 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:569
|
||
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:571
|
||
msgid "# Data structures"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:573
|
||
msgid "## Structs"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:578
|
||
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:582
|
||
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:589
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"struct Point {\n"
|
||
" x: f64,\n"
|
||
" y: f64\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:593
|
||
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:597
|
||
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:602
|
||
msgid ""
|
||
"~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } 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:606
|
||
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:609
|
||
msgid ""
|
||
"`match` patterns destructure structs. The basic syntax is `Name { fieldname: "
|
||
"pattern, ... }`:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:618
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\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:625
|
||
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:633
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\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:635
|
||
msgid "## Enums"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:638
|
||
msgid ""
|
||
"Enums are datatypes that have several alternate representations. For "
|
||
"example, consider the type shown earlier:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:646
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"enum Shape {\n"
|
||
" Circle(Point, f64),\n"
|
||
" Rectangle(Point, Point)\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:652
|
||
msgid ""
|
||
"A value of this type is either a `Circle`, in which case it contains a "
|
||
"`Point` struct and a `f64`, 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:658
|
||
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:661
|
||
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:670
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"enum Direction {\n"
|
||
" North,\n"
|
||
" East,\n"
|
||
" South,\n"
|
||
" West\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:673
|
||
msgid ""
|
||
"This declaration defines `North`, `East`, `South`, and `West` as constants, "
|
||
"all of which have type `Direction`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:677
|
||
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:685
|
||
#, 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:690
|
||
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:693
|
||
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:697
|
||
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:709
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"use std::f64;\n"
|
||
"# struct Point {x: f64, y: f64}\n"
|
||
"# enum Shape { Circle(Point, f64), Rectangle(Point, Point) }\n"
|
||
"fn area(sh: Shape) -> f64 {\n"
|
||
" match sh {\n"
|
||
" Circle(_, size) => f64::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:714
|
||
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:727
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\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:729
|
||
msgid "Enum variants may also be structs. For example:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:747
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"use std::f64;\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"# fn square(x: f64) -> f64 { x * x }\n"
|
||
"enum Shape {\n"
|
||
" Circle { center: Point, radius: f64 },\n"
|
||
" Rectangle { top_left: Point, bottom_right: Point }\n"
|
||
"}\n"
|
||
"fn area(sh: Shape) -> f64 {\n"
|
||
" match sh {\n"
|
||
" Circle { radius: radius, _ } => f64::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:749
|
||
msgid "## Tuples"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:754
|
||
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:761
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"let mytup: (int, int, f64) = (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:763
|
||
msgid "## Tuple structs"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:768
|
||
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:777
|
||
#, no-wrap
|
||
msgid ""
|
||
"For example:\n"
|
||
"~~~~\n"
|
||
"struct MyTup(int, int, f64);\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:779
|
||
msgid "<a name=\"newtype\"></a>"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:784
|
||
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:788
|
||
msgid "~~~~ struct GizmoId(int); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:791
|
||
msgid ""
|
||
"For convenience, you can extract the contents of such a struct with the "
|
||
"dereference (`*`) unary operator:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:797
|
||
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:800
|
||
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:805
|
||
msgid "~~~~ struct Inches(int); struct Centimeters(int); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:808
|
||
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:810
|
||
msgid "# Functions"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:818
|
||
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:824
|
||
#, 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:829
|
||
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:835
|
||
#, 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:842
|
||
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:845
|
||
msgid "~~~~ fn do_nothing_the_hard_way() -> () { return (); }"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:848
|
||
msgid "fn do_nothing_the_easy_way() { } ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:850
|
||
msgid ""
|
||
"Ending the function with a semicolon like so is equivalent to returning `()`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:854
|
||
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:858
|
||
msgid "assert!(8 == line(5, 3, 1)); assert!(() == oops(5, 3, 1)); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:862
|
||
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:866
|
||
msgid "~~~ fn first((value, _): (int, f64)) -> int { value } ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:868 doc/tutorial-ffi.md:143
|
||
msgid "# Destructors"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:872
|
||
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:876
|
||
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:878
|
||
msgid ""
|
||
"The `~` sigil represents a unique handle for a memory allocation on the heap:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:886
|
||
#, 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:890
|
||
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:892
|
||
msgid "# Ownership"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:897
|
||
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:903
|
||
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:907
|
||
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:914
|
||
#, 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:919
|
||
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:925
|
||
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:927
|
||
msgid "# Boxes"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:934
|
||
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:939
|
||
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:941
|
||
msgid "## Owned boxes"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:944
|
||
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:949
|
||
msgid "~~~~ let x = 5; // immutable let mut y = 5; // mutable y += 2;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:954
|
||
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:959
|
||
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:962
|
||
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:968
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~ {.xfail-test}\n"
|
||
"struct Foo {\n"
|
||
" child: Option<Foo>\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:972
|
||
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:976
|
||
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:982
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"struct Foo {\n"
|
||
" child: Option<~Foo>\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:984
|
||
msgid "## Managed boxes"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:992
|
||
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 managed 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:995
|
||
msgid "~~~~ let a = @5; // immutable"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:998
|
||
msgid "let mut b = @5; // mutable variable, immutable box b = @10;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1001
|
||
msgid "let c = @mut 5; // immutable variable, mutable box *c = 10;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1006
|
||
msgid ""
|
||
"let mut d = @mut 5; // mutable variable, mutable box *d += 5; d = @mut 15; "
|
||
"~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1011
|
||
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:1015
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"let a = @1; // immutable box\n"
|
||
"let b = @mut 2; // mutable box\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1018
|
||
#, 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:1022
|
||
#, 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:1027
|
||
#, 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:1029
|
||
msgid "# Move semantics"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1035
|
||
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:1041
|
||
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:1044
|
||
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:1051
|
||
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:1053
|
||
msgid "# Borrowed pointers"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1059
|
||
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:1061
|
||
msgid "As an example, consider a simple struct type, `Point`:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1068
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"struct Point {\n"
|
||
" x: f64,\n"
|
||
" y: f64\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1072
|
||
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:1079
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\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:1089
|
||
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 point—that 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. So we’d 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:1099
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"# fn sqrt(f: f64) -> f64 { 0f }\n"
|
||
"fn compute_distance(p1: &Point, p2: &Point) -> f64 {\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:1101 doc/tutorial-borrowed-ptr.md:72
|
||
msgid "Now we can call `compute_distance()` in various ways:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1111
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# struct Point{ x: f64, y: f64 };\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) -> f64 { 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:1118
|
||
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:1124
|
||
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:1133
|
||
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:1136
|
||
msgid ""
|
||
"For a more in-depth explanation of borrowed pointers, read the [borrowed "
|
||
"pointer tutorial][borrowtut]."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1138
|
||
msgid "[borrowtut]: tutorial-borrowed-ptr.html"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1140
|
||
msgid "## Freezing"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1143
|
||
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:1152
|
||
#, 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"
|
||
"# x = 3;\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1156
|
||
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:1166
|
||
#, 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:1168
|
||
msgid "# Dereferencing pointers"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1171
|
||
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:1176
|
||
msgid "~~~ let managed = @10; let owned = ~20; let borrowed = &30;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1179
|
||
msgid "let sum = *managed + *owned + *borrowed; ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1183
|
||
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:1187
|
||
msgid "~~~ let managed = @mut 10; let mut owned = ~20;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1190
|
||
msgid "let mut value = 30; let borrowed = &mut value;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1195
|
||
#, no-wrap
|
||
msgid ""
|
||
"*managed = *owned + 10;\n"
|
||
"*owned = *borrowed + 100;\n"
|
||
"*borrowed = *managed + 1000;\n"
|
||
"~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1199
|
||
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:1209
|
||
msgid ""
|
||
"~~~ # struct Point { x: f64, y: f64 } # 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:1213
|
||
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:1223
|
||
msgid ""
|
||
"~~~ # struct Point { x: f64, y: f64 } # 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:1227
|
||
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:1233
|
||
msgid ""
|
||
"~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
|
||
"20f }; println(fmt!(\"%f\", point.x)); ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1235
|
||
msgid "The indexing operator (`[]`) also auto-dereferences."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1237
|
||
msgid "# Vectors and strings"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1242
|
||
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:1252
|
||
#, 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:1255
|
||
msgid ""
|
||
"// A borrowed pointer to stack-allocated vector let stack_crayons: &[Crayon] "
|
||
"= &[Aquamarine, Asparagus, AtomicTangerine];"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1258
|
||
msgid ""
|
||
"// A local heap (managed) vector of crayons let local_crayons: @[Crayon] = "
|
||
"@[BananaMania, Beaver, Bittersweet];"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1262
|
||
msgid ""
|
||
"// An exchange heap (owned) vector of crayons let exchange_crayons: "
|
||
"~[Crayon] = ~[Black, BlizzardBlue, Blue]; ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1264
|
||
msgid "The `+` operator means concatenation when applied to vector types."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1274
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
|
||
"# Aquamarine, Asparagus, AtomicTangerine,\n"
|
||
"# BananaMania, Beaver, Bittersweet };\n"
|
||
"# impl Clone for Crayon {\n"
|
||
"# fn clone(&self) -> Crayon {\n"
|
||
"# *self\n"
|
||
"# }\n"
|
||
"# }\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1277
|
||
msgid ""
|
||
"let my_crayons = ~[Almond, AntiqueBrass, Apricot]; let your_crayons = "
|
||
"~[BananaMania, Beaver, Bittersweet];"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1280
|
||
msgid ""
|
||
"// Add two vectors to create a new one let our_crayons = my_crayons + "
|
||
"your_crayons;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1285
|
||
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:1290
|
||
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:1292
|
||
msgid "Square brackets denote indexing into a vector:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1304
|
||
#, 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:1306
|
||
msgid "A vector can be destructured using pattern matching:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1316
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"let numbers: &[int] = &[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:1320
|
||
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:1326
|
||
#, 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:1329
|
||
msgid "crayons[0] = Apricot; // ERROR: Can't assign to immutable vector ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1331
|
||
msgid "Moving it into a mutable slot makes the elements assignable."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1337
|
||
#, 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:1340
|
||
msgid ""
|
||
"// Put the vector into a mutable slot let mut mutable_crayons = crayons;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1344
|
||
msgid "// Now it's mutable to the bone mutable_crayons[0] = Apricot; ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1347
|
||
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:1355
|
||
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:1359
|
||
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:1362
|
||
msgid ""
|
||
"// The same thing, but with the `&` let stack_crayons: &str = &\"Aquamarine, "
|
||
"Asparagus, AtomicTangerine\";"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1365
|
||
msgid ""
|
||
"// A local heap (managed) string let local_crayons: @str = @\"BananaMania, "
|
||
"Beaver, Bittersweet\";"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1369
|
||
msgid ""
|
||
"// An exchange heap (owned) string let exchange_crayons: ~str = ~\"Black, "
|
||
"BlizzardBlue, Blue\"; ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1373
|
||
msgid ""
|
||
"Both vectors and strings support a number of useful [methods](#methods), "
|
||
"defined in [`std::vec`] and [`std::str`]. Here are some examples."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1376
|
||
msgid "[`std::vec`]: std/vec.html [`std::str`]: std/str.html"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1387
|
||
#, 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:1389
|
||
msgid "let crayons = [Almond, AntiqueBrass, Apricot];"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1393
|
||
msgid ""
|
||
"// Check the length of the vector assert!(crayons.len() == 3); assert!(!"
|
||
"crayons.is_empty());"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1400
|
||
#, no-wrap
|
||
msgid ""
|
||
"// Iterate over a vector, obtaining a pointer to each element\n"
|
||
"// (`for` is explained in the container/iterator tutorial)\n"
|
||
"for crayon in crayons.iter() {\n"
|
||
" let delicious_crayon_wax = unwrap_crayon(*crayon);\n"
|
||
" eat_crayon_wax(delicious_crayon_wax);\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1404
|
||
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:1407
|
||
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:1413
|
||
#, 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:1415
|
||
msgid "# Closures"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1420
|
||
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:1423
|
||
msgid "~~~~ {.ignore} let foo = 10;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1428
|
||
#, no-wrap
|
||
msgid ""
|
||
"fn bar() -> int {\n"
|
||
" return foo; // `bar` cannot refer to `foo`\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1431
|
||
msgid ""
|
||
"Rust also supports _closures_, functions that can access variables in the "
|
||
"enclosing scope."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1434
|
||
msgid "~~~~ fn call_closure_with_ten(b: |int|) { b(10); }"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1437
|
||
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:1440
|
||
msgid "call_closure_with_ten(closure); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1446
|
||
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:1451
|
||
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:1455
|
||
msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1459
|
||
msgid ""
|
||
"There are several forms of closure, each with its own role. The most common, "
|
||
"called a _stack closure_, has type `||` and can directly access local "
|
||
"variables in the enclosing scope."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1464
|
||
msgid "~~~~ let mut max = 0; [1, 2, 3].map(|x| if *x > max { max = *x }); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1473
|
||
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:1475
|
||
msgid "## Managed closures"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1481
|
||
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:1486
|
||
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:1489
|
||
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:1495
|
||
#, 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:1501
|
||
#, 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:1503
|
||
msgid "## Owned closures"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1510
|
||
msgid ""
|
||
"Owned closures, written `proc`, 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:1512
|
||
msgid "## Closure compatibility"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1519
|
||
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 `||`. 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 `||`. That way, callers may "
|
||
"pass any kind of closure."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1527
|
||
msgid ""
|
||
"~~~~ fn call_twice(f: ||) { 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:1531
|
||
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:1533
|
||
msgid "## Do syntax"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1536
|
||
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:1539
|
||
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:1549
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"fn each(v: &[int], op: |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:1553
|
||
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:1561
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# fn each(v: &[int], op: |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:1564
|
||
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:1572
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# fn each(v: &[int], op: |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:1577
|
||
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:1582
|
||
msgid ""
|
||
"`do` is a convenient way to create tasks with the `task::spawn` function. "
|
||
"`spawn` has the signature `spawn(fn: proc())`. In other words, it is a "
|
||
"function that takes an owned closure that takes no arguments."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1585 doc/tutorial.md:1597
|
||
msgid "~~~~ use std::task::spawn;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1590
|
||
#, no-wrap
|
||
msgid ""
|
||
"do spawn() || {\n"
|
||
" debug!(\"I'm a task, whatever\");\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1594
|
||
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:1602
|
||
#, no-wrap
|
||
msgid ""
|
||
"do spawn {\n"
|
||
" debug!(\"Kablam!\");\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1605
|
||
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:1607
|
||
msgid "# Methods"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1613
|
||
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:1617
|
||
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:1625
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# fn draw_circle(p: Point, f: f64) { }\n"
|
||
"# fn draw_rectangle(p: Point, p: Point) { }\n"
|
||
"struct Point {\n"
|
||
" x: f64,\n"
|
||
" y: f64\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1630
|
||
#, no-wrap
|
||
msgid ""
|
||
"enum Shape {\n"
|
||
" Circle(Point, f64),\n"
|
||
" Rectangle(Point, Point)\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1639
|
||
#, 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:1643
|
||
msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f); s.draw(); ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1647
|
||
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:1652
|
||
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:1667
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# fn draw_circle(p: Point, f: f64) { }\n"
|
||
"# fn draw_rectangle(p: Point, p: Point) { }\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"# enum Shape {\n"
|
||
"# Circle(Point, f64),\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:1669
|
||
msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f);"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1675
|
||
msgid ""
|
||
"(@s).draw_managed(); (~s).draw_owned(); (&s).draw_borrowed(); s."
|
||
"draw_value(); ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1679
|
||
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:1697
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# fn draw_circle(p: Point, f: f64) { }\n"
|
||
"# fn draw_rectangle(p: Point, p: Point) { }\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"# enum Shape {\n"
|
||
"# Circle(Point, f64),\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:1700
|
||
msgid "(@s).draw_borrowed(); (~s).draw_borrowed();"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1704
|
||
msgid ""
|
||
"// Unlike typical function arguments, the self value will // automatically "
|
||
"be referenced ... s.draw_borrowed();"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1707
|
||
msgid "// ... and dereferenced (& &s).draw_borrowed();"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1711
|
||
msgid "// ... and dereferenced and borrowed (&@~s).draw_borrowed(); ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1715
|
||
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:1722
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~ {.xfail-test}\n"
|
||
"impl Circle {\n"
|
||
" fn area(&self) -> f64 { ... }\n"
|
||
" fn new(area: f64) -> Circle { ... }\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1724
|
||
msgid ""
|
||
"To call such a method, just prefix it with the type name and a double colon:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1733
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"use std::f64::consts::pi;\n"
|
||
"struct Circle { radius: f64 }\n"
|
||
"impl Circle {\n"
|
||
" fn new(area: f64) -> Circle { Circle { radius: (area / pi).sqrt() } }\n"
|
||
"}\n"
|
||
"let c = Circle::new(42.5);\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1735
|
||
msgid "# Generics"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1743
|
||
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:1753
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"fn map<T, U>(vector: &[T], function: |v: &T| -> U) -> ~[U] {\n"
|
||
" let mut accumulator = ~[];\n"
|
||
" for element in vector.iter() {\n"
|
||
" accumulator.push(function(element));\n"
|
||
" }\n"
|
||
" return accumulator;\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1758
|
||
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:1768
|
||
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:1770
|
||
msgid ""
|
||
"Generic `type`, `struct`, and `enum` declarations follow the same pattern:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1774
|
||
msgid "~~~~ use std::hashmap::HashMap; type Set<T> = HashMap<T, ()>;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1778
|
||
#, no-wrap
|
||
msgid ""
|
||
"struct Stack<T> {\n"
|
||
" elements: ~[T]\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1784
|
||
#, no-wrap
|
||
msgid ""
|
||
"enum Option<T> {\n"
|
||
" Some(T),\n"
|
||
" None\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1787
|
||
msgid ""
|
||
"These declarations can be instantiated to valid types like `Set<int>`, "
|
||
"`Stack<int>`, and `Option<int>`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1793
|
||
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:1804
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"# enum Shape { Circle(Point, f64), Rectangle(Point, Point) }\n"
|
||
"fn radius(shape: Shape) -> Option<f64> {\n"
|
||
" match shape {\n"
|
||
" Circle(_, radius) => Some(radius),\n"
|
||
" Rectangle(*) => None\n"
|
||
" }\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1812
|
||
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:1814
|
||
msgid "## Traits"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1824
|
||
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:1832
|
||
msgid ""
|
||
"As motivation, let us consider copying in Rust. The `clone` method 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 destructors cannot be copied unless you "
|
||
"explicitly implement `Clone` for them."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1837
|
||
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:1844
|
||
#, 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:1851
|
||
msgid ""
|
||
"However, we can tell the compiler that the `head` function is only for "
|
||
"copyable types: that is, those that implement the `Clone` trait. In that "
|
||
"case, we can explicitly create a second copy of the value we are returning "
|
||
"using the `clone` keyword:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1858
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"// This does\n"
|
||
"fn head<T: Clone>(v: &[T]) -> T {\n"
|
||
" v[0].clone()\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1866
|
||
msgid ""
|
||
"This says that we can call `head` on any type `T` as long as that type "
|
||
"implements the `Clone` 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 that does not implement `Clone`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1871
|
||
msgid ""
|
||
"While most traits can be defined and implemented by user code, two traits "
|
||
"are automatically derived and implemented for all applicable types by the "
|
||
"compiler, and may not be overridden:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1875
|
||
#, no-wrap
|
||
msgid ""
|
||
"* `Send` - Sendable types.\n"
|
||
"Types are sendable\n"
|
||
"unless they contain managed boxes, managed closures, or borrowed pointers.\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1880
|
||
#, no-wrap
|
||
msgid ""
|
||
"* `Freeze` - Constant (immutable) types.\n"
|
||
"These are types that do not contain anything intrinsically mutable.\n"
|
||
"Intrinsically mutable values include `@mut`\n"
|
||
"and `Cell` in the standard library.\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1883
|
||
msgid ""
|
||
"> ***Note:*** These two traits were referred to as 'kinds' in earlier > "
|
||
"iterations of the language, and often still are."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1889
|
||
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:1894
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"struct TimeBomb {\n"
|
||
" explosivity: uint\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1903
|
||
#, no-wrap
|
||
msgid ""
|
||
"impl Drop for TimeBomb {\n"
|
||
" fn drop(&self) {\n"
|
||
" for _ in range(0, self.explosivity) {\n"
|
||
" println(\"blam!\");\n"
|
||
" }\n"
|
||
" }\n"
|
||
"}\n"
|
||
"~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1906
|
||
msgid ""
|
||
"It is illegal to call `drop` directly. Only code inserted by the compiler "
|
||
"may call it."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1908
|
||
msgid "## Declaring and implementing traits"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1914
|
||
msgid ""
|
||
"A trait consists of a set of methods without bodies, or may be empty, as is "
|
||
"the case with `Send` and `Freeze`. 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:1920
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"trait Printable {\n"
|
||
" fn print(&self);\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1925
|
||
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:1927
|
||
msgid "[impls]: #methods"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1933
|
||
#, 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:1937
|
||
#, no-wrap
|
||
msgid ""
|
||
"impl Printable for ~str {\n"
|
||
" fn print(&self) { println(*self) }\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1941
|
||
msgid "# 1.print(); # (~\"foo\").print(); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1946
|
||
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:1951
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"trait Seq<T> {\n"
|
||
" fn length(&self) -> uint;\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:1956
|
||
#, 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:1963
|
||
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:1968
|
||
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:1973
|
||
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:1980
|
||
#, 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:1986
|
||
#, 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:1991
|
||
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:1996
|
||
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:2002
|
||
msgid ""
|
||
"~~~~ use std::f64::consts::pi; trait Shape { fn new(area: f64) -> "
|
||
"Self; } struct Circle { radius: f64 } struct Square { length: f64 }"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2009
|
||
#, no-wrap
|
||
msgid ""
|
||
"impl Shape for Circle {\n"
|
||
" fn new(area: f64) -> Circle { Circle { radius: (area / pi).sqrt() } }\n"
|
||
"}\n"
|
||
"impl Shape for Square {\n"
|
||
" fn new(area: f64) -> Square { Square { length: (area).sqrt() } }\n"
|
||
"}\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2014
|
||
msgid ""
|
||
"let area = 42.5; let c: Circle = Shape::new(area); let s: Square = Shape::"
|
||
"new(area); ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2016
|
||
msgid "## Bounded type parameters and static method dispatch"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2021
|
||
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:2030
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# trait Printable { fn print(&self); }\n"
|
||
"fn print_all<T: Printable>(printable_things: ~[T]) {\n"
|
||
" for thing in printable_things.iter() {\n"
|
||
" thing.print();\n"
|
||
" }\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2036
|
||
msgid ""
|
||
"Declaring `T` as conforming to the `Printable` trait (as we earlier did with "
|
||
"`Clone`) 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:2039
|
||
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:2051
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~\n"
|
||
"# trait Printable { fn print(&self); }\n"
|
||
"fn print_all<T: Printable + Clone>(printable_things: ~[T]) {\n"
|
||
" let mut i = 0;\n"
|
||
" while i < printable_things.len() {\n"
|
||
" let copy_of_thing = printable_things[i].clone();\n"
|
||
" copy_of_thing.print();\n"
|
||
" i += 1;\n"
|
||
" }\n"
|
||
"}\n"
|
||
"~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2055
|
||
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:2057
|
||
msgid "This usage of traits is similar to Haskell type classes."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2059
|
||
msgid "## Trait objects and dynamic method dispatch"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2063
|
||
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:2069
|
||
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:2076
|
||
#, no-wrap
|
||
msgid ""
|
||
"fn draw_all<T: Drawable>(shapes: ~[T]) {\n"
|
||
" for shape in shapes.iter() { shape.draw(); }\n"
|
||
"}\n"
|
||
"# let c: Circle = new_circle();\n"
|
||
"# draw_all(~[c]);\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2082
|
||
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:2089
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"# trait Drawable { fn draw(&self); }\n"
|
||
"fn draw_all(shapes: &[@Drawable]) {\n"
|
||
" for shape in shapes.iter() { shape.draw(); }\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2094
|
||
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:2101
|
||
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:2104
|
||
msgid ""
|
||
"impl Drawable for Circle { fn draw(&self) { ... } } impl Drawable for "
|
||
"Rectangle { fn draw(&self) { ... } }"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2109
|
||
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:2117
|
||
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:2131
|
||
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:2136
|
||
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:2138
|
||
msgid "This usage of traits is similar to Java interfaces."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2140
|
||
msgid "## Trait inheritance"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2145
|
||
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:2150
|
||
msgid ""
|
||
"~~~~ trait Shape { fn area(&self) -> f64; } trait Circle : Shape { fn "
|
||
"radius(&self) -> f64; } ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2152
|
||
msgid ""
|
||
"Now, we can implement `Circle` on a type only if we also implement `Shape`."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2167
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~\n"
|
||
"use std::f64::consts::pi;\n"
|
||
"# trait Shape { fn area(&self) -> f64; }\n"
|
||
"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
|
||
"# struct Point { x: f64, y: f64 }\n"
|
||
"# fn square(x: f64) -> f64 { x * x }\n"
|
||
"struct CircleStruct { center: Point, radius: f64 }\n"
|
||
"impl Circle for CircleStruct {\n"
|
||
" fn radius(&self) -> f64 { (self.area() / pi).sqrt() }\n"
|
||
"}\n"
|
||
"impl Shape for CircleStruct {\n"
|
||
" fn area(&self) -> f64 { pi * square(self.radius) }\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2172
|
||
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:2196
|
||
msgid ""
|
||
"~~~ {.xfail-test} use std::f64::consts::pi; # trait Shape { fn area(&self) "
|
||
"-> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } # struct "
|
||
"Point { x: f64, y: f64 } # struct CircleStruct { center: Point, radius: "
|
||
"f64 } # impl Circle for CircleStruct { fn radius(&self) -> f64 { (self."
|
||
"area() / pi).sqrt() } } # impl Shape for CircleStruct { fn area(&self) -> "
|
||
"f64 { pi * square(self.radius) } }"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2201
|
||
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:2203
|
||
msgid "> ***Note:*** Trait inheritance does not actually work with objects yet"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2205
|
||
msgid "## Deriving implementations for traits"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2212
|
||
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:2216
|
||
msgid "~~~ #[deriving(Eq)] struct Circle { radius: f64 }"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2220
|
||
msgid "#[deriving(Rand, ToStr)] enum ABC { A, B, C } ~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2224
|
||
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:2226
|
||
msgid "# Modules and crates"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2230
|
||
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:2236
|
||
#, 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:2241
|
||
#, no-wrap
|
||
msgid ""
|
||
"fn main() {\n"
|
||
" println(farm::chicken());\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2246
|
||
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:2252
|
||
msgid ""
|
||
"~~~ # mod farm { pub fn chicken() { } } # fn main() { // Bring `chicken` "
|
||
"into scope use farm::chicken;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2262
|
||
#, 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:2269
|
||
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:2276
|
||
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:2289
|
||
#, 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:2295
|
||
#, no-wrap
|
||
msgid ""
|
||
" impl Farm {\n"
|
||
" fn feed_chickens(&self) { ... }\n"
|
||
" fn feed_cows(&self) { ... }\n"
|
||
" pub fn add_chicken(&self, c: Chicken) { ... }\n"
|
||
" }\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2301
|
||
#, 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:2311
|
||
#, 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:2313
|
||
msgid "## Crates"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2317
|
||
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:2322
|
||
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:2327
|
||
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:2336
|
||
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:2340
|
||
msgid ""
|
||
"~~~~ { .xfail-test } // Crate linkage metadata #[link(name = \"farm\", vers "
|
||
"= \"2.5\", author = \"mjh\")];"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2343
|
||
msgid "// Make a library (\"bin\" is the default) #[crate_type = \"lib\"];"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2346
|
||
msgid "// Turn on a warning #[warn(non_camel_case_types)]"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2349
|
||
msgid "// Link to the standard library extern mod std;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2354
|
||
msgid "// Load some modules from other files mod cow; mod chicken; mod horse;"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2359
|
||
#, no-wrap
|
||
msgid ""
|
||
"fn main() {\n"
|
||
" ...\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2366
|
||
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:2370
|
||
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:2373
|
||
msgid ""
|
||
"To have a nested directory structure for your source files, you can nest "
|
||
"mods:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2380
|
||
#, no-wrap
|
||
msgid ""
|
||
"~~~~ {.ignore}\n"
|
||
"mod poultry {\n"
|
||
" mod chicken;\n"
|
||
" mod turkey;\n"
|
||
"}\n"
|
||
"~~~~\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2385
|
||
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:2387
|
||
msgid "## Using other crates"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2395
|
||
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:2397
|
||
msgid "For example, `extern mod std` links the [standard library]."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2399
|
||
msgid "[standard library]: std/index.html"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2406
|
||
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:2408
|
||
msgid "Our example crate declared this set of `link` attributes:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2412
|
||
msgid "~~~~ #[link(name = \"farm\", vers = \"2.5\", author = \"mjh\")]; ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2414
|
||
msgid "Which you can then link with any (or all) of the following:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2420
|
||
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:2423
|
||
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:2425
|
||
msgid "## A minimal example"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2428
|
||
msgid ""
|
||
"Now for something that you can actually compile yourself, we have these two "
|
||
"files:"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2434
|
||
msgid ""
|
||
"~~~~ // world.rs #[link(name = \"world\", vers = \"1.0\")]; pub fn explore() "
|
||
"-> &str { \"world\" } ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2440
|
||
msgid ""
|
||
"~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello "
|
||
"\" + world::explore()); } ~~~~"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2442
|
||
msgid "Now compile and run like this (adjust to your platform if necessary):"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2449
|
||
#, 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:2454
|
||
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:2456
|
||
msgid "## The standard library"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2461
|
||
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:2472
|
||
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:2474
|
||
msgid "### Standard Library injection and the Rust prelude"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2477
|
||
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:2479
|
||
#, no-wrap
|
||
msgid " extern mod std;\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2483
|
||
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:2488
|
||
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:2490
|
||
#, no-wrap
|
||
msgid " use std::prelude::*;\n"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2516
|
||
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:2518
|
||
msgid "# What next?"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2521
|
||
msgid ""
|
||
"Now that you know the essentials, check out any of the additional tutorials "
|
||
"on individual topics."
|
||
msgstr ""
|
||
|
||
#. type: Bullet: '* '
|
||
#: doc/tutorial.md:2527
|
||
msgid "[Borrowed pointers][borrow]"
|
||
msgstr ""
|
||
|
||
#. type: Bullet: '* '
|
||
#: doc/tutorial.md:2527
|
||
msgid "[Tasks and communication][tasks]"
|
||
msgstr ""
|
||
|
||
#. type: Bullet: '* '
|
||
#: doc/tutorial.md:2527
|
||
msgid "[Macros][macros]"
|
||
msgstr ""
|
||
|
||
#. type: Bullet: '* '
|
||
#: doc/tutorial.md:2527
|
||
msgid "[The foreign function interface][ffi]"
|
||
msgstr ""
|
||
|
||
#. type: Bullet: '* '
|
||
#: doc/tutorial.md:2527
|
||
msgid "[Containers and iterators](tutorial-container.html)"
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2529
|
||
msgid "There is further documentation on the [wiki]."
|
||
msgstr ""
|
||
|
||
#. type: Plain text
|
||
#: doc/tutorial.md:2534
|
||
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:2536
|
||
msgid "[wiki]: https://github.com/mozilla/rust/wiki/Docs"
|
||
msgstr ""
|