首页 > 其他分享 >rus语法 1

rus语法 1

时间:2023-03-12 21:57:20浏览次数:43  
标签:rs self 语法 let println rus my fn

打印

#[derive(Debug)] // 有了这才能通过 {:?} {:#?} debug
struct Complex {
    real: f64,
    imag: f64,
}
impl fmt::Display for Complex {
    // 默认泛型容器没有实现,要手动实现才能使用 {} 打印
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "x: {}, y: {}", self.real, self.imag)
    }
}

/// this is doc comment
/// ...
fn print() {
    /* format!();print!();println!();eprint!();eprintln!(); */
    let variable = 1;
    println!("{} 为占位符", variable);
    println!(
        "named argument: {subject} {verb} {object}",
        subject = "A",
        verb = "hava",
        object = "ball"
    );

    println!("Base 10:               {}", 69420); //69420
    println!("Base 2 (binary):       {:b}", 69420); //10000111100101100
    println!("Base 8 (octal):        {:o}", 69420); //207454
    println!("Base 16 (hexadecimal): {:x}", 69420); //10f2c
    println!("Base 16 (hexadecimal): {:X}", 69420); //10F2C

    println!(
        "打印详细信息:{o} {o:?} {o:#?}",
        o = Complex {
            real: 1.1,
            imag: 3.2
        }
    ); // 默认不可打印,实现 Debug 接口才可
}
// 可打印列表
struct List(Vec<i32>);

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let vec = &self.0;

        write!(f, "[")?; // ? 用于处理 Result 返回值,出错则直接结束函数返回error,否则继续

        for (i, ele) in vec.iter().enumerate() {
            if i != 0 {
                write!(f, ",")?;
            }
            write!(f, "{} : {}", i, ele)?;
        }

        write!(f, "]")
    }
}

更多格式见:https://doc.rust-lang.org/std/fmt/

基本

操作符类似C

fn main() {
    // Integer addition
    println!("1 + 2 = {}", 1u32 + 2);

    // Integer subtraction
    println!("1 - 2 = {}", 1i32 - 2);
    // TODO ^ Try changing `1i32` to `1u32` to see why the type is important

    // Short-circuiting boolean logic
    println!("true AND false is {}", true && false);
    println!("true OR false is {}", true || false);
    println!("NOT true is {}", !true);

    // Bitwise operations
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    println!("1 << 5 is {}", 1u32 << 5);
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);

    // Use underscores to improve readability!
    println!("One million is written as {}", 1_000_000u32);
}

tuple

fn fun() {
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    let matrix = Matrix(1.1f32, 1.2f32, 1.3, 1.4);
    println!("Matrix:\n{}", matrix);
    println!("Transpose:\n{}", transpose(matrix));
}

struct Matrix(f32, f32, f32, f32);
impl fmt::Display for Matrix {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "( {} {} )\n( {} {})", self.0, self.1, self.2, self.3)
    }
}

fn transpose(matrix: Matrix) -> Matrix {
    let e0 = matrix.0;
    let e1 = matrix.1;
    let e2 = matrix.2;
    let e3 = matrix.3;

    Matrix(e0, e1, e3, e2)
}

切片:占用两个字,一个为指向数据的指针,另一个为长度。

fn analyze_slice(slice: &[i32]) {
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}
fn fun() {
    let arr1: [i32; 5] = [1,2,3,4,5];
    let arr2: [i32; 10] = [0; 10];
    println!("{} {} {}", arr1[0], arr2.len(), std::mem::size_of_val(&arr1));

    // 数组被自动借用为切片,空切片:&[]
    analyze_slice(&arr1);
    analyze_slice(&arr2[3 .. 6]);

    // 使用 get 方法得到被 Option 包裹的数据,可以使用 match 或 expect 方法处理
    for i in 0..arr2.len() + 1 {
        match arr2.get(i) {
            Some(val) => println!("{}: {}", i, val),
            None => println!("over the bound!"),
        }
    }
}

结构体 枚举类型 别名 静态变量

结构体

// 无字段可用于泛型
struct Unit;

// struct tuple 即命名数组
struct Pair(i32, i32);

