diff --git a/src/doc/guide.md b/src/doc/guide.md index c855b6831d8..2974ef018c6 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -535,7 +535,7 @@ arguments we pass to functions and macros, if you're passing more than one. When you just use the curly braces, Rust will attempt to display the value in a meaningful way by checking out its type. If you want to specify the format in a more detailed manner, there are a [wide number of options -available](/std/fmt/index.html). For now, we'll just stick to the default: +available](std/fmt/index.html). For now, we'll just stick to the default: integers aren't very complicated to print. So, we've cleared up all of the confusion around bindings, with one exception: @@ -3520,15 +3520,15 @@ out. In systems programming, pointers are an incredibly important topic. Rust has a very rich set of pointers, and they operate differently than in many other languages. They are important enough that we have a specific [Pointer -Guide](/guide-pointers.html) that goes into pointers in much detail. In fact, +Guide](guide-pointers.html) that goes into pointers in much detail. In fact, while you're currently reading this guide, which covers the language in broad overview, there are a number of other guides that put a specific topic under a microscope. You can find the list of guides on the [documentation index -page](/index.html#guides). +page](index.html#guides). In this section, we'll assume that you're familiar with pointers as a general concept. If you aren't, please read the [introduction to -pointers](/guide-pointers.html#an-introduction) section of the Pointer Guide, +pointers](guide-pointers.html#an-introduction) section of the Pointer Guide, and then come back here. We'll wait. Got the gist? Great. Let's talk about pointers in Rust. @@ -4711,75 +4711,177 @@ fail. # Macros -One of Rust's most advanced features is is system of **macro**s. While +One of Rust's most advanced features is its system of **macro**s. While functions allow you to provide abstractions over values and operations, macros allow you to provide abstractions over syntax. Do you wish Rust had the ability to do something that it can't currently do? You may be able to write a macro to extend Rust's capabilities. -You've already used one macro extensively: `println!`. When we invoke +You've already used one macro extensively: `println!`. When we invoke a Rust macro, we need to use the exclamation mark (`!`). There's two reasons that this is true: the first is that it makes it clear when you're using a macro. The second is that macros allow for flexible syntax, and so Rust must be able to tell where a macro starts and ends. The `!(...)` helps with this. -An example of even more advanced macro usage is in Rust's `regex` crate. This -implements **regular expressions* for Rust. Regular expressions provide a -powerful way to determine if a string matches a certain pattern, but they also -have their own syntax. Therefore, they're a perfect fit for Rust's macros. - -Here's an example of using a regular expression in Rust: +Let's talk some more about `println!`. We could have implemented `println!` as +a function, but it would be worse. Why? Well, what macros allow you to do +is write code that generates more code. So when we call `println!` like this: ```{rust} -#![feature(phase)] -#[phase(plugin)] -extern crate regex_macros; -extern crate regex; +let x = 5i; +println!("x is: {}", x); +``` +The `println!` macro does a few things: + +1. It parses the string to find any `{}`s +2. It checks that the number of `{}`s matches the number of other arguments. +3. It generates a bunch of Rust code, taking this in mind. + +What this means is that you get type checking at compile time, because +Rust will generate code that takes all of the types into account. If +`println!` was a function, it could still do this type checking, but it +would happen at run time rather than compile time. + +We can check this out using a special flag to `rustc`. This code, in a file +`print.rs`: + +```{rust} fn main() { - let re = regex!(r"^\d{4}-\d{2}-\d{2}$"); - println!("Does our expression match? {}", re.is_match("2014-01-01")); + let x = "Hello"; + println!("x is: {:s}", x); } ``` -This will print "Does our expression match? true". Now, we won't learn -everything there is to know about regular expressions in this tutorial. We can -consult [the regex crate's documentation](/regex/index.html) for more on that -later. For now, here's the important parts: +Can have its macros expanded like this: `rustc print.rs --pretty=expanded`, will +give us this huge result: -```{rust} +```{rust,ignore} #![feature(phase)] -#[phase(plugin)] -extern crate regex_macros; -# fn main() {} +#![no_std] +#![feature(globs)] +#[phase(plugin, link)] +extern crate std = "std"; +extern crate rt = "native"; +use std::prelude::*; +fn main() { + let x = "Hello"; + match (&x,) { + (__arg0,) => { + #[inline] + #[allow(dead_code)] + static __STATIC_FMTSTR: [::std::fmt::rt::Piece<'static>, ..2u] = + [::std::fmt::rt::String("x is: "), + ::std::fmt::rt::Argument(::std::fmt::rt::Argument{position: + ::std::fmt::rt::ArgumentNext, + format: + ::std::fmt::rt::FormatSpec{fill: + ' ', + align: + ::std::fmt::rt::AlignUnknown, + flags: + 0u, + precision: + ::std::fmt::rt::CountImplied, + width: + ::std::fmt::rt::CountImplied,},})]; + let __args_vec = + &[::std::fmt::argument(::std::fmt::secret_string, __arg0)]; + let __args = + unsafe { + ::std::fmt::Arguments::new(__STATIC_FMTSTR, __args_vec) + }; + ::std::io::stdio::println_args(&__args) + } + }; +} ``` -These attributes allow the `regex_macros` crate to actually hook in to the -compiler itself and extend it with the regular expression syntax. Macros -are serious business! +Intense. Here's a trimmed down version that's a bit easier to read: -Next, let's look at the actual invocation: +```{rust,ignore} +fn main() { + let x = 5i; + match (&x,) { + (__arg0,) => { + static __STATIC_FMTSTR: = + [String("x is: "), + Argument(Argument { + position: ArgumentNext, + format: FormatSpec { + fill: ' ', + align: AlignUnknown, + flags: 0u, + precision: CountImplied, + width: CountImplied, + }, + }, + ]; + let __args_vec = &[argument(secret_string, __arg0)]; + let __args = unsafe { Arguments::new(__STATIC_FMTSTR, __args_vec) }; -```{rust} -# #![feature(phase)] -# #[phase(plugin)] -# extern crate regex_macros; -# extern crate regex; -# fn main() { -let re = regex!(r"^\d{4}-\d{2}-\d{2}$"); -# } + println_args(&__args) + } + }; +} ``` -The `regex!` macro allows us to define a macro. inside of the `()`s, we have a -`r""` construct. This is a 'raw' string literal, that does no escaping of its -contents. This is a Rust feature, not a macros feature. Finally, the rest of -the insides, which is the regular expression itself. This regular expression -roughly translates to "four digits, followed by a hypen, followed by two -digits, followed by a hypen, followed by two digits." +Whew! This isn't too terrible. You can see that we still `let x = 5i`, +but then things get a little bit hairy. Three more bindings get set: a +static format string, an argument vector, and the aruments. We then +invoke the `println_args` function with the generated arguments. -For more on macros, please consult [the Macros Guide](/guide-macros.html). -Macros are a very advanced and still slightly experimental feature, and don't -require a deep understanding to use. The Guide can help you if you want to -write your own. +This is the code (well, the full version) that Rust actually compiles. You can +see all of the extra information that's here. We get all of the type safety and +options that it provides, but at compile time, and without needing to type all +of this out. This is how macros are powerful. Without them, you would need to +type all of this by hand to get a type checked `println`. + +For more on macros, please consult [the Macros Guide](guide-macros.html). +Macros are a very advanced and still slightly experimental feature, but don't +require a deep understanding to call, since they look just like functions. The +Guide can help you if you want to write your own. # Unsafe + +Finally, there's one more concept that you should be aware in Rust: `unsafe`. +There are two circumstances where Rust's safety provisions don't work well. +The first is when interfacing with C code, and the second is when building +certain kinds of abstractions. + +Rust has support for FFI, (which you can read about in the [FFI +Guide](guide-ffi.html)) but Rust can't guarantee that the C code will be safe, +like Rust's will. Therefore, Rust marks such functions with the `unsafe` +keyword, which indicates that the function may not behave properly. + +Second, if you'd like to create some sort of shared-memory data structure, Rust +won't allow it, because memory must be owned by a single owner. However, if +you're planning on making access to that shared memory safe, such as with a +mutex, _you_ know that it's safe, but Rust can't know. Writing an `unsafe` +block allows you to ask the compiler to trust you. In this case, the _internal_ +implementation of the mutex is considered unsafe, but the _external_ interface +we present is safe. This allows it to be effectively used in normal Rust, while +being able to implement functionality that the compiler can't double check for +us. + +Doesn't an escape hatch undermine the safety of the entire system? Well, if +Rust code segfaults, it _must_ be because of unsafe code somewhere. By +annotating exactly where that is, you have a significantly smaller area to +search. + +We haven't even talked about any examples here, and that's because I want to +emphasize that you should not be writing unsafe code unless you know exactly +what you're doing. The vast majority of Rust developers will only interact with +it when doing FFI, and advanced library authors may use it to build certain +kinds of abstraction. + +# Conclusion + +We covered a lot of ground here. When you've mastered everything in this Guide, +you will have a firm grasp of basic Rust development. There's a whole lot more +out there, we've just covered the surface. There's tons of topics that you can +dig deeper into, and we've built specialized guides for many of them. To learn +more, dig into the [full documentation +index](http://doc.rust-lang.org/index.html). + +Happy hacking!