質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

998閲覧

Rustの型推論について、対象のコードでどの様に推論されたかを知りたい。

iromay

総合スコア19

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

1クリップ

投稿2021/11/07 16:30

いつもお世話になっております。
先日からRustに入門した初心者です。
現在エラーハンドリングについて学んでおり、
anyhowクレートを利用した処理に取り組んでいます。

テキストの中で以下のコードが紹介してあったのですが、
一部分からないところがあり、今回質問させて頂きました。

Q1:use anyhow::{Context, Result};について
ここではクレートanyhow内のContext、Resultという型を使うことを
宣言しているという認識で合っているでしょうか?

Q2:fn get_int_from_file()内のlet num_strの行では
with.contextメソッドを利用しています。
これはuseで宣言したanyhowクレートの中の
Result型にImplementされたメソッドですが、
コードの中でnum_strというオブジェクトを
Result型であると明示的に宣言をしていません。

これは恐らくRustの型推論が働いたのだと思われますが、
どういったの要因により、型が決まったのでしょうか?

以下のいずれかかと考えております。

  • Result型に実装されたメソッドを利用しているので、Result型に定まった。
  • 返り値でResult型を指定しており、関数get_int_from_fileの返り値となるのは

num_strであるので、Result型に定まった。

Rust

1use anyhow::{Context, Result}; 2 3fn get_int_from_file() -> Result<i32>{ 4 let path = "number.txt"; 5 6 let num_str = std::fs::read_to_string(path).with_context(|| format!("failed to read string {}", path))?; 7 8 println!("{}",type_of(num_str)); 9 10 num_str 11 .trim() 12 .parse::<i32>() 13 .map(|t| t * 2) 14 .context("failed to parse string") 15} 16 17fn main() { 18 match get_int_from_file(){ 19 Ok(x) => println!("{}", x), 20 Err(e) => println!("{:#?}", e) 21 } 22}

お忙しいところ大変恐縮ですが、ご教授頂けますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Q1 use anyhow::{Context, Result};について

ここではクレートanyhow内のContext、Resultという型を使うことを
宣言しているという認識で合っているでしょうか?

半分合ってます。anyhowクレートで定義されたアイテムを使うことを宣言している、という点では合ってますが、アイテムは型とは限りません。

  • anyhow::Contextはトレイトでwith_contextcontextメソッドを定義している。userしているのは、それらのメソッドを使うため
  • anyhow::Resultは型エイリアスで、core::result::Result<T, E>型の別名として定義されている。Rustのcoreクレートは、stdクレート(標準ライブラリー)のさらに基礎となるクレート。useしている理由はget_int_from_file関数の戻り値型の定義Result<i32>で使うため

Q2

コードの中でnum_strというオブジェクトを
Result型であると明示的に宣言をしていません。

これは恐らくRustの型推論が働いたのだと思われますが、
どういったの要因により、型が決まったのでしょうか?

たしかに、num_str変数の型は型推論によって導かれますが、実はその型はResult型ではなくてString型です。

rust

1let num_str = // String型 2 std::fs::read_to_string(path) 3 .with_context(|| format!("failed to read string {}", path))?;

以下のようにして決まります。

  1. std::fs::read_to_string関数の戻り値型はstd::io::Result<String>std::result::Result<T, E>の型エイリアス。なおコンパイラーはcore::result::Result<T, E>std::result::Result<T, E>を同じ型として扱う)
  2. anyhow::Context::with_contextメソッドの戻り値型はanyhow::Result<String, anyhow::Error>
  3. anyhow::Result<String, anyhow::Error>?演算子を適用した後の値にnum_str変数を束縛している。?演算子はResult<T, E>型の値がOk(T)ならTをunwrapして返し、Err(E)ならget_int_from_fileから早期リターンする。ここでTString型なので、num_str変数の型はStringに決まる。

余談ですが、rust-analyzerをVisual Studio Code(VS Code)と組み合わせて使うと、以下のスクリーンショットのように、Rustソースコードの編集画面にコンパイラーが推論した型などをグレーの文字で表示してくれます。便利ですので、ぜひ使ってみてください。

rust-analyzerのスクリーンショット

投稿2021/11/08 02:49

tatsuya6502

総合スコア2046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

iromay

2021/11/08 06:15

早速のお返事ありがとうございます。 丁寧で明解なご回答、誠に感謝いたします! 以下について、num_strがString型ということは理解出来ました。 let num_str = // String型 std::fs::read_to_string(path) .with_context(|| format!("failed to read string {}", path))?; 一点確認なのですが、ここで.with_contextが使用出来ているのは、 std::fs::read_to_string(path)の戻り値がResult型であり、 このプログラムでは"use anyhow::{Context, Result};"が宣言されているので、 Result型のメソッドとして、anyhowの中でcontexトレイトがResult型に実装されているから という理解であっているでしょうか?
tatsuya6502

2021/11/08 07:05

> 一点確認なのですが、ここで.with_contextが使用出来ているのは、 std::fs::read_to_string(path)の戻り値がResult型であり、 このプログラムでは"use anyhow::{Context, Result};"が宣言されているので、 Result型のメソッドとして、anyhowの中でcontexトレイトがResult型に実装されているから はい。その理解で合ってます!
iromay

2021/11/08 22:58

ありがとうございます!理解することが出来ました!引き続き勉強頑張ります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問