LearningOS/rcore_step_by_step

HCZ-关于Rust学习的流水账

Closed this issue · 0 comments

练习三代码:

fn apply<F>(mut f: F) where
    F: FnMut() {
    f();
}

fn main() {
    let mut x = 7;
    let print = || { x+=2; println!("{}", x);};
    apply(print);
    x=8;
    println!("x is {}",x);
}

因为这里调用的X的缘故,闭包类型需为FnMut

7.19日0点54分更新:
今天在看《Rust编程之道》的时候看到有这么一句话:“Copy的行为是一个隐式的行为,开发者不能重载Copy行为,他永远都是一个简单的位复制。”

这让我联想到了之前的《关于练习的流水账》(见 #14 )提到的,由于审题错误而尝试去做的重载copy trait,当时给出的error是list不在scope中,使得我以为如果可以成功将vec转为结构体后是可以实现copy trait的。

那么问题来了:如何理解“Copy trait永远都是一个简单的位复制”这句话呢

7.18:
首先我必须先给我的助教道歉,很抱歉由于我的粗心给助教带来了麻烦,也非常感谢助教对我包容。

这次问题主要是出在练习2上,本题考察的是“如何用引用表示不可copy的类型”,线索处于函数的签名中,源代码fn largest<T: PartialOrd + Copy>(list: &[T]) -> T 中,明确说明函数的返回类型为T,但接下来在需更改的函数签名为fn largest<T: PartialOrd >(list: &[T]) -> &T,这是可以看到返回类型是&T,可以说是一个非常强烈的暗示了!

然而没有仔细读题的我看成了fn largest<T: PartialOrd>(list: &[T]) -> T 误把出题意图理解成了“重构copy trait”(请原谅我最近写trait写傻了),因为“像 i32 和 char 这样的类型是已知大小的并可以储存在栈上,所以他们实现了 Copy trait。当我们将 largest 函数改成使用泛型后,现在 list 参数的类型就有可能是没有实现 Copy trait 的, 这意味着我们可能不能将 list[0] 的值移动到 largest 变量中。所以我们需要重构泛型copy trait”,于是我的思考方向就是重构泛型copy trait,然后是两个思路:1)最简单的重构泛型 2)在堆上开辟空间 。

我一开始采用的是思路1,在完成了自定义的copy_self_define trait面临的问题是:由于trait作为方法的聚合,其旗下的方法必将也必须作用于一个struct上(这里理解可能有错,欢迎大家指出),也就是说,如果我想让我自定义的copy_self_define trait生效,list作为一个vec是不可行的,只有将list转为一个struct,copy_self_define trait才能有效执行。也就是说接下来我们需要用struct重构vec。但vec作为Rust自己定义的一个类型,无法搜寻到Rust的源码可以参考,也无从知道如何实现通过Struct稳定安全的重构vec的方法,思路1陷入困境。困境则意味着思路方向出了问题。

我把思路和问题的解决过程做了一个PDF向助教询问,在得到助教答复后比对代码,发现千算万算,还是没有算到函数签名头上。但无论如何,这次练习2给我带来的教训和意义是深刻的。征服trait之路,任重道远啊。

附上练习2的代码:

fn largest<T: PartialOrd >(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

fn main() {
    let number_list = vec![34, 50, 25, 99, 65];
    let result = largest(&number_list);
    println!("The largest number is {}", result);
    let char_list = vec!['y', 'm', 'z', 'q'];
    let result = largest(&char_list);
    println!("The largest char is {}", result);
}

练习1代码:

use std::env;
use std::fs;
use std::error::Error;
use std::process;


fn main()
{
    let store_sp: Vec<String> = env::args().collect();
    let value_info:config = config::new(&store_sp);
    let contents = fs::read_to_string(value_info.file_name).expect("hello world");
    println!("{}\n",value_info.author_name);
    println!("{}",contents);
    println!("{:?}",search(&value_info.query,&contents.to_string()));
}

struct config{
    file_name:String,
    author_name:String,
    query:String,
}

impl config{
    fn new(ssp:&[String])->config{
        let file_name = ssp[1].clone();
        let author_name = ssp[2].clone();
        let query = ssp[3].clone();
        config{
            file_name,
            author_name,
            query,
        }
    }
}

fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();
    for line in contents.lines() {
        if line.contains(query) {
                results.push(line);
        }
    }
    results
}