diff --git a/doc/tutorial.md b/doc/tutorial.md index 535b965cf75fe..4743e384633da 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1551,14 +1551,13 @@ fn contains(v: ~[int], elt: int) -> bool { ## Generic functions -Throughout this tutorial, we've been defining functions like -that act only on single data types. It is 2012, and we no longer -expect to be defining such functions again and again for every type -they apply to. Thus, Rust allows functions and datatypes to have type -parameters. +Throughout this tutorial, we've been defining functions that act only on +single data types. It's a burden to define such functions again and again for +every type they apply to. Thus, Rust allows functions and datatypes to have +type parameters. ~~~~ -fn map(vector: ~[T], function: fn(T) -> U) -> ~[U] { +fn map(vector: &[T], function: fn(T) -> U) -> ~[U] { let mut accumulator = ~[]; for vector.each |element| { vec::push(accumulator, function(element)); @@ -1577,51 +1576,20 @@ inside them, but you can pass them around. ## Generic datatypes -Generic `type` and `enum` declarations follow the same pattern: - -~~~~ -type circular_buf = {start: uint, - end: uint, - buf: ~[mut T]}; - -enum option { some(T), none } -~~~~ - -You can then declare a function to take a `circular_buf` or return -an `option<~str>`, or even an `option` if the function itself is -generic. - -The `option` type given above exists in the core library and is the -way Rust programs express the thing that in C would be a nullable -pointer. The nice part is that you have to explicitly unpack an -`option` type, so accidental null pointer dereferences become -impossible. - -## Type-inference and generics - -Rust's type inferrer works very well with generics, but there are -programs that just can't be typed. +Generic `type`, `struct`, and `enum` declarations follow the same pattern: ~~~~ -let n = option::None; -# option::iter(n, fn&(&&x:int) {}) -~~~~ - -If you never do anything else with `n`, the compiler will not be able -to assign a type to it. (The same goes for `[]`, the empty vector.) If -you really want to have such a statement, you'll have to write it like -this: +struct Stack { + elements: ~[mut T] +} -~~~~ -let n2: Option = option::None; -// or -let n = option::None::; +enum Maybe { + Just(T), + Nothing +} ~~~~ -Note that, in a value expression, `<` already has a meaning as a -comparison operator, so you'll have to write `::` to explicitly -give a type to a name that denotes a generic value. Fortunately, this -is rarely necessary. +These declarations produce valid types like `Stack` and `Maybe`. ## Kinds @@ -1661,34 +1629,6 @@ resource type. Rust has several kinds that can be used as type bounds: > kinds will actually be traits that the compiler has special > knowledge about. -## Generic functions and argument-passing - -The previous section mentioned that arguments are passed by pointer or -by value based on their type. There is one situation in which this is -difficult. If you try this program: - -~~~~{.xfail-test} -fn plus1(x: int) -> int { x + 1 } -vec::map(~[1, 2, 3], plus1); -~~~~ - -You will get an error message about argument passing styles -disagreeing. The reason is that generic types are always passed by -reference, so `map` expects a function that takes its argument by -reference. The `plus1` you defined, however, uses the default, -efficient way to pass integers, which is by value. To get around this -issue, you have to explicitly mark the arguments to a function that -you want to pass to a generic higher-order function as being passed by -pointer, using the `&&` sigil: - -~~~~ -fn plus1(&&x: int) -> int { x + 1 } -vec::map(~[1, 2, 3], plus1); -~~~~ - -> ***Note:*** This is inconvenient, and we are hoping to get rid of -> this restriction in the future. - # Modules and crates The Rust namespace is divided into modules. Each source file starts