Skip to content

Commit a0a729a

Browse files
committed
---
yaml --- r: 153077 b: refs/heads/try2 c: 5b11610 h: refs/heads/master i: 153075: f2d384f v: v3
1 parent ab9e778 commit a0a729a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+2131
-1318
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: c4ac124edda29eabffc2acc3255aca1a0c2680f0
8+
refs/heads/try2: 5b11610ced12e42f3de4d7f41fe47bbf07dd5af2
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/mk/platform.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ CFG_PATH_MUNGE_i686-pc-mingw32 :=
461461
CFG_LDPATH_i686-pc-mingw32 :=$(CFG_LDPATH_i686-pc-mingw32):$(PATH)
462462
CFG_RUN_i686-pc-mingw32=PATH="$(CFG_LDPATH_i686-pc-mingw32):$(1)" $(2)
463463
CFG_RUN_TARG_i686-pc-mingw32=$(call CFG_RUN_i686-pc-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
464+
RUSTC_FLAGS_i686-pc-mingw32=-C link-args="-Wl,--large-address-aware"
464465

465466
# i586-mingw32msvc configuration
466467
CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc

branches/try2/src/doc/guide.md

Lines changed: 332 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,45 @@ let x: int = 5;
515515
```
516516

517517
If I asked you to read this out loud to the rest of the class, you'd say "`x`
518-
is a binding with the type `int` and the value `five`." Rust requires you to
519-
initialize the binding with a value before you're allowed to use it. If
520-
we try...
518+
is a binding with the type `int` and the value `five`."
519+
520+
By default, bindings are **immutable**. This code will not compile:
521+
522+
```{ignore}
523+
let x = 5i;
524+
x = 10i;
525+
```
526+
527+
It will give you this error:
528+
529+
```{ignore,notrust}
530+
error: re-assignment of immutable variable `x`
531+
x = 10i;
532+
^~~~~~~
533+
```
534+
535+
If you want a binding to be mutable, you can use `mut`:
536+
537+
```{rust}
538+
let mut x = 5i;
539+
x = 10i;
540+
```
541+
542+
There is no single reason that bindings are immutable by default, but we can
543+
think about it through one of Rust's primary focuses: safety. If you forget to
544+
say `mut`, the compiler will catch it, and let you know that you have mutated
545+
something you may not have cared to mutate. If bindings were mutable by
546+
default, the compiler would not be able to tell you this. If you _did_ intend
547+
mutation, then the solution is quite easy: add `mut`.
548+
549+
There are other good reasons to avoid mutable state when possible, but they're
550+
out of the scope of this guide. In general, you can often avoid explicit
551+
mutation, and so it is preferable in Rust. That said, sometimes, mutation is
552+
what you need, so it's not verboten.
553+
554+
Let's get back to bindings. Rust variable bindings have one more aspect that
555+
differs from other languages: bindings are required to be initialized with a
556+
value before you're allowed to use it. If we try...
521557

522558
```{ignore}
523559
let x;
@@ -611,8 +647,301 @@ concept: `if`.
611647

612648
## If
613649

650+
Rust's take on `if` is not particularly complex, but it's much more like the
651+
`if` you'll find in a dynamically typed language than in a more traditional
652+
systems language. So let's talk about it, to make sure you grasp the nuances.
653+
654+
`if` is a specific form of a more general concept, the 'branch.' The name comes
655+
from a branch in a tree: a decision point, where depending on a choice,
656+
multiple paths can be taken.
657+
658+
In the case of `if`, there is one choice that leads down two paths:
659+
660+
```rust
661+
let x = 5i;
662+
663+
if x == 5i {
664+
println!("x is five!");
665+
}
666+
```
667+
668+
If we changed the value of `x` to something else, this line would not print.
669+
More specifically, if the expression after the `if` evaluates to `true`, then
670+
the block is executed. If it's `false`, then it is not.
671+
672+
If you want something to happen in the `false` case, use an `else`:
673+
674+
```
675+
let x = 5i;
676+
677+
if x == 5i {
678+
println!("x is five!");
679+
} else {
680+
println!("x is not five :(");
681+
}
682+
```
683+
684+
This is all pretty standard. However, you can also do this:
685+
686+
687+
```
688+
let x = 5i;
689+
690+
let y = if x == 5i {
691+
10i
692+
} else {
693+
15i
694+
};
695+
```
696+
697+
Which we can (and probably should) write like this:
698+
699+
```
700+
let x = 5i;
701+
702+
let y = if x == 5i { 10i } else { 15i };
703+
```
704+
705+
This reveals two interesting things about Rust: it is an expression-based
706+
language, and semicolons are different than in other 'curly brace and
707+
semicolon'-based languages. These two things are related.
708+
709+
### Expressions vs. Statements
710+
711+
Rust is primarily an expression based language. There are only two kinds of
712+
statements, and everything else is an expression.
713+
714+
So what's the difference? Expressions return a value, and statements do not.
715+
In many languages, `if` is a statement, and therefore, `let x = if ...` would
716+
make no sense. But in Rust, `if` is an expression, which means that it returns
717+
a value. We can then use this value to initialize the binding.
718+
719+
Speaking of which, bindings are a kind of the first of Rust's two statements.
720+
The proper name is a **declaration statement**. So far, `let` is the only kind
721+
of declaration statement we've seen. Let's talk about that some more.
722+
723+
In some languages, variable bindings can be written as expressions, not just
724+
statements. Like Ruby:
725+
726+
```{ruby}
727+
x = y = 5
728+
```
729+
730+
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
731+
following will produce a compile-time error:
732+
733+
```{ignore}
734+
let x = (let y = 5i); // found `let` in ident position
735+
```
736+
737+
The compiler is telling us here that it was expecting to see the beginning of
738+
an expression, and a `let` can only begin a statement, not an expression.
739+
740+
However, re-assigning to a mutable binding is an expression:
741+
742+
```{rust}
743+
let mut x = 0i;
744+
let y = x = 5i;
745+
```
746+
747+
In this case, we have an assignment expression (`x = 5`) whose value is
748+
being used as part of a `let` declaration statement (`let y = ...`).
749+
750+
The second kind of statement in Rust is the **expression statement**. Its
751+
purpose is to turn any expression into a statement. In practical terms, Rust's
752+
grammar expects statements to follow other statements. This means that you use
753+
semicolons to separate expressions from each other. This means that Rust
754+
looks a lot like most other languages that require you to use semicolons
755+
at the end of every line, and you will see semicolons at the end of almost
756+
every line of Rust code you see.
757+
758+
What is this exception that makes us say 'almost?' You saw it already, in this
759+
code:
760+
761+
```
762+
let x = 5i;
763+
764+
let y: int = if x == 5i { 10i } else { 15i };
765+
```
766+
767+
Note that I've added the type annotation to `y`, to specify explicitly that I
768+
want `y` to be an integer.
769+
770+
This is not the same as this, which won't compile:
771+
772+
```{ignore}
773+
let x = 5i;
774+
775+
let y: int = if x == 5 { 10i; } else { 15i; };
776+
```
777+
778+
Note the semicolons after the 10 and 15. Rust will give us the following error:
779+
780+
```{ignore,notrust}
781+
error: mismatched types: expected `int` but found `()` (expected int but found ())
782+
```
783+
784+
We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
785+
special type in Rust's type system. `()` is different than `null` in other
786+
languages, because `()` is distinct from other types. For example, in C, `null`
787+
is a valid value for a variable of type `int`. In Rust, `()` is _not_ a valid
788+
value for a variable of type `int`. It's only a valid value for variables of
789+
the type `()`, which aren't very useful. Remember how we said statements don't
790+
return a value? Well, that's the purpose of unit in this case. The semicolon
791+
turns any expression into a statement by throwing away its value and returning
792+
unit instead.
793+
794+
There's one more time in which you won't see a semicolon at the end of a line
795+
of Rust code. For that, we'll need our next concept: functions.
796+
614797
## Functions
615798

799+
You've already seen one function so far, the `main` function:
800+
801+
```{rust}
802+
fn main() {
803+
}
804+
```
805+
806+
This is the simplest possible function declaration. As we mentioned before,
807+
`fn` says 'this is a function,' followed by the name, some parenthesis because
808+
this function takes no arguments, and then some curly braces to indicate the
809+
body. Here's a function named `foo`:
810+
811+
```{rust}
812+
fn foo() {
813+
}
814+
```
815+
816+
So, what about taking arguments? Here's a function that prints a number:
817+
818+
```{rust}
819+
fn print_number(x: int) {
820+
println!("x is: {}", x);
821+
}
822+
```
823+
824+
Here's a complete program that uses `print_number`:
825+
826+
```{rust}
827+
fn main() {
828+
print_number(5);
829+
}
830+
831+
fn print_number(x: int) {
832+
println!("x is: {}", x);
833+
}
834+
```
835+
836+
As you can see, function arguments work very similar to `let` declarations:
837+
you add a type to the argument name, after a colon.
838+
839+
Here's a complete program that adds two numbers together and prints them:
840+
841+
```{rust}
842+
fn main() {
843+
print_sum(5, 6);
844+
}
845+
846+
fn print_sum(x: int, y: int) {
847+
println!("sum is: {}", x + y);
848+
}
849+
```
850+
851+
You separate arguments with a comma, both when you call the function, as well
852+
as when you declare it.
853+
854+
Unlike `let`, you _must_ declare the types of function arguments. This does
855+
not work:
856+
857+
```{ignore}
858+
fn print_number(x, y) {
859+
println!("x is: {}", x + y);
860+
}
861+
```
862+
863+
You get this error:
864+
865+
```{ignore,notrust}
866+
hello.rs:5:18: 5:19 error: expected `:` but found `,`
867+
hello.rs:5 fn print_number(x, y) {
868+
```
869+
870+
This is a deliberate design decision. While full-program inference is possible,
871+
languages which have it, like Haskell, often suggest that documenting your
872+
types explicitly is a best-practice. We agree that forcing functions to declare
873+
types while allowing for inference inside of function bodies is a wonderful
874+
compromise between full inference and no inference.
875+
876+
What about returning a value? Here's a function that adds one to an integer:
877+
878+
```{rust}
879+
fn add_one(x: int) -> int {
880+
x + 1
881+
}
882+
```
883+
884+
Rust functions return exactly one value, and you declare the type after an
885+
'arrow', which is a dash (`-`) followed by a greater-than sign (`>`).
886+
887+
You'll note the lack of a semicolon here. If we added it in:
888+
889+
```{ignore}
890+
fn add_one(x: int) -> int {
891+
x + 1;
892+
}
893+
```
894+
895+
We would get an error:
896+
897+
```{ignore,notrust}
898+
note: consider removing this semicolon:
899+
x + 1;
900+
^
901+
error: not all control paths return a value
902+
fn add_one(x: int) -> int {
903+
x + 1;
904+
}
905+
```
906+
907+
Remember our earlier discussions about semicolons and `()`? Our function claims
908+
to return an `int`, but with a semicolon, it would return `()` instead. Rust
909+
realizes this probably isn't what we want, and suggests removing the semicolon.
910+
911+
This is very much like our `if` statement before: the result of the block
912+
(`{}`) is the value of the expression. Other expression-oriented languages,
913+
such as Ruby, work like this, but it's a bit unusual in the systems programming
914+
world. When people first learn about this, they usually assume that it
915+
introduces bugs. But because Rust's type system is so strong, and because unit
916+
is its own unique type, we have never seen an issue where adding or removing a
917+
semicolon in a return position would cause a bug.
918+
919+
But what about early returns? Rust does have a keyword for that, `return`:
920+
921+
```{rust}
922+
fn foo(x: int) -> int {
923+
if x < 5 { return x; }
924+
925+
x + 1
926+
}
927+
```
928+
929+
Using a `return` as the last line of a function works, but is considered poor
930+
style:
931+
932+
```{rust}
933+
fn foo(x: int) -> int {
934+
if x < 5 { return x; }
935+
936+
return x + 1;
937+
}
938+
```
939+
940+
There are some additional ways to define functions, but they involve features
941+
that we haven't learned about yet, so let's just leave it at that for now.
942+
943+
## Comments
944+
616945
return
617946

618947
comments

branches/try2/src/doc/rust.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,8 +2155,6 @@ These are functions:
21552155

21562156
* `str_eq`
21572157
: Compare two strings (`&str`) for equality.
2158-
* `uniq_str_eq`
2159-
: Compare two owned strings (`String`) for equality.
21602158
* `strdup_uniq`
21612159
: Return a new unique string
21622160
containing a copy of the contents of a unique string.

branches/try2/src/doc/rustdoc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Calculates the factorial of a number.
5151
5252
Given the input integer `n`, this function will calculate `n!` and return it.
5353
"]
54-
pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n)} }
54+
pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n - 1)} }
5555
# fn main() {}
5656
~~~
5757

0 commit comments

Comments
 (0)