csv - 如何在结构回调中使用外部对象,例如将数据附加到 CSV 时?

标签 csv struct callback rust

我的理解是在范围外创建的对象在范围内可用(因此允许诸如阴影之类的东西),但在这种情况下它似乎不起作用:

extern crate csv;
extern crate rand;

use rand::Rng;
use std::path::Path;
use std::time::SystemTime;

#[derive(Debug)]
struct Event {
    time: SystemTime,
    value: u32,
}

impl Event {
    fn new(t: SystemTime, n: u32) -> Event {
        Event {
            time: SystemTime,
            value: n,
        }
    }
}

struct Process;

impl Process {
    fn new() -> Process {
        Process {}
    }

    fn start(&self) {
        loop {
            let now = SystemTime::now();
            let random_number: u32 = rand::thread_rng().gen();
            let event = Event::new(now, random_number);
            self.callback(event);
        }
    }

    fn callback(&self, event: Event) {
        println!("{:?}", event);
        wtr.write_record(&event).unwrap();
        wtr.flush().unwrap();
    }
}

fn main() {
    let file_path = Path::new("test.csv");
    let mut wtr = csv::Writer::from_path(file_path).unwrap();

    let process: Process = Process::new();
    process.start();
}

错误是:

error[E0423]: expected value, found struct `SystemTime`
  --> src/main.rs:17:19
   |
17 |             time: SystemTime,
   |                   ^^^^^^^^^^ constructor is not visible here due to private fields

error[E0425]: cannot find value `wtr` in this scope
  --> src/main.rs:41:9
   |
41 |         wtr.write_record(&event).unwrap();
   |         ^^^ not found in this scope

error[E0425]: cannot find value `wtr` in this scope
  --> src/main.rs:42:9
   |
42 |         wtr.flush().unwrap();
   |         ^^^ not found in this scope

如何从 Process 的回调函数中将数据(Event)附加到 CSV 文件?

最佳答案

强烈鼓励您回去重新阅读The Rust Programming Language ,特别是关于functions的章节.此代码似乎显示了围绕函数工作方式的整个模型的基本问题。

例如,代码试图在函数 callback 中使用变量 wtr,而不是直接或间接传入它。

如果这样的代码有效1,程序员可能会讨厌与这种语言打交道,因为几乎不可能告诉什么在哪里wtr 甚至来自。

解决方案很简单:将一段代码需要的任何值传递给该代码。这样就很容易(或更容易)分辨出值(value)的来源。有多种途径可以发挥作用。

  1. 将参数传递给 callback 方法:

    use std::io::Write;
    
    impl Process {
        fn start<R>(&self, wtr: &mut csv::Writer<R>)
        where
            R: Write,
        {
            loop {
                // ...
                self.callback(wtr, event);
            }
        }
    
        fn callback<R>(&self, wtr: &mut csv::Writer<R>, event: Event)
        where
            R: Write,
        {
            // ...
        }
    }
    
    fn main() {
        // ...
        process.start(&mut wtr);
    }
    
  2. 将参数传递给构造函数并将其保存在结构中:

    use std::io::Write;
    
    struct Process<'a, R>
    where
        R: Write + 'a,
    {
        wtr: &'a mut csv::Writer<R>,
    }
    
    impl<'a, R> Process<'a, R>
    where
        R: Write,
    {
        fn new(wtr: &'a mut csv::Writer<R>) -> Self {
            Process { wtr }
        }
    
        // ...
    
        fn callback(&self, event: Event) {
            // ...
            self.wtr.write_record(event).unwrap();
            self.wtr.flush().unwrap();
        }
    }
    
    fn main() {
        // ...
        let process = Process::new(&mut wtr);
    }
    

代码在如何使用 CSV 库方面还有其他问题,我忽略了这些问题,因为它们与您的问题无关。我鼓励您从一段更简单的代码开始,让它运行起来,然后再让它变得更复杂。这样一开始您只会处理更简单的错误。

了解了函数的基本用法后,您可能希望了解 closures .这些允许您从外部范围“捕获”变量并将它们传入(使用与上述相同的两种方法),而无需处理特定数量或类型的变量。

objects created outside of the scope are available inside the scope

对于单个函数来说是这样。它不适用于跨函数。

hence things such as shadowing allowed

阴影与范围无关。您可以在同一范围内进行阴影:

let a = Some(32);
let a = a.unwrap();

1。这样的语言存在;它们是带有 dynamic scope 的语言有些人更喜欢它们。他们是少数,用这些语言编写的程序很难推理!

关于csv - 如何在结构回调中使用外部对象,例如将数据附加到 CSV 时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50462046/

相关文章:

c - 在c中以恒定时间从数组中删除3D点

swift - 在方法A中,在方法B中从回调中获取数据?

c# - 对象异常的无限循环stackoverflow列表

mysql - 如何使用 LOAD DATA INFILE 将 CSV 文件中的选定列插入 MySQL 数据库

c - 为什么我的C工程编译找不到我的结构?

node.js - 在没有回调 hell 的情况下停止 Sequelize promise 链

javascript - 在闭包中调用父函数

python - 删除巨大的 csv 中已知的确切行

python - 在 python 中创建 CSV 文件,它将列出目录中带有服务器名称的所有文件

c - 结构指针兼容性