💭

[Rust]Stringでtake的な処理[memo]

2020/09/17に公開

初投稿テストも兼ねて、ちょっといろいろ実装しているときに、引っかかったので解決法を。

やりたいこと

String型変数aの文字列を空にして、その値を返す

実現コード

事前に変数aがmutableで参照できることを前提に、

{
let mut b = String::new();
std::mem::swap(&mut a, &mut b);
b
}

という形で記述する。

追記: core::mem::takeでできました。WAO。

macroコード

いちいち上のようなコードを作成するのもあれですし、かといってクレートにグローバルな関数を書くのもなーと思ったので、以下のようなmacroを組んで使っています。

#[macro_export]
/// Takes string inner.
macro_rules! take_string {
   ($var:ident) => {{
   	let mut empty = String::new();
   	std::mem::swap(&mut $var, &mut empty);
   	empty
   	}};
   ($var:expr) => {{
   	let mut empty = String::new();
   	std::mem::swap(&mut $var, &mut empty);
   	empty
   	}};
}

追記: core::mem::takeでできることが分かったので、

#[macro_export]
/// Takes string inner.
macro_rules! take {
   ($var:ident) => {
   	core::mem::take(&mut $var)
   };
   ($var:expr) => {{
   	core::mem::take(&mut $var)
   	}};
}

という感じに修正。
 もしくはもう、use core::mem::take;したらいいかなと思っています。

やっていること

空の文字列を持つ変数を作成し、std::mem::swapで変数の値を入れ替えた(追記前)。
追記後: core::mem::take関数を利用してOptionにおけるtakeのようなことをした。

あれこれ

Stringに組み込みでtakeほしいなって思ったり。というか、Zenn割と書きやすいですね。重くないし。

Discussion