Skip to content

Commit 65e5b14

Browse files
steveklabnikalexcrichton
authored andcommitted
---
yaml --- r: 153054 b: refs/heads/try2 c: 748b947 h: refs/heads/master v: v3
1 parent fb31866 commit 65e5b14

File tree

7 files changed

+303
-119
lines changed

7 files changed

+303
-119
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: dd812ccbb56193c36819993dea25912788b447f0
8+
refs/heads/try2: 748b9477f8b0c0fdbb3a45a83bf6f26b5b6c3378
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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,6 @@ 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"
465464

466465
# i586-mingw32msvc configuration
467466
CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc

branches/try2/src/doc/guide.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,153 @@ concept: `if`.
611611

612612
## If
613613

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

616763
return

branches/try2/src/libnum/rational.rs

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -274,17 +274,12 @@ impl<T: Clone + Integer + PartialOrd>
274274
Num for Ratio<T> {}
275275

276276
/* String conversions */
277-
impl<T: fmt::Show + Eq + One> fmt::Show for Ratio<T> {
278-
/// Renders as `numer/denom`. If denom=1, renders as numer.
277+
impl<T: fmt::Show> fmt::Show for Ratio<T> {
278+
/// Renders as `numer/denom`.
279279
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280-
if self.denom == One::one() {
281-
write!(f, "{}", self.numer)
282-
} else {
283-
write!(f, "{}/{}", self.numer, self.denom)
284-
}
280+
write!(f, "{}/{}", self.numer, self.denom)
285281
}
286282
}
287-
288283
impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
289284
/// Renders as `numer/denom` where the numbers are in base `radix`.
290285
fn to_str_radix(&self, radix: uint) -> String {
@@ -296,20 +291,21 @@ impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
296291

297292
impl<T: FromStr + Clone + Integer + PartialOrd>
298293
FromStr for Ratio<T> {
299-
/// Parses `numer/denom` or just `numer`
294+
/// Parses `numer/denom`.
300295
fn from_str(s: &str) -> Option<Ratio<T>> {
301-
let mut split = s.splitn('/', 1);
302-
303-
let num = split.next().and_then(|n| FromStr::from_str(n));
304-
let den = split.next().or(Some("1")).and_then(|d| FromStr::from_str(d));
305-
306-
match (num, den) {
307-
(Some(n), Some(d)) => Some(Ratio::new(n, d)),
308-
_ => None
296+
let split: Vec<&str> = s.splitn('/', 1).collect();
297+
if split.len() < 2 {
298+
return None
309299
}
300+
let a_option: Option<T> = FromStr::from_str(*split.get(0));
301+
a_option.and_then(|a| {
302+
let b_option: Option<T> = FromStr::from_str(*split.get(1));
303+
b_option.and_then(|b| {
304+
Some(Ratio::new(a.clone(), b.clone()))
305+
})
306+
})
310307
}
311308
}
312-
313309
impl<T: FromStrRadix + Clone + Integer + PartialOrd>
314310
FromStrRadix for Ratio<T> {
315311
/// Parses `numer/denom` where the numbers are in base `radix`.
@@ -433,13 +429,6 @@ mod test {
433429
assert!(!_neg1_2.is_integer());
434430
}
435431

436-
#[test]
437-
fn test_show() {
438-
assert_eq!(format!("{}", _2), "2".to_string());
439-
assert_eq!(format!("{}", _1_2), "1/2".to_string());
440-
assert_eq!(format!("{}", _0), "0".to_string());
441-
assert_eq!(format!("{}", Ratio::from_integer(-2i)), "-2".to_string());
442-
}
443432

444433
mod arith {
445434
use super::{_0, _1, _2, _1_2, _3_2, _neg1_2, to_big};
@@ -573,11 +562,11 @@ mod test {
573562
assert_eq!(FromStr::from_str(s.as_slice()), Some(r));
574563
assert_eq!(r.to_str(), s);
575564
}
576-
test(_1, "1".to_string());
577-
test(_0, "0".to_string());
565+
test(_1, "1/1".to_string());
566+
test(_0, "0/1".to_string());
578567
test(_1_2, "1/2".to_string());
579568
test(_3_2, "3/2".to_string());
580-
test(_2, "2".to_string());
569+
test(_2, "2/1".to_string());
581570
test(_neg1_2, "-1/2".to_string());
582571
}
583572
#[test]

0 commit comments

Comments
 (0)