tutorial: Remove all references to 'records'. Misc
This commit is contained in:
parent
e4148932fc
commit
2891f5abe3
@ -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, let’s 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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user