blue_sky 0.1.1

A fun game where you guess what number the computer has chosen.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
use std::cmp::Ordering;
use std::collections::HashMap;
use std::env::args;
use std::fmt::{format, Debug, Display};
use std::fs::File;
use std::{env, fs, io, process, thread};
use std::error::Error;
use std::io::ErrorKind;
use std::pin::pin;
use std::str::Matches;
use std::time::Duration;
use rand::Rng;
use blue_sky::{run, search, Config};

//cargo doc --open 每个crate的使用文档
fn main() {
    //guess();
    //variables();
    //data_type();
    //foreach();
    // scope();
    //variable_copy();
    //ownership();
    //slice(&String::from("Hello, world!"));
    //slice_simple();
    //struct_define();
    // tuple_struct();
    //tangle_area_test();
    //related_function();
    //enum_test();
    //value_in_cents(Coin::Quarter(State::Alabama));
    //vector();
    //hashmap();
    //panic();
    //call_generic_type();
    //trait_test();
    //lifecycle_null_ref();
    //longest_test();
    //mini_grep();
    //excise_plan();
    iter();
}
//迭代器
fn iter() {
    let vec = vec![1, 2, 3, 4];
    let iter = vec.iter();
    //let sum = iter.sum();
    for item in iter {
        println!("{}", item);
    }

    let vec1 = vec![1, 2, 3, 4];
    let iter1 = vec1.iter();
    let new_vec:Vec<i32> = iter1.map(|x| x + 1).collect();
    for i in new_vec {
        println!("{}", i);
    }
}
//闭包
struct Cacher<T>
where
    T: Fn(u32) -> u32, //T 的 trait bound 指定了 T 是一个使用 Fn 的闭包
{
    calculation: T, //函数类型
    value: Option<u32>, //执行该函数返回的值
}
impl<T> Cacher<T>
where
    T: Fn(u32) -> u32,
{
    //构建Cacher对象
    fn new(calculation: T) -> Cacher<T> {
        Cacher { calculation, value: None }
    }
    //存在返回,不存在计算
    fn value(&mut self, arg: u32) -> u32 {
        match self.value {
            Some(v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.value = Some(v);
                v
            }
        }
    }
}
fn excise_plan() {
    let simulated_user_specified_value = 10;
    let simulated_random_number = 7;

    generate_workout(
        simulated_user_specified_value,
        simulated_random_number,
    );
}

fn generate_workout(intensity: u32, random_number: u32) {
    ////定义闭包接收一个参数 num
    let expensive_closure = |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    }; //注意分号

    let mut cacher = Cacher::new(expensive_closure);
    if intensity < 25 {
        println!(
            "Today, do {} pushups!",
            cacher.value(intensity));
        println!(
            "Next, do {} situps!",
            cacher.value(intensity)
        );
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!(
                "Today, run for {} minutes!",
                cacher.value(intensity)
            );
        }
    }
}

//实战-模拟命令行grep命令
fn mini_grep() {
    //获取系统环境变量
    let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
    //获取命令行参数
    let args: Vec<String> = args().collect();
    let config = Config::new(&args).unwrap_or_else(|err| {
        println!("Problem parsing arguments: {}", err);
        process::exit(1);
    });

    if let Err(e) = run(&config) {
        println!("{}", e);
        process::exit(1);
    }
}

//单元测试
#[cfg(test)]
mod tests {
    #[test]
    fn unit_test() {
        assert_eq!(2 + 2, 3, "这里失败了....");
    }
    #[test]
    #[should_panic]
    fn valid_val() {}
}

//结合泛型类型参数、trait bounds 和生命周期
fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
where
    T: Display,
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
//这里有一种特殊的生命周期值得讨论:'static,其生命周期能够存活于整个程序期间。所有的字符串字面量都拥有 'static 生命周期
fn static_lifecycle() {
    let s: &'static str = "I have a static lifetime.";
}
//结构体定义中的每一个引用添加生命周期标注
fn test_important_excerpt() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.')
        .next()
        .expect("Could not find a '.'");
    let i = ImportantExcerpt { part: first_sentence };
}
struct ImportantExcerpt<'a> {
    part: &'a str,
}