#[derive(Debug)]
struct Point {
    x: f32,
    y: f32,
}
struct Rectangle {
    top_left: Point,
    bottom_right: Point,
}
impl Rectangle {
    fn area(&self) -> f32 {
        (self.bottom_right.x - self.top_left.x) * (self.bottom_right.y - self.top_left.y)
    }
}

fn square(p: Point, l: f32) -> Rectangle {
    Rectangle {
        bottom_right: Point { // 注意这里要在 top_left 之前声明,否则p被 borrowed ,就无法再使用
            x: p.x + l,
            y: p.y + l,
        },
        top_left: p,
    }
}

fn fun() {
    let point1 = Point{x:1.1, y:1.2};
    
    // 使用结构体更新语法引用其他结构体数据
    let point2 = Point{x:2.1, ..point1};

    // destructure
    let Point { x: left_edge, y: top_edge } = point2;

    let _rec = Rectangle {
        top_left: Point { x: left_edge, y: top_edge },
        bottom_right: point1,  // point1 be borrowed
    };
}

 枚举类型,use 与命名空间

enum Event {
    PageLoad,       // unit struct
    KeyPress(char), // struct tuple
    Paste(String),
    Click { x: i64, y: i64 }, // struct
}
fn inspect(event: Event) {
    // 使用 use 后无需使用命名空间
    use crate::Event::{KeyPress, PageLoad}; // use create::Event::*;
    match event {
        PageLoad => println!("page loaded"),
        KeyPress(c) => println!("pressed '{}'.", c),
        Event::Paste(s) => println!("pasted \"{}\".", s),
        Event::Click { x, y } => {
            println!("clicked at x={}, y={}.", x, y);
        }
    }
}
#![allow(dead_code)]

use std::fmt::Display;
use crate::List::*;

enum List<T: Display> {
    Cons(T, Box<List<T>>),
    Nil,
}
impl<T: Display> List<T> {
    fn new() -> List<T> {
        List::Nil
    }
    // self 代表对象,所有权会移交
    fn prepend(self, elem: T) -> List<T> {
        List::Cons(elem, Box::new(self))
    }
    // &self 代表引用,所有权不会移交
    fn len(&self) -> u64 {
        match self {
            List::Cons(_, tail) => 1 + tail.len(),
            Nil => 0,
        }
    }
    fn stringify(&self) -> String {
        match self {
            List::Cons(head, tail) => {
                format!("{}, {}", head, tail.stringify())
            }
            List::Nil => {
                format!("Nil")
            }
        }
    }
}

fn main() {
    let mut list = List::<i32>::new();

    list = list.prepend(1);
    list = list.prepend(2);
    list = list.prepend(3);

    println!("{}", list.stringify()); // 3, 2, 1, Nil
}

enum 类C用法

// enum with implicit discriminator (starts at 0)
enum Number {
    Zero,
    One,
    Two,
}

// enum with explicit discriminator
enum Color {
    Red = 0xff0000,
    Green = 0x00ff00,
    Blue = 0x0000ff,
}

fn main() {
    // `enums` can be cast as integers.
    println!("zero is {}", Number::Zero as i32);
    println!("one is {}", Number::One as i32);

    println!("roses are #{:06x}", Color::Red as i32);
    println!("violets are #{:06x}", Color::Blue as i32);
}

 别名

type AliasType = SomeType;

 静态变量

  • const:不可变,常用
  • static:可能是 mut 类型,被推断为静态生命周期 'static,访问修改都是 unsafe 的

类型转换

使用 use 显现类型转换,rust 没有隐式类型转换

let decimal = 65.4321_f32;
let integer = decimal as u8;
let char = integer as char;

// 300.0 as u8 is 255
println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
// -100.0 as u8 is 0
println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
// nan as u8 is 0
println!("   nan as u8 is : {}", f32::NAN as u8);

 内置类型转换 From Into

let my_str = "hello";
let my_string = String::from(my_str);

struct Number {
    value: i32,
}
impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

let num = Number::from(30);

let int = 5;
let num: Number = int.into();

try_from / try_into 返回一个 Result

#[derive(Debug, PartialEq)]
struct EvenNumber(i32);

