contentRustで再帰的データ構造を定義するRustRust勉強中。現状メインで使用している言語はC。Rustの勉強と低レイヤの勉強をかねて、「低レイヤを知りたい人のためのCコンパイラ作成入門」をRustで実装しているが、Cの頭で書こうとしたらつまづいたのでメモ。構造体を定義する実装したいデータ構造はCだとこうなる。Nodeのポインタになっており、再帰的なデータ構造になる。kindがND_NUMの場合のみ使う};これをRustで表現する。u32,}これは当然失敗する。indirectionlhsとrhsが実態として定義されており、再帰的に繰り返された場合に構造体のデータサイズが無限に発散してしまうため、コンパイラがエラーにする。ここをCでいうポインタとして定義したい訳だが、Rustではポインタの考え方というか、使い方がCとは大きく異なる。生ポインタというものもあるらしいが、ここで安易にunsafeな処理にもしたくない。調べたら、こういう場合はBoxを使えばいいらしいと分かった。Boxを使って書き変えてみる。checkするとコンパイルは問題なく通る。以下で説明するが、これは罠である。構造体を使ってみるまず、Cの世界でデータ構造を使用する関数を見てみる。node;}これをRustで実装してみる。checkするとエラーになる。`rhs`Rustでは構造体を使うとき、全てのメンバを初期化しなくてはならない。ん?Boxの初期値?u32であるvalの初期値は、適当に0とかに設定できなくもないが、Boxの初期値が設定できない。ダミーのBoxを用意してその値を入れようとしても、そのダミーの中のBoxを定義するためにまた別のBoxが、というように再帰しているので詰んでしまう。する?ここで、今回のデータ構造を整理してみる。再帰的データ構造には2種類のデータが含まれている。再帰するデータ(次につながるデータ)終端するデータ(次がないデータ)ここまでに書いた構造体では、この2種類のデータが1つの構造体に混在してしまっていることになる。Cではこのような構造体を定義できるが、結果としてそれぞれのデータを表現する際に初期化されない(意味のある値が入らない)領域ができてしまう。これでは、意味のない値に不正にアクセスしてしまう危険が生じるところ、Rustではそのような危険性を排除できている、と言えるかもしれない。するか?Rustでは、こういうときにはenumを使うとうまく表現できる。RustのenumはCに比べて多様なデータ構造を表現できる。ここでは、再帰するデータは2項演算子、終端するデータは数字となるため、それぞれのデータに必要な情報を考えenumを用いて定義する。}操作関数も定義する。checkも通り、再帰的データ構造に必要な2種類のデータも明確に分離させて定義できた。まとめRustで再帰的データ構造を定義するときはenumを使おう。upLoginユーザーは見つかりませんでした。