tutorial: Remove all references to 'records'. Misc

This commit is contained in:
Brian Anderson 2012-09-26 16:41:14 -07:00
parent e4148932fc
commit 2891f5abe3
3 changed files with 41 additions and 32 deletions

View File

@ -29,10 +29,10 @@ a limit duration. Borrowed pointers never claim any kind of ownership
over the data that they point at: instead, they are used for cases
where you like to make use of data for a short time.
As an example, consider a simple record type `point`:
As an example, consider a simple struct type `point`:
~~~
type point = {x: float, y: float};
struct point {x: float, y: float}
~~~
We can use this simple definition to allocate points in many ways. For
@ -82,7 +82,7 @@ compute_distance(shared_box, unique_box);
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 record value) and we have to take its address to get a
(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 created an alias: that is, another
route to the same data.
@ -325,15 +325,18 @@ which has been freed.
In fact, the compiler can apply this same kind of reasoning can be
applied to any memory which is _(uniquely) owned by the stack
frame_. So we could modify the previous example to introduce
additional unique pointers and records, and the compiler will still be
additional unique pointers and structs, and the compiler will still be
able to detect possible mutations:
~~~ {.xfail-test}
fn example3() -> int {
let mut x = ~{mut f: ~{g: 3}};
struct R { g: int }
struct S { mut f: ~R }
let mut x = ~S {mut f: ~R {g: 3}};
let y = &x.f.g;
x = ~{mut f: ~{g: 4}}; // Error reported here.
x.f = ~{g: 5}; // Error reported here.
x = ~S {mut f: ~R {g: 4}}; // Error reported here.
x.f = ~R {g: 5}; // Error reported here.
*y
}
~~~
@ -504,7 +507,7 @@ Stack Memory
~~~
As you can see, the `size` pointer would not be pointing at a `float` and
not a record. This is not good.
not a struct. This is not good.
So, in fact, for every `ref` binding, the compiler will impose the
same rules as the ones we saw for borrowing the interior of a unique
@ -559,14 +562,14 @@ defined by the caller.
In any case, whatever the lifetime L is, the pointer produced by
`&p.x` always has the same lifetime as `p` itself, as a pointer to a
field of a record is valid as long as the record is valid. Therefore,
field of a struct is valid as long as the struct is valid. Therefore,
the compiler is satisfied with the function `get_x()`.
To drill in this point, lets look at a variation on the example, this
time one which does not compile:
~~~ {.xfail-test}
type point = {x: float, y: float};
struct point {x: float, y: float}
fn get_x_sh(p: @point) -> &float {
&p.x // Error reported here
}

View File

@ -205,7 +205,7 @@ vector.
## Passing structures
C functions often take pointers to structs as arguments. Since Rust
records are binary-compatible with C structs, Rust programs can call
structs are binary-compatible with C structs, Rust programs can call
such functions directly.
This program uses the POSIX function `gettimeofday` to get a
@ -215,14 +215,20 @@ microsecond-resolution timer.
extern mod std;
use libc::c_ulonglong;
type timeval = {mut tv_sec: c_ulonglong,
mut tv_usec: c_ulonglong};
struct timeval {
mut tv_sec: c_ulonglong,
mut tv_usec: c_ulonglong
}
#[nolink]
extern mod lib_c {
fn gettimeofday(tv: *timeval, tz: *()) -> i32;
}
fn unix_time_in_microseconds() -> u64 unsafe {
let x = {mut tv_sec: 0 as c_ulonglong, mut tv_usec: 0 as c_ulonglong};
let x = timeval {
mut tv_sec: 0 as c_ulonglong,
mut tv_usec: 0 as c_ulonglong
};
lib_c::gettimeofday(ptr::addr_of(x), ptr::null());
return (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64);
}
@ -234,8 +240,8 @@ The `#[nolink]` attribute indicates that there's no foreign library to
link in. The standard C library is already linked with Rust programs.
A `timeval`, in C, is a struct with two 32-bit integers. Thus, we
define a record type with the same contents, and declare
`gettimeofday` to take a pointer to such a record.
define a struct type with the same contents, and declare
`gettimeofday` to take a pointer to such a struct.
The second argument to `gettimeofday` (the time zone) is not used by
this program, so it simply declares it to be a pointer to the nil

View File

@ -713,16 +713,16 @@ enum Shape {
}
~~~~
A value of this type is either a Circle, in which case it contains a
point struct and a float, or a Rectangle, in which case it contains
two point records. The run-time representation of such a value
A value of this type is either a `Circle`, in which case it contains a
`Point` struct and a float, or a `Rectangle`, in which case it contains
two `Point` structs. The run-time representation of such a value
includes an identifier of the actual form that it holds, much like the
'tagged union' pattern in C, but with better ergonomics.
The above declaration will define a type `shape` that can be used to
refer to such shapes, and two functions, `circle` and `rectangle`,
The above declaration will define a type `Shape` that can be used to
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({x: 0f, y: 0f}, 10f)` is the way to
the specified types). So `Circle(Point {x: 0f, y: 0f}, 10f)` is the way to
create a new circle.
Enum variants need not have type parameters. This, for example, is
@ -820,7 +820,7 @@ fn point_from_direction(dir: Direction) -> Point {
## Tuples
Tuples in Rust behave exactly like records, except that their fields
Tuples in Rust behave exactly like structs, except that their fields
do not have names (and can thus not be accessed with dot notation).
Tuples can have any arity except for 0 or 1 (though you may consider
nil, `()`, as the empty tuple if you like).
@ -1006,16 +1006,16 @@ of each is key to using Rust effectively.
# Boxes and pointers
In contrast to a lot of modern languages, aggregate types like records
In contrast to a lot of modern languages, aggregate types like structs
and enums are _not_ represented as pointers to allocated memory in
Rust. They are, as in C and C++, represented directly. This means that
if you `let x = {x: 1f, y: 1f};`, you are creating a record on the
stack. If you then copy it into a data structure, the whole record is
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, the whole struct is
copied, not just a pointer.
For small records like `point`, this is usually more efficient than
allocating memory and going through a pointer. But for big records, or
records with mutable fields, it can be useful to have a single copy on
For small structs like `Point`, this is usually more efficient than
allocating memory and going through a pointer. But for big structs, or
those with mutable fields, it can be useful to have a single copy on
the heap, and refer to that through a pointer.
Rust supports several types of pointers. The safe pointer types are
@ -1191,8 +1191,8 @@ compute_distance(shared_box, unique_box);
~~~
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 record value) and we have to take its address to get a
`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 created an alias: that is, another
route to the same data.
@ -1517,7 +1517,7 @@ fn each(v: &[int], op: fn(v: &int)) {
The reason we pass in a *pointer* to an integer rather than the
integer itself is that this is how the actual `each()` function for
vectors works. Using a pointer means that the function can be used
for vectors of any type, even large records that would be impractical
for vectors of any type, even large structs that would be impractical
to copy out of the vector on each iteration. 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.