//生命周期(避免悬垂引用)
fn longest_test() {
    let str1 = String::from("abcd");
    let str2 = "xyz";
    let r = longest(str1.as_str(), &str2);
    println!("{}", r);
}
//生命周期标注语法(生命周期标注并不改变任何引用的生命周期的长短,当指定了泛型生命周期后函数也能接受任何生命周期的引用。生命周期标注描述了多个引用生命周期相互的关系,而不影响其生命周期)
//&i32        // 引用
//'a i32     // 带有显式生命周期的引用
//&'a mut i32 // 带有显式生命周期的可变引用
//这里我们想要告诉 Rust 关于参数中的引用和返回值之间的限制是他们都必须拥有相同的生命周期
//现在函数签名表明对于某些生命周期 'a,函数会获取两个参数,他们都是与生命周期 'a 存在的一样长的字符串 slice。函数会返回一个同样也与生命周期 'a 存
// 在的一样长的字符串 slice。它的实际含义是 longest 函数返回的引用的生命周期与传入该函数的引用的生命周期的较小者一致
// 'a 的具体生命周期等同于 x 和 y 的生命周期中较小的那一个 (重要)
//综上,生命周期语法是用于将函数的多个参数与其返回值的生命周期进行关联的
fn longest<'a>(str1: &'a str, str2: &'a str) -> &'a str {
    if str1.len() > str2.len() {
        str1
    } else {
        str2
    }
}
//我们为参数 x 和返回值指定了生命周期参数 'a,不过没有为参数 y 指定,因为 y 的生命周期与参数 x 和返回值的生命周期没有任何关系。
fn longest_1<'a>(x: &'a str, y: &str) -> &'a str {
    x
}
//生命周期(避免悬垂引用)
fn lifecycle_null_ref() {
    {
        let r = 10;                // ---------+-- 'a
        //          |
        {                     //          |
            let x = 5;        // -+-- 'b  |
            //r = &x;(注释放开报错)           //  |       |
        }                     // -+       | //借用的x引用在离开作用域后失效,产生悬垂引用 (报错信息 `x` does not live long enough)
        //          |
        println!("r: {}", r); //          |
    }                         // ---------+
}
//Trait (接口)
fn trait_test() {
    let article = NewsArticle { headline: String::from("xxx"), location: String::from("xxx"), author: String::from("xxx"), content: String::from("xxx") };
    println!("{}", article.summarize());
    article.default();
    trait_as_params(&article);
    notify(&article)
}
fn returns_summarizable() -> impl Summary {
    NewsArticle { headline: String::from("xxx"), location: String::from("xxx"), author: String::from("xxx"), content: String::from("xxx") }
}

fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
    2
}
//where 等价上面的写法(看起来简单一些)
fn some_function_simple<T, U>(t: T, u: U) -> i32
where
    T: Display + Clone,
    U: Clone + Debug,
{
    2
}
//限制多种类型
pub fn notify_advance<T: Summary + SummaryAdvance>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}
//限制T的类型
pub fn notify<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}

fn trait_as_params_advanced(summary: &(impl Summary + SummaryAdvance)) {
    println!("{:#?}", summary.summarize());
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

//接口作为参数
fn trait_as_params(summary: &impl Summary) {
    println!("{:#?}", summary.summarize());
}
impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
}
pub trait Summary {
    //默认实现
    fn default(&self) -> String {
        String::from("(Read more...)")
    }
    fn summarize(&self) -> String;
}

pub trait SummaryAdvance {
    //默认实现
    fn advanced(&self) -> String;
}
//泛型
struct PointPosition<T> {
    x: T,
    y: T,
}
enum PointType<T> {
    Some(T),
    None,
}
enum Result1<T, E> {
    Ok(PointPosition<T>),
    Err(E),
}
fn call_generic_type() {
    let arr = [1, 2, 3];
    println!("aaaaaa {}", generic_type(&arr));
}
fn generic_type<T: std::cmp::PartialOrd + Copy>(arr: &[T]) -> T
{
    let mut largest = arr[0];

    for &item in arr.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}
