@@ -1432,86 +1432,6 @@ building our guessing game, but we need to know how to do one last thing first:
1432
1432
get input from the keyboard. You can't have a guessing game without the ability
1433
1433
to guess!
1434
1434
1435
- # Strings
1436
-
1437
- Strings are an important concept for any programmer to master. Rust's string
1438
- handling system is a bit different than in other languages, due to its systems
1439
- focus. Any time you have a data structure of variable size, things can get
1440
- tricky, and strings are a re-sizable data structure. That said, Rust's strings
1441
- also work differently than in some other systems languages, such as C.
1442
-
1443
- Let's dig into the details. A ** string** is a sequence of unicode scalar values
1444
- encoded as a stream of UTF-8 bytes. All strings are guaranteed to be
1445
- validly-encoded UTF-8 sequences. Additionally, strings are not null-terminated
1446
- and can contain null bytes.
1447
-
1448
- Rust has two main types of strings: ` &str ` and ` String ` .
1449
-
1450
- The first kind is a ` &str ` . This is pronounced a 'string slice.' String literals
1451
- are of the type ` &str ` :
1452
-
1453
- ``` {rust}
1454
- let string = "Hello there.";
1455
- ```
1456
-
1457
- This string is statically allocated, meaning that it's saved inside our
1458
- compiled program, and exists for the entire duration it runs. The ` string `
1459
- binding is a reference to this statically allocated string. String slices
1460
- have a fixed size, and cannot be mutated.
1461
-
1462
- A ` String ` , on the other hand, is an in-memory string. This string is
1463
- growable, and is also guaranteed to be UTF-8.
1464
-
1465
- ``` {rust}
1466
- let mut s = "Hello".to_string();
1467
- println!("{}", s);
1468
-
1469
- s.push_str(", world.");
1470
- println!("{}", s);
1471
- ```
1472
-
1473
- You can coerce a ` String ` into a ` &str ` with the ` as_slice() ` method:
1474
-
1475
- ``` {rust}
1476
- fn takes_slice(slice: &str) {
1477
- println!("Got: {}", slice);
1478
- }
1479
-
1480
- fn main() {
1481
- let s = "Hello".to_string();
1482
- takes_slice(s.as_slice());
1483
- }
1484
- ```
1485
-
1486
- To compare a String to a constant string, prefer ` as_slice() ` ...
1487
-
1488
- ``` {rust}
1489
- fn compare(string: String) {
1490
- if string.as_slice() == "Hello" {
1491
- println!("yes");
1492
- }
1493
- }
1494
- ```
1495
-
1496
- ... over ` to_string() ` :
1497
-
1498
- ``` {rust}
1499
- fn compare(string: String) {
1500
- if string == "Hello".to_string() {
1501
- println!("yes");
1502
- }
1503
- }
1504
- ```
1505
-
1506
- Converting a ` String ` to a ` &str ` is cheap, but converting the ` &str ` to a
1507
- ` String ` involves allocating memory. No reason to do that unless you have to!
1508
-
1509
- That's the basics of strings in Rust! They're probably a bit more complicated
1510
- than you are used to, if you come from a scripting language, but when the
1511
- low-level details matter, they really matter. Just remember that ` String ` s
1512
- allocate memory and control their data, while ` &str ` s are a reference to
1513
- another string, and you'll be all set.
1514
-
1515
1435
# Standard Input
1516
1436
1517
1437
Getting input from the keyboard is pretty easy, but uses some things
@@ -3694,94 +3614,6 @@ guide](http://doc.rust-lang.org/guide-pointers.html#rc-and-arc).
3694
3614
3695
3615
# Patterns
3696
3616
3697
- # Method Syntax
3698
-
3699
- Functions are great, but if you want to call a bunch of them on some data, it
3700
- can be awkward. Consider this code:
3701
-
3702
- ``` {rust,ignore}
3703
- baz(bar(foo(x)));
3704
- ```
3705
-
3706
- We would read this left-to right, and so we see 'baz bar foo.' But this isn't the
3707
- order that the functions would get called in, that's inside-out: 'foo bar baz.'
3708
- Wouldn't it be nice if we could do this instead?
3709
-
3710
- ``` {rust,ignore}
3711
- x.foo().bar().baz();
3712
- ```
3713
-
3714
- Luckily, as you may have guessed with the leading question, you can! Rust provides
3715
- the ability to use this ** method call syntax** via the ` impl ` keyword.
3716
-
3717
- Here's how it works:
3718
-
3719
- ```
3720
- struct Circle {
3721
- x: f64,
3722
- y: f64,
3723
- radius: f64,
3724
- }
3725
-
3726
- impl Circle {
3727
- fn area(&self) -> f64 {
3728
- std::f64::consts::PI * (self.radius * self.radius)
3729
- }
3730
- }
3731
-
3732
- fn main() {
3733
- let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
3734
- println!("{}", c.area());
3735
- }
3736
- ```
3737
-
3738
- This will print ` 12.566371 ` .
3739
-
3740
- We've made a struct that represents a circle. We then write an ` impl ` block,
3741
- and inside it, define a method, ` area ` . Methods take a special first
3742
- parameter, ` &self ` . There are three variants: ` self ` , ` &self ` , and ` &mut self ` .
3743
- You can think of this first parameter as being the ` x ` in ` x.foo() ` . The three
3744
- variants correspond to the three kinds of thing ` x ` could be: ` self ` if it's
3745
- just a value on the stack, ` &self ` if it's a reference, and ` &mut self ` if it's
3746
- a mutable reference. We should default to using ` &self ` , as it's the most
3747
- common.
3748
-
3749
- Finally, as you may remember, the value of the area of a circle is ` π*r² ` .
3750
- Because we took the ` &self ` parameter to ` area ` , we can use it just like any
3751
- other parameter. Because we know it's a ` Circle ` , we can access the ` radius `
3752
- just like we would with any other struct. An import of π and some
3753
- multiplications later, and we have our area.
3754
-
3755
- You can also define methods that do not take a ` self ` parameter. Here's a
3756
- pattern that's very common in Rust code:
3757
-
3758
- ```
3759
- struct Circle {
3760
- x: f64,
3761
- y: f64,
3762
- radius: f64,
3763
- }
3764
-
3765
- impl Circle {
3766
- fn new(x: f64, y: f64, radius: f64) -> Circle {
3767
- Circle {
3768
- x: x,
3769
- y: y,
3770
- radius: radius,
3771
- }
3772
- }
3773
- }
3774
-
3775
- fn main() {
3776
- let c = Circle::new(0.0, 0.0, 2.0);
3777
- }
3778
- ```
3779
-
3780
- This ** static method** builds a new ` Circle ` for us. Note that static methods
3781
- are called with the ` Struct::method() ` syntax, rather than the ` ref.method() `
3782
- syntax.
3783
-
3784
-
3785
3617
# Closures
3786
3618
3787
3619
So far, we've made lots of functions in Rust. But we've given them all names.
@@ -4486,152 +4318,6 @@ the same function, so our binary is a little bit larger.
4486
4318
4487
4319
# Tasks
4488
4320
4489
- Concurrency and parallelism are topics that are of increasing interest to a
4490
- broad subsection of software developers. Modern computers are often multi-core,
4491
- to the point that even embedded devices like cell phones have more than one
4492
- processor. Rust's semantics lend themselves very nicely to solving a number of
4493
- issues that programmers have with concurrency. Many concurrency errors that are
4494
- runtime errors in other languages are compile-time errors in Rust.
4495
-
4496
- Rust's concurrency primitive is called a ** task** . Tasks are lightweight, and
4497
- do not share memory in an unsafe manner, preferring message passing to
4498
- communicate. It's worth noting that tasks are implemented as a library, and
4499
- not part of the language. This means that in the future, other concurrency
4500
- libraries can be written for Rust to help in specific scenarios. Here's an
4501
- example of creating a task:
4502
-
4503
- ``` {rust}
4504
- spawn(proc() {
4505
- println!("Hello from a task!");
4506
- });
4507
- ```
4508
-
4509
- The ` spawn ` function takes a proc as an argument, and runs that proc in a new
4510
- task. A proc takes ownership of its entire environment, and so any variables
4511
- that you use inside the proc will not be usable afterward:
4512
-
4513
- ``` {rust,ignore}
4514
- let mut x = vec![1i, 2i, 3i];
4515
-
4516
- spawn(proc() {
4517
- println!("The value of x[0] is: {}", x[0]);
4518
- });
4519
-
4520
- println!("The value of x[0] is: {}", x[0]); // error: use of moved value: `x`
4521
- ```
4522
-
4523
- ` x ` is now owned by the proc, and so we can't use it anymore. Many other
4524
- languages would let us do this, but it's not safe to do so. Rust's type system
4525
- catches the error.
4526
-
4527
- If tasks were only able to capture these values, they wouldn't be very useful.
4528
- Luckily, tasks can communicate with each other through ** channel** s. Channels
4529
- work like this:
4530
-
4531
- ``` {rust}
4532
- let (tx, rx) = channel();
4533
-
4534
- spawn(proc() {
4535
- tx.send("Hello from a task!".to_string());
4536
- });
4537
-
4538
- let message = rx.recv();
4539
- println!("{}", message);
4540
- ```
4541
-
4542
- The ` channel() ` function returns two endpoints: a ` Receiver<T> ` and a
4543
- ` Sender<T> ` . You can use the ` .send() ` method on the ` Sender<T> ` end, and
4544
- receive the message on the ` Receiver<T> ` side with the ` recv() ` method. This
4545
- method blocks until it gets a message. There's a similar method, ` .try_recv() ` ,
4546
- which returns an ` Option<T> ` and does not block.
4547
-
4548
- If you want to send messages to the task as well, create two channels!
4549
-
4550
- ``` {rust}
4551
- let (tx1, rx1) = channel();
4552
- let (tx2, rx2) = channel();
4553
-
4554
- spawn(proc() {
4555
- tx1.send("Hello from a task!".to_string());
4556
- let message = rx2.recv();
4557
- println!("{}", message);
4558
- });
4559
-
4560
- let message = rx1.recv();
4561
- println!("{}", message);
4562
-
4563
- tx2.send("Goodbye from main!".to_string());
4564
- ```
4565
-
4566
- The proc has one sending end and one receiving end, and the main task has one
4567
- of each as well. Now they can talk back and forth in whatever way they wish.
4568
-
4569
- Notice as well that because ` Sender ` and ` Receiver ` are generic, while you can
4570
- pass any kind of information through the channel, the ends are strongly typed.
4571
- If you try to pass a string, and then an integer, Rust will complain.
4572
-
4573
- ## Futures
4574
-
4575
- With these basic primitives, many different concurrency patterns can be
4576
- developed. Rust includes some of these types in its standard library. For
4577
- example, if you wish to compute some value in the background, ` Future ` is
4578
- a useful thing to use:
4579
-
4580
- ``` {rust}
4581
- use std::sync::Future;
4582
-
4583
- let mut delayed_value = Future::spawn(proc() {
4584
- // just return anything for examples' sake
4585
-
4586
- 12345i
4587
- });
4588
- println!("value = {}", delayed_value.get());
4589
- ```
4590
-
4591
- Calling ` Future::spawn ` works just like ` spawn() ` : it takes a proc. In this
4592
- case, though, you don't need to mess with the channel: just have the proc
4593
- return the value.
4594
-
4595
- ` Future::spawn ` will return a value which we can bind with ` let ` . It needs
4596
- to be mutable, because once the value is computed, it saves a copy of the
4597
- value, and if it were immutable, it couldn't update itself.
4598
-
4599
- The proc will go on processing in the background, and when we need the final
4600
- value, we can call ` get() ` on it. This will block until the result is done,
4601
- but if it's finished computing in the background, we'll just get the value
4602
- immediately.
4603
-
4604
- ## Success and failure
4605
-
4606
- Tasks don't always succeed, they can also fail. A task that wishes to fail
4607
- can call the ` fail! ` macro, passing a message:
4608
-
4609
- ``` {rust}
4610
- spawn(proc() {
4611
- fail!("Nope.");
4612
- });
4613
- ```
4614
-
4615
- If a task fails, it is not possible for it to recover. However, it can
4616
- notify other tasks that it has failed. We can do this with ` task::try ` :
4617
-
4618
- ``` {rust}
4619
- use std::task;
4620
- use std::rand;
4621
-
4622
- let result = task::try(proc() {
4623
- if rand::random() {
4624
- println!("OK");
4625
- } else {
4626
- fail!("oops!");
4627
- }
4628
- });
4629
- ```
4630
-
4631
- This task will randomly fail or succeed. ` task::try ` returns a ` Result `
4632
- type, so we can handle the response like any other computation that may
4633
- fail.
4634
-
4635
4321
# Macros
4636
4322
4637
4323
# Unsafe
0 commit comments