5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rustを使わない理由に反論していく

Posted at

今回は、このサイトに反論していきます。

参照を保存するバッファを再利用できない

これは事実です。いい解決法は今のところありません。
いい解決法ではないですが、解決策としては、下記のように、参照を強制的に引き延ばすことができます。
なお、例えバッファを再利用しても、数回呼び出す程度ならば、その都度イテレータを生成したほうが動作速度は速いでしょう。

pub fn process_sources(sources: Vec<Sources>) {
    let mut buffer: Vec<&[u8]> = Vec::new();
    for source in sources {
        let mut data: Vec<u8> = source.fetch_data();
        let data_borrowed = &mut data;

        // It's not a smart solution, but everything else has failed.
        // You must verify the validity period of the reference yourself.
        let data_borrowed: &'_ mut Vec<u8> = unsafe { std::mem::transmute(data_borrowed) };

        buffer.extend(data_borrowed.split(splitter));
        process_data(buffer.as_ref());
        buffer.clear();
    }
}

自己参照構造体が作れない

これは、ある程度解決しています。Rustの知識量の問題です。ただし、Cargo miriというメモリ使用診断ツールでは、自己参照構造体はまだエラーが出ます。現在はIssueで話し合った後放置されています。

自己参照構造体は、PinとMaybeUninitを用いると書けます。
例はこんな感じです。理解できない人は自己参照構造体を作れるライブラリなどを使って下さい。
かなり端折っているので、コードをすべて見たい人はhttps://github.com/oligamiq/small_example_lifetime をどうぞ

pub struct PinUninitGuard<'a, T: Unpin + PinnedInit> {
    initialized: Pin<&'a mut T>,
}

impl<'a, T: Unpin + PinnedInit> PinUninitGuard<'a, T> {
    pub fn new(mut pinned: Pin<&'a mut MaybeUninit<T>>, builder: T::Builder) -> Self {
        unsafe { <T as PinnedInit>::init(&mut pinned, builder) };
        Self {
            initialized: unsafe { pinned.map_unchecked_mut(|t| t.assume_init_mut()) },
        }
    }
}

impl<'a, T: Unpin + PinnedInit> Drop for PinUninitGuard<'a, T> {
    fn drop(&mut self) {
        unsafe {
            MaybeUninit::assume_init_drop(
                core::mem::transmute::<&mut T, &'a mut MaybeUninit<T>>(
                    &mut self.initialized.as_mut(),
                ),
            )
        };
    }
}

fn main() {
    let normalizer = std::pin::pin!(Normalizer::uninit());
    let mut normalizer = PinUninitGuard::new(normalizer, Cache::new());
    normalizer.use_something();
    normalizer.use_component();

    let mut boxed_normalizer = Box::pin(Normalizer::uninit());
    let boxed_normalizer = boxed_normalizer.as_mut();
    let mut boxed_normalizer = PinUninitGuard::new(boxed_normalizer, Cache::new());
    boxed_normalizer.use_something();
    boxed_normalizer.use_component();
}

コンパイル時ジェネリクス

これに関しては、Rustの思想の問題です。
もう行っているようですが、素直にマクロを使うのが一番です。

まとめ

皆さんRustを使いましょう

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?