impl TryFrom<i32> for EvenNumber {
    type Error = ();

    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value % 2 == 0 {
            Ok(EvenNumber(value))
        } else {
            Err(())
        }
    }
}

使用 Display 转为 String

使用字符串实现的 FromStr 接口的 parse 方法将 String 转为其他类型

let parsed: i32 = "5".parse().unwrap();
let turbo_parsed = "10".parse::<i32>().unwrap();

控制流

let x = if n < 100.0 {
    1
}  else if n < 10.0 {
    2
} else {
    3
};

// loop 死循环 可搭配 break continue
fn main() {
    'outer: loop {
        println!("Entered the outer loop");
        'inner: loop {
            println!("Entered the inner loop");
            // This breaks the outer loop
            break 'outer;
        }
        println!("This point will never be reached");
    }
    println!("Exited the outer loop");
}
/*
Entered the outer loop
Entered the inner loop
Exited the outer loop
*/

let result = loop {
    counter += 1;

    if counter == 10 {
        break counter * 2;
    }
};

while 搭配布尔语句

for n in 1..101 {

}
for n in 1..=100 {

}

let names = vec!["Bob", "Frank", "Ferris"];

// 元素被借用,循环后可再用
for name in names.iter() {
    match name {
        &"Ferris" => println!("There is a rustacean among us!"),
        _ => println!("Hello {}", name),
    }
}

// 元素可以被原地修改,循环后可用
for name in names.iter_mut() {
    *name = match name {
        &mut "Ferris" => "There is a rustacean among us!",
        _ => "Hello",
    }
}

// 元素被移动,循环后不可再用
for name in names.into_iter() {
    match name {
        "Ferris" => println!("There is a rustacean among us!"),
        _ => println!("Hello {}", name),
    }
}

 match destructuring

match number {
    1 => println!("One!"),
    2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
    13..=19 => println!("A teen"),
    _ => println!("Ain't special"),  // 处理其他情况,不可缺少
}

let arr = 数组或切片;
match arr {
    [0, second, third] => print!(),
    [1, _, third] => print!(),
    // 绑定一些忽略一些
    [2, second, ..] => print!(),
    // 将剩余的绑定到数组或切片
    [3, second, tail @ ..] => print!(),
    [first, middle @ .., last] => print!(),
}
match tuple {
    (0, x, y) if x > 0 => println!(""), // 分支守卫
    (3, .., 4) => println!(""),
    _ => print!(),
}
let reference = &4;
match reference {
    &val => print!("这里变量被解引用"),
}

match value {
    ref r => print!("创建新引用"),
}

match value {
    ref mut m => print!("可变引用"),
}

match value {
    Foo { x: 1, y: a} => print!(""),
    Foo { x: a, y: 1} => print!(""),
}
// 使用 @ 绑定对象
match age() {
    0 => xx,
    n @ 1 ..= 12 => xx,
    n @ 13 ..= 19 => xx,
    n => xx,
}

闭包

fn main() {
    /****************** borrow / reference *******************/
    let mut outer_var = 42;
    let closure_annotated = |i: i32| -> i32 { i + outer_var }; // immutrably borrow
    let mut closure_inferred = |i| outer_var += i; // mutably borrow

    closure_inferred(1); // 有了这句使用后才能推断出闭包类型
    // println!("{}", outer_var); // 在其他借用没有结束时借用,会报错
    closure_inferred(1);
    println!("{}", outer_var); // 此处不会报错

    /****************** move *******************/
    let movable = Box::new(3);
    let consume = || {
        println!("`movable`: {:?}", movable);
        std::mem::drop(movable); // drop函数需要传入move值,此处发生 move
    };

    consume();
    // consume(); 因为变量只能move一次,所以再次调用会报错
    
    let contains = move |needle| haystack.contains(needle);  // 在 | 前使用 move 关键字,强制move
}

当闭包作为函数参数时,需要用接口指明 参数为闭包 还有 闭包的参数捕获方式:Fn FnMut FnOnce。权限逐渐变严格,FnOnce接收更宽松的两类接口,FnMut也可传入Fn接口

