Насколько я понимаю, объекты, созданные вне области видимости, доступны внутри области (следовательно, разрешены такие вещи, как затенение), но, похоже, это не работает в этом сценарии:

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

Как я могу добавить данные (Event) в файл CSV изнутри функции обратного вызова для Process?

-1
Greg 22 Май 2018 в 10:25

1 ответ

Лучший ответ

Я настоятельно рекомендую вам вернуться и перечитать < em> Язык программирования Rust , в частности, глава о функции. Этот код, кажется, показывает фундаментальные проблемы, связанные со всей моделью работы функций.

Например, код пытается использовать переменную wtr в функции callback без ее прямой или косвенной передачи.

Если бы такой код работал 1 , программисты, вероятно, возненавидели бы иметь дело с этим языком, потому что было бы почти невозможно сказать что и где значение wtr даже пришел из.

Решение простое: передать в этот код любое значение, которое необходимо фрагменту кода. Тогда легко (или проще) определить, откуда взялось значение. Есть несколько способов, которые могут сработать.

  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, которые я игнорирую, потому что они не связаны с вашим вопросом. Я рекомендую вам начать с более простого фрагмента кода, заставить его работать, а затем усложнять его. Таким образом, вы сначала имеете дело только с более простыми ошибками.

Когда вы поймете основы использования функций, вы можете узнать о закрытия . Это позволяет вам «захватывать» переменные из внешней области видимости и передавать их (теми же двумя методами, что и выше) без необходимости иметь дело с конкретным количеством или типом переменных.

объекты, созданные вне области видимости, доступны внутри области

Это верно для одной функции. Это не распространяется на функции.

следовательно, такие вещи как слежка разрешены

Слежка не имеет ничего общего с областью применения. Вам разрешено затенение внутри той же области:

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

1 . Такие языки существуют; это языки с динамической областью видимости, и некоторые люди их предпочитают. Их меньшинство, программы, написанные на этих языках, сложно рассуждать!

2
Shepmaster 22 Май 2018 в 09:23