//panic
fn panic() {
    //注意与 Option 枚举一样,Result 枚举和其成员也被导入到了 prelude 中
    let f = File::open("/Users/qumingxing/Downloads/hello.txt");
    let f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("/Users/qumingxing/Downloads/hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("create file failed!{}", e)
            },
            other_error => panic!("open file failed!")
        }
    };
}
//hashmap
fn hashmap() {
    let mut map = HashMap::new();
    map.insert(1, 2);
    map.insert(2, 3);
    let v = map.get(&1);
    println!("{}", v.expect("v not found"));
    for (k, v) in &map {
        println!("{} {}", k, v);
    }
}
//集合
fn vector() {
    let vec: Vec<i32> = Vec::new();
    let mut vec1 = vec![1, 2, 3];
    vec1.push(10);
    //不获取所有权(借用)
    let v = &vec1[1];
    println!("vec1: {:?}", v);
    match vec1.get(1) {
        Some(third) => println!("vec1: {:?}", third),
        None => println!("vec1 is empty")
    }
    for i in &mut vec1 {
        //* 表示解引用,修改vec1中引用的值
        *i += 10;
        println!("{}", i);
    }
    //let f = vec1[100];//panic
    let f1 = vec1.get(100);
    println!("{:?}", f1); //None
}
/**
包(Packages): Cargo 的一个功能,它允许你构建、测试和分享 crate。提供一系列功能的一个或者多个 crate。一个包会包含有一个 Cargo.toml 文件,阐述如何去构建这些 crate
Crates :一个模块的树形结构,它形成了库或二进制项目。
模块(Modules)和 use: 允许你控制作用域和路径的私有性(我们可以将一个 crate 中的代码进行分组,以提高可读性与重用性,模块还可以控制项的 私有性)。
路径(path):一个命名例如结构体、函数或模块等项的方式

包中所包含的内容由几条规则来确立。一个包中至多 只能 包含一个库 crate(library crate);
包中可以包含任意多个二进制 crate(binary crate);包中至少包含一个 crate,无论是库的还是二进制的。

src/main.rs 就是一个与包同名的二进制 crate 的 crate 根

Cargo 知道如果包目录中包含 src/lib.rs,则包带有与其同名的库 crate,且 src/lib.rs 是 crate 根。crate 根文件将由 Cargo 传递给 rustc 来实际构建库或者二进制项目

在此,我们有了一个只包含 src/main.rs 的包,意味着它只含有一个名为 hello_world 的二进制 crate

如果一个包同时含有 src/main.rs 和 src/lib.rs,则它有两个 crate,一个库和一个二进制项,且名字都与包相同
*/
//if let 语句可以简化match无穷匹配规则问题
fn let_if_test() {
    let x = Some(8);
    if let Some(3) = x {
        println!("====");
    }
}
fn option_test_v2() {
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
}
//Optional
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        Some(i) => Some(i + 1),
        None => None
    }
}
//match
fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Dime => 2,
        Coin::Quarter(state) => {
            println!("{:#?}", state);
            3
        }
        Coin::Nickel => 4
    }
}
#[derive(Debug)] // 这样可以立刻看到州的名称
enum State {
    Alabama,
    Alaska,
}
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(State),
}
//Option<T> 枚举是如此有用以至于它甚至被包含在了 prelude 之中,你不需要将其显式引入作用域
fn option_test() {
    let some_number = Some(5);
    let some_string = Some("a string");
    let absent_number: Option<i32> = None;
}
fn enum_test() {
    let v4 = IpAddrKind::V4(127, 0, 0, 1);
    let v6 = IpAddrKind::V6(String::from("::1"));
    v6.check();
}
//枚举
enum IpAddrKind {
    V4(u8, u8, u8, u8), //元组
    V6(String),
}
//枚举也可以定义方法
impl IpAddrKind {
    fn check(&self) {
        println!("check...");
    }
}
fn related_function() {
    let phone = Phone::new(String::from("xx"), String::from("xx"));
    println!("{:#?}", phone)
}
//关联函数(像String::from 一样,与普通方法区别是第一个参数不是&self),有点像java中的静态方法
#[derive(Debug)]
struct Phone {
    color: String,
    shape: String,
}
impl Phone {
    //注意:第一个参数不是&self
    fn new(color: String, shape: String) -> Phone {
        Phone { color, shape }
    }
}
fn tangle_area_test() {
    let rectangle = Rectangle { width: 30, height: 30 };
    println!("area:{}", tangle_area(&rectangle));
    println!("{}>>", rectangle.area());
}
//借用结构体,但所有权不会转移
fn tangle_area(rectangle: &Rectangle) -> u32 {
    println!("{:#?}", rectangle);
    rectangle.width * rectangle.height
}
#[derive(Debug)] //支println!输出
struct Rectangle {
    width: u32,
    height: u32,
}
//结构体方法(注意方法和函数不一样,方法是附加在结构体上的,函数是独立存在)
impl Rectangle {
    //&self是 self:&Self 的缩写,之所以用& 表示这个方法借用了 Self 实例,而不获取所有权
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
//单元结构体(类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用)
struct Car;
//元组结构体
struct Laptop(String, u8);
fn tuple_struct() {
    let color = Color(255, 255, 255);
}

//元组结构体
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn build_user(active: bool, username: String) -> User {
    //入参名称与结构体变量名相同可以直接用
    User { active, username, email: String::from(""), sign_in_count: 11 }
}
fn struct_define() {
    //注意整个实例必须是可变的;Rust 并不允许只将某个字段标记为可变
    let mut user = User { active: true, username: String::from("John"), email: String::from("John.qq.com"), sign_in_count: 12 };
    user.username = String::from("jack");
    println!("{}", user.sign_in_count);
    //复用一个struct的内容得到一个新的struct(注意user 的所有权已转移)
    let user1 = User { active: false, ..user }; //..user 必须在最后
    println!("{}", user1.active);
    //已借用(所有权已转移)
    //println!("{}",user.username);
}
struct User {
    active: bool,
    username: String, //不能使用&str代替 String,要使用带所有权的类型
    email: String,
    sign_in_count: i32,
}
//slice 没有所有权(和基本类型一样),slice=&str
fn slice_simple() {
    let s = String::from("Hello, world!");
    //它不是对整个 String 的引用,而是对部分 String 的引用
    let hello = &s[0..5];
    let world = &s[6..11];
    let slice = &s[3..];
    let slice = &s[..3];
    let slice = &s[..];
    //字符串字面量就是slice
    let str = "Hello, world!";
    println!("{}", String::from(&str[0..3]));
}
fn slice(s: &String) -> i32 {
    let byt = s.as_bytes();
    for (i, &item) in byt.iter().enumerate() {
        if item == b'o' {
            return i as i32;
        }
    }
    byt.len() as i32
}
//所有权(重要)
/*
1.Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
2.值在任一时刻有且只有一个所有者。
3.当所有者(变量)离开作用域,这个值将被丢弃。
*/
fn ownership() {
    let s = String::from("hello");
    take_ownership_str(s);
    //s.push_str(", world");//不可以使用,因为所有权已经转移,对象已释放

    let x = 10;
    take_ownership_int(x);
    //可以继续使用,因为x 是copy 的,所有权未发生变化
    println!("{}", x);

    //take_ownership_str方法调用后 z可以继续使用
    let mut z = String::from("hello");
    //对象的引用作为参数而不是获取值的所有权
    // & 符号就是 引用,它们允许你使用值但不获取其所有权(也称为借用)
    take_ownership_borrow(&z);
    //所有权有效
    z.push_str(", world");
    println!("{}", z);

    //允许函数将改变它所借用的值
    let mut h = String::from("hello");
    take_ownership_borrow_success(&mut h);
    println!("{}", h);

    //可以多次借用
    let mut k = String::from("hello");
    let k1 = &mut k;
    let k2 = &mut k;
    println!("{}", k2);
}
fn take_ownership_str(s: String) {
    println!("{}", s);
} // 这里,s 移出作用域并调用 `drop` 方法。占用的内存被释放

fn take_ownership_borrow(s: &String) {
    println!("{}", s);
    //s.push_str(", world");//只是借用,没有所有权,不能修改
} // 这里,s 离开了作用域。但因为它并不拥有引用值的所有权,所以什么也不会发生

fn take_ownership_borrow_success(s: &mut String) {
    println!("{}", s);
    //可以改变所有权的值
    s.push_str(", world");
}

fn take_ownership_int(i: i32) {
    println!("{}", i);
} // 这里,i 移出作用域。不会有特殊操作

//作用域
fn scope() {
    //变量离开作用域后,Rust 自动调用 drop 函数并清理变量的堆内存
    {
        //s无效
        let s = "hello"; //s有效
        println!("{}", s); //s有效
    }
    //s 无效

}
fn variable_copy() {
    //值拷贝,栈中会压入2个1
    let x = 1;
    let y = x;
    println!("the value of y is : {}", y);

    //引用拷贝
    let str1 = String::from("hello");
    //指向地址的指针,而非复制一份数据
    let str2 = str1;
    //如果这时输出str1 则会报错,因为在 let str2 = str1 之后,Rust 认为 str1 不再有效. 否则会报错 value borrowed here after move
    println!("the value of str2 is : {}", str2);

    //深拷贝,hello 会被复制一份(不存在借用,也不会报value borrowed here after move)
    let str3 = String::from("hello3");
    let str4 = str3.clone();
    println!("the value of str3 is : {}", str3);
    println!("the value of str4 is : {}", str4);
}
fn string_type() {
    /*
    String 类型的数据存储在堆上(基本类型存在栈上).
    String 是拥有所有权的可变字符串类型,适用于需要修改的场景。
    str 是不可变的字符串切片类型,通常用于只读场景和函数参数传递。由于 str 没有所有权,Rust 需要一个指向内存的引用来管理其生命周期。
    不能直接使用 str 类型,因为它是一个固定大小类型,不能独立存在,通常都使用 &str
     */
    //字符串字面量(就是slice类型)
    let str: &str = "hello1";
    println!("{}", str);
    //也可以
    let str3: &str = &String::from("hello2");
    println!("{}", str3);
    //拥有所有权的存储在堆上的字符串对象
    let str1 = String::from("hello3");
    println!("{}", str1);
    //String 是可以变的
    let mut str4 = String::from("hello4");
    //不可以直接str4 = "xx";因为String 是分配在堆上的
    str4.push_str(" world!");
    println!("{}", str4);

    //字符串拼接
    let str5 = format!("{}-{}", str1, str4);
    println!("{}", str5);
}
//循环
fn foreach() {
    let mut count = 0;
    loop {
        println!("loop");
        count += 1;
        if count == 5 {
            break;
        }
    }
    //循环返回值
    let result: &str = loop {
        if count == 5 {
            break "success";
        }
    };
    println!("{}", result);

    while count < 10 {
        println!("{}", count);
        count += 1;
    }

    let arr = [1, 2, 3, 4, 5];
    for x in arr {
        println!("{}", x)
    }
    //range 区间
    //正序
    //for x in (0..10) {
    //倒序
    for x in (0..10).rev() {
        println!("{}", x);
    }
}
//条件表达式
fn condition_express(count: i32) {
    if count == 10 {
        println!("condition express");
    } else if count != 11 {
        println!("condition not");
    } else {
        println!("condition not");
    }
    // if else 的返回值类型必须相同
    let condition: i32 = if count == 12 {
        5
    } else { 6 };
}
//function with output params
fn return_express_function() -> i32 {
    let x: i32 = 1;
    x + 2
}

//function with input params
fn other_function(x: i32) {
    println!("This is the other function-snake case!{}", x);

    //定义一个变量,它的值基于代码块来获得
    let x = {
        let y = 10;
        y + 1;
    };
}
//数据类型
fn data_type() {
    //类型转换(转换的目标根据具体声明的类型,如果不指定类型将编译报错)
    let v: u32 = "9".parse().expect("Not valid");
    println!("{}", v);

    //4 个基本的标量类型:整型、浮点型、布尔型和字符 (整型默认是 i32)
    //有符号和无符号表示数字能否取负数

    //8 位 有符号 长度 -128 ~ 127
    let i8: i8 = 1;
    //8 位 无符号 长充 0 ~ 255
    let u8: u8 = 1;
    //16 位 有符号
    let i16: i16 = 2;
    //16 位 无符号
    let u16: u16 = 2;
    //32 位 有符号
    let i32: i32 = 3;
    //32 位 无符号
    let u32: u32 = 3;
    //64 位 有符号
    let i64: i64 = 4;
    //64 位 无符号
    let u64: u64 = 5;

    //byte
    let byt = b'A';

    //float/double
    let f32: f32 = 1.0;
    let f64 = 2.0;

    //bool
    let flag: bool = true;

    //char
    let ch: char = 'A';

    //tup 元组
    let tup_vals: (i32, u64, f32) = (-1, 12, 6.9);
    println!("{}, {}, {}", tup_vals.0, tup_vals.1, tup_vals.2);
    let (x, y, z) = tup_vals;
    println!("{} {} {}", x, y, z);

    //array
    let arr = [1, 2, 3, 4, 5];
    let arr_other: [i32; 3] = [1, 2, 3];
    let arr_zero = [0; 3];
}
//变量定义
fn variables() {
    let x = 5;
    println!("The value of x is: {}", x);
    //编译不通过,默认变量是不可变的
    //x = 6;

    //可变的变量
    let mut y = 5;
    println!("The value of y is: {}", y);
    y = 6;
    println!("The value of y is: {}", y);

    //常量
    const PI: f64 = 3.14;
    println!("The value of PI is: {}", PI);

    //遮蔽(同名变量) shadow
    let z = 6;
    let z = z + 1;
    println!("The value of z is: {}", z);

    //遮蔽(同名变量不同类型) shadow
    let spaces = "   ";
    let spaces = spaces.len();
    println!("The value of spaces is: {}", spaces);
}
//猜字游戏
fn guess() {
    println!("Guess the number!");
    let secret_number = rand::thread_rng().gen_range(1..11); // 或 1..=10
    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        //& 表示一个对象的引用,引用默认是不可变的,所以需要加上 mut
        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line.");

        //遮蔽 (shadow)
        let guess: u32 = match guess.trim().parse()
        {
            Ok(num) => num,
            Err(_) => continue
        };

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}