fn apply<F>(f: F)
where
    F: FnOnce(),
{
    f();
}
fn main() {
    use std::mem;

    let mut w = "hello".to_owned(); // create owned data
    let f = || {
        mem::drop(w);
    };
    apply(f); // 函数f的参数是 move 来的,apply中必须要用 FnOnce
}

当闭包作为输出时要用 impl 和接口指明类型,同时还要用 move 将捕获变量转移出,否者在函数结束后引用变量销毁。

fn create_fn() -> impl Fn() {
    let text = "Fn".to_owned();

    move || println!("This is a: {}", text)
}

fn create_fnmut() -> impl FnMut() {
    let text = "FnMut".to_owned();

    move || println!("This is a: {}", text)
}

fn create_fnonce() -> impl FnOnce() {
    let text = "FnOnce".to_owned();

    move || println!("This is a: {}", text)
}

fn main() {
    let fn_plain = create_fn();
    let mut fn_mut = create_fnmut();
    let fn_once = create_fnonce();

    fn_plain();
    fn_mut();
    fn_once();
}

函数式编程

// Functional approach 所有奇数的平方
let sum_of_squared_odd_numbers: u32 =
    (0..).map(|n| n * n)                             // All natural numbers squared
    .take_while(|&n_squared| n_squared < upper) // Below upper limit
    .filter(|&n_squared| is_odd(n_squared))     // That are odd
    .sum();                                     // Sum them
println!("functional style: {}", sum_of_squared_odd_numbers);

Diverging functions

不会正常返回的函数

fn foo() -> ! {
    panic!("This call never returns.");
}

#![feature(never_type)]

fn main() {
    let x: ! = panic!("This call never returns.");
    println!("You will never see this line!");
}

fn main() {
    fn sum_odd_numbers(up_to: u32) -> u32 {
        let mut acc = 0;
        for i in 0..up_to {
            // Notice that the return type of this match expression must be u32
            // because of the type of the "addition" variable.
            let addition: u32 = match i%2 == 1 {
                // The "i" variable is of type u32, which is perfectly fine.
                true => i,
                // On the other hand, the "continue" expression does not return
                // u32, but it is still fine, because it never returns and therefore
                // does not violate the type requirements of the match expression.
                false => continue,
            };
            acc += addition;
        }
        acc
    }
    println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9));
}

模块

模块默认都是私有的,使用 pub 关键字修饰后其他模块才可见。
结构体的字段与方法也都默认私有。

mod my_mod {
    fn private_fun(){}
    pub fn public_fun(){}

    pub mod nested {
        pub(in crate::my_mod) fn public_in_given_mod(){}
        pub(super) fn public_in_super_super_mod(){}
        pub(crate) fn same_as_private(){}
    }
}

use 声明

use crate::deeply::nested::{
    my_first_function,
    my_second_function,
    AndATraitType
};

use deeply::nested::function as other_function;

super & self

mod mod1 {
    pub(super) fn fun1() {
        println!("fun1");
    }
}

mod mod2 {
    mod mod3 {
        pub fn fun2() {
            println!("fun2");
        }
    }
    fn fun() {
        self::mod3::fun2();
        super::mod1::fun1();
    }
}
$ tree .
.
├── my
│   ├── inaccessible.rs    my::nested::xxx
│   └── nested.rs          my::nested::xxx
├── my.rs                     my::xxx
└── split.rs

在 split.rs 文件头部输入 mod my; 使 my.rs 内部自动创建模块my并插入 my.rs 的内容
在 my.rs 文件头部插入 mod inaccessible; 和 pub mod nested;

|--main.rs                       通过 pub mod util; 引入util模块
|--util.rs
|--util/
       |--mod.rs
       |--math.rs
注意:utils.rs 和 util/mod.rs 内容都是util模块下的内容;二者同时存在会冲突

Cargo & Crates

crates.io: Rust Package Registry https://crates.io

cargo new foo       # A binary
cargo new --lib bar # A library
cargo build
cargo run

.
├── bar
│   ├── Cargo.toml
│   └── src
│       └── lib.rs   # 库
│       └── main.rs  # 可执行文件
└── foo
    ├── Cargo.toml
    └── src
        └── lib.rs   # 库
        └── main.rs  # 可执行文件

一个 crate 包中生成多个可执行文件

foo
├── Cargo.toml
└── src
    ├── main.rs
    └── bin
        └── my_other_bin.rs
# cargo build                      生成默认文件
# cargo build --bin my_other_bin   指定可执行文件,文件名为 my_other_bin

Attributes

修饰crate、条件编译、格式化、链接、单元测试、压力测试、类宏属性

#![allow(dead_code)] // #! 开头,修饰crate


// 三种修饰 mod fn 的格式
#[attribute = "value"]
#[attribute(key = "value")]
#[attribute(value)]

cfg 代指 configure,在使用 rustc 编译时可以通过 --cfg 指定

  • #[cfg(...)] 条件编译
  • cfg!(...) 在运行时返回布尔值
#[cfg(target_os = "linux")]
fn are_you_on_linux() {
    println!("You are running linux!");
}
#[cfg(not(target_os = "linux"))]
fn are_you_on_linux() {
    println!("You are *not* running linux!");
}

fn main() {
    are_you_on_linux();
    println!("Are you sure?");
    if cfg!(target_os = "linux") {
        println!("Yes. It's definitely linux!");
    } else {
        println!("Yes. It's definitely *not* linux!");
    }
}

 

标签:rs,self,语法,let,println,rus,my,fn
From: https://www.cnblogs.com/zhh567/p/17201586.html

相关文章

  • Rust 3
    https://www.jetbrains.com.cn/rust/https://yew.rs/zh-Hans/docs/getting-started/introductionrustuptargetaddwasm32-unknown-unknown#notethatthismightta......
  • Rust 2
    ThisisthesourcecodeofthetraditionalHelloWorldprogram.//Thisisacomment,andisignoredbythecompiler.//Youcantestthiscodebyclickingthe......
  • Rust 1
    curl--proto'=https'--tlsv1.2-sSfhttps://sh.rustup.rs|shRustisamodernsystemsprogramminglanguagefocusingonsafety,speed,andconcurrency.Itac......
  • OpenGL学习(十)-- 着色语言 GLSL 语法介绍
    我的OpenGL专题学习目录,希望和大家一起学习交流进步!OpenGL学习(一)--术语了解OpenGL学习(二)--Xcode搭建OpenGL环境OpenGL学习(三)--OpenGL基础渲染OpenGL学习(......
  • OpenGL笔记十四:GLSL语法
    前言期待您移步上篇:OpenGL笔记十三:GLSL加载纹理颠倒六种方案概述GLSL全称OpenGLShadingLanguage,是用来在OpenGL中着色编程的语言,即开发人员写的自定义程序代码......
  • GLSL基础语法介绍
    GLSL(OpenGL着色语言OpenGLShadingLanguage)语法跟C语言很类似,在可编程管线中我们必须要纯手写顶点和片源着色器,这里就要求必须使用GLSL,自行编译,链接,使用,本片文章介绍......
  • GLSL语法简单总结
    1、变量类型基础类型:bool,int,uint,float,double向量类型:vecN,bvecN,ivecN,uvecN,dvecNN表示向量维数(N=1,2,3,4)。含前缀b为bool向量,i为int向量,u为uint向量,d为double向量,不含......
  • Day02-ES6新语法
    ES6新语法糖(初级)1什么是ES6JS语法分三块ECMAScript:基础语法BOM浏览器对象historylocationwindowDOM文档对象document编程语言JavaScript是ECMAScr......
  • Day03-vue&es6新语法(高级)
    vue的学习网站:https://www.runoob.com/vue2/vue-tutorial.html回顾#1.ajax:完成页面局部刷新,异步交互。#2.axios发送ajax异步请求: 1)引入库<scriptsrc=""></script>......
  • BitBake使用攻略--BitBake的语法知识二
    目录写在前面1.BitBake中的任务2.任务配置2.1依赖2.1.1内部任务间的依赖2.1.2不同菜谱下的任务间依赖2.1.3运行时态下的依赖2.1.4递归依赖2.1.5任务间的依赖2.2事......