Nano Hash - криптовалюты, майнинг, программирование

ржавчина: проблема на всю жизнь, нужна помощь

Недавно я делаю аналог iostream C++ для ржавчины, но меня смущает система времени жизни. Я хочу сохранить ссылку на читатель или голый читатель в IStream, поэтому я сохраняю Q в структуре. И затем я использую фантомный тип D для преобразования Q в R.

Вот объяснение:

  • R — это Reader, где мне действительно нужно.
  • Q — это тип хранилища R, поэтому Q может быть голым R или ссылкой &mut R.
  • Я использую D для преобразования Q в R. Потому что borrow_from_mut(&mut R) дает мне &mut R, а borrow_from_mut(R) также дает мне &mut R. Таким образом, это может быть D: BorrowFromMut<Q>.
  • и D можно преобразовать в R путем разыменования. Итак, &mut D: DerefMut<R>
  • потому что &mut D можно разыменовать на D, но мне нужно &mut D разыменовать на R, здесь нужно использовать trait object для динамической отправки метода deref_mut из-за отсутствия UFCS. (трюк: let tmp: &'c mut Q = &mut *self.istream.borrow_mut();)

Такой трюк позволяет IStream хранить как &mut R, так и R.

Но код не может скомпилироваться из-за пожизненной проблемы:

let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
//the Q borrowed from the RefCell only valid in the block, doesn't out live 'c.

как я могу это решить?

вот пример кода:

pub struct IStream<'a,'b,R:'a+'b,Q:'a+'b,Sized? D:'b> where R: Reader, D: BorrowFromMut<Q>, &'b mut D: DerefMut<R> {
    istream: Rc<RefCell<Q>>
}

impl<'a,'b,R,Q,D> Clone for IStream<'a,'b,R,Q,D> where R: Reader, D: BorrowFromMut<Q>, &'b mut D: DerefMut<R> {
    fn clone(&self) -> IStream<'a,'b,R,Q,D> {
        IStream {
            istream: self.istream.clone()
        }
    }
}

impl<'a,'b,'c,F,R,Q,D> Shr<&'b mut F,IStream<'a,'c,R,Q,D>> for IStream<'a,'c,R,Q,D> where R: Reader, F: FromStr + Default, D: BorrowFromMut<Q>, &'c mut D: DerefMut<R> {
    fn shr(mut self, output: &mut F) -> IStream<'a,'c,R,Q,D> {
        let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
        let mut reader: &mut D = BorrowFromMut::borrow_from_mut(tmp);
        let mut real_reader: &DerefMut<R> = &reader;

        let mut buf = String::new(); // a string buffer

        loop {
            if let Ok(byte) = (*real_reader.deref_mut()).read_byte() {
                if byte == '\u{A}' as u8 || byte == '\u{20}' as u8 {
                    break
                } else {
                    buf.push(byte as char);
                }
            } else {
                break
            }
        }

        *output = FromStr::from_str(buf[]).unwrap_or_default();
        IStream {
            istream: self.istream.clone()
        }
    }
}

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

Ответы:


1

Я думаю, ты пытаешься перехитрить себя. Вам не нужно одновременно хранить средство чтения или изменяемую ссылку на средство чтения, потому что вы может легко преобразовать такую ​​изменяемую ссылку в полноценное средство чтения. Без этих сложностей ваш код будет выглядеть так (обратите внимание на пример by_ref() ниже):

#![feature(slicing_syntax)]

use std::cell::RefCell;
use std::rc::Rc;
use std::str::FromStr;
use std::default::Default;
use std::io::ByRefReader;

pub struct IStream<R> where R: Reader {
    istream: Rc<RefCell<R>>
}

impl<R> Clone for IStream<R> where R: Reader {
    fn clone(&self) -> IStream<R> {
        IStream {
            istream: self.istream.clone()
        }
    }
}

impl<'b, F, R> Shr<&'b mut F, IStream<R>> for IStream<R> where R: Reader, F: FromStr + Default {
    fn shr(self, output: &'b mut F) -> IStream<R> {  // '
        let mut real_reader = self.istream.borrow_mut();

        let mut buf = String::new(); // a string buffer
        loop {
            if let Ok(byte) = real_reader.read_byte() {
                if byte == '\u{A}' as u8 || byte == '\u{20}' as u8 {
                    break
                } else {
                    buf.push(byte as char);
                }
            } else {
                break
            }
        }

        *output = FromStr::from_str(buf[]).unwrap_or_default();

        self.clone()
    }
}

fn main() {
    let mut stdin = std::io::stdin();
    let stdin_ref: &mut _ = &mut stdin;  // a mutable reference to a reader

    let is = IStream { istream: Rc::new(RefCell::new(stdin_ref.by_ref())) };

    let mut x: uint = 0;
    let mut y: uint = 0;

    is >> &mut x >> &mut y;

    println!("{}, {}", x, y);
}
01.01.2015

2

Вот воспроизведение упомянутой вами ошибки:

use std::cell::RefCell;

fn foo<'a>(rc: &'a RefCell<u8>) { 
    let b: &'a u8 = &*rc.borrow();
}

fn main() {
}

Это не скомпилируется с

заемная стоимость не живет достаточно долго

По определению результат borrow() имеет область, привязанную к области, в которой он вызывается, вы не можете «обмануть» его, указав другое время жизни. Все, что нужно сделать, это заставить компилятор сказать вам, что вы не можете этого сделать.

01.01.2015
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..