【学習17日目】脱線して浮動小数点について復習

なぜコンピュータに小数を表現させるのに、あのような回りくどい子ををさせるのか、ちょっと理解できたのでメモ。
ようするに、整数と違い、数と数の間に無限に小数が含まれているので、数の数を確保することができないため。
えーっとなんだっけ。
1.23を表現するには

Rustの浮動小数点はIEEE 754 形式。
f32 = 単精度浮動小数点数では、符号部 1 ビット ・ 指数部 8 ビット ・ 仮数部 23 ビット
f64 = 倍精度浮動小数点数では、符号部 1 ビット ・ 指数部 11 ビット ・ 仮数部 52 ビット
(これはやっぱり難しいので引き続き理解するまで加筆。)

【学習16日目】3.5 制御フロー

3.5.1 if 式


fn main() {
let number = 7;

if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}

if部分は以下のようにつながっとる。

if number < 5 {println!("condition was true");} else {println!("condition was false");}
最初の波括弧の中にも、elseの波括弧のなかもセミコロンがある。
これは取ってもエラーにならん。文を追加することに備えてのセミコロンか。

【学習15日目】これまで登場したコード内の記号、記法おさらい

これまで登場したもので把握している範囲で。いまのところ独自解釈あり。

【関数】
fn ←関数であることを示す
fn main ←プログラム内には main という最初に読まれる関数が必要
fn main () ←関数には引数の枠が必要(空でもよし)
fn another_function () ←関数には自分で名前をつけることが可能
fn main () { } ←関数の中身は波括弧の中に記述していく
※波括弧のあとにセミコロンは必要ない。関数内部で使用される場合は必要な場合あり
※ちなみに ( ) や { } の前後にスペースを入れようが、入れまいが
コンパイラは気にしない。(全角スペースは試していない)
なんとなくだが ( ) の中にはだいたい引数が入るようだ。
例えば
println!("good morning");
これはprintln! に good morning という引数を与えている
また
.read_line(&mut guess) のように変数を引数として入れているときも

波括弧は
("x is { }", x) のように変数を取り出すことも出来る。

セミコロンの意味(機能)
これがまだ分からない。
処理の終わり(区切り)?

【学習14日目】3.3.3 戻り値のある関数

3.3.3 戻り値のある関数

  • 関数は、それを呼び出したコードに値を返すことができます。
  • 矢印( -> ) の後に型を書いて確かに宣言します。
  • 多くの関数は最後の式を暗黙的に返します。


fn five() -> i32 {
5
}
fn main() {
let x = five();
println!("The value of x is: {}", x);
}
そろそろいちいち型注釈をすることに慣れなくては。

混乱してきた。文 (statement)、式 (expression)、関数 (function)、
そして戻り値のある関数 (Functions with Return Values)

※疑問。ひとつのコードのなかの各関数の中で使われている変数名は重複していてもエラーにならない?


fn first_function() {
let x : i32 = 1;
println!("x is {}", x);
}

fn second_function() {
let x : i32 = 2;
println!("x is {}", x);
}

fn main() {
first_function();
second_function():
}

これは動く。
別の関数であれば変数名は干渉しない。

疑問
変数に値をセット「するだけ」の関数は動く?
→ それが以下にあたるが、5の末尾にセミコロンを付けるとエラーになる。
fn five() -> i32 {
5
}

明日はここまでの記法を自分なりに整理してみよう。

【学習13日目】3.3.2 関数本体は、文と式を含む

3.3.2 関数本体は、文と式を含む
関数本体は、文が並び、最後に式を置くか文を置くという形で形成されます。

文とは値を返さない命令
文=statement
parentheses = 括弧
unstable = 不安定

let x = 1; ←これはOK
let x = (let y = 1); ←これは括弧内のletが値を返さず、xに何も入らないのでダメ。

※C やRuby では、代入は代入値を返します。これらの言語では、x = y = 6 と書いて、x もy も値6 になるようにできるのですが、Rust においては、そうは問屋が卸さないわけです。


fn statement_test(){
let q = {
let p = 2;
};
println!("q = {}", q);
}
↑これも文のみ(値を返す構造になっていない)


fn statement_test(){
let q = {
let p = 2;
P + 1 //←行末にセミコロンなし
};
println!("q = {}", q);
}
↑これは p+1という式が中にあり、値を返すので動作する。

式は文の一部になりえます: 関数呼び出しも式です。マクロ呼び出しも式です。新しいスコープを作る際に使用するブロック( {} ) も式です:

式は終端にセミコロンを含みません。式の終端にセミコロンを付けたら、文に変えてしまいます。そして、文は値を返しません。

わかったようなわからないような。

【学習12日目】関数

3.3 関数
関数命名の慣例 スネークケース
全文字を小文字にし、単語区切りにアンダースコアを使うこと
Snake case - Wikipedia

Rust, for variable names, function names, method names, module names, and macros.

その他
Camel Case vs. Snake Case vs. Pascal Case — Naming Conventions | Khalil Stemmler
スネークケースとは - 意味をわかりやすく - IT用語辞典 e-Words

定数は UPPER_SNAKE_CASE

波かっこ {
} が、コンパイラに関数本体の開始と終了の位置を伝えます。

おお、そうか。

コンパイラは、関数がどこで定義されているかは気にしません。
どこかで定義されていることのみ気にします。

↑これは知らんかった…。すげえ
確かに、順に読んで順に実行するシェルスクリプトとは違って、「コンパイル」するということは内容が一旦全部内蔵されるわけだ(だよね。)
※でも main 関数がプログラムへのエントリーポイント(訳注:スタート地点)になります。ことには変わりなし。

3.3.1 関数の引数
関数は、引数(ひきすう)を持つようにも定義できます。
まあ、今の段階では引数をコードの中に「書く」意義は分からない。

関数シグニチャにおいて、各仮引数の型を宣言しなければなりません。
関数実行の引数は値のみ記述し、関数本体で方を宣言する

fn main() {
sub_function(5); //ここで呼び出している
}

fn sub_function(x: i32) { //ここ(関数本体)で引数で書かれるべきデータ型を定義している。引数が"x"に入る。
println!("The value of x is: {}", x);
}

これもやはり上下段の関数の登場順番を入れ替えてもちゃんと動く。
呼び出す側の関数と呼び出される側の関数の記述順がどうでもいいというのは、
いまだに実感が無いが。
コードがコンパイルされてバイナリになると、順番とか時間がなくなってしまうような感覚だ。

【学習11日目】データ型・配列型

3.2.2.2 配列型 (The Array Type)

  • 配列の全要素は、同じ型(データ型)でなければなりません。
  • Rust の配列は、固定長: 一度宣言されたら、サイズを伸ばすことも縮めることもできません。
  • 素数が決まっているものに使うとよい、とのこと(曜日、月名など)


let a = [1, 2, 3, 4, 5]; //簡単な基本形
let b: [i32, 5] = [1, 2, 3, 4, 5]; //丁寧な基本形(注釈・配列サイズ付き)
let c = [0; 5] //配列の初期設定のようなものの例(0が5つ)

配列型はタプル型よりむずかしい。