2017年7月15日土曜日

Gamarnik, Tsisiklis. Fundamentals of Probability 10日目 写像で作られる確率変数のpdf

David Gamarnik, and John Tsitsiklis. 6.436J Fundamentals of Probability. Fall 2008. Massachusetts Institute of Technology: MIT OpenCourseWare, https://ocw.mit.edu. License: Creative Commons BY-NC-SA.

Lecture 10. Derived Distributions

random variable とPDF が与えられ,measurable があるとき,のdistribution(CDF, PDF or PMF)を知りたいことがよく有る.がdiscreteならば

でよいが、continuousな場合はより複雑になる.

1. Functions of a Single Random Variable

Calculation of the PDF of a Function Y=g(X) of a Continuous Random Variable X

(a)
(b)

Example

とする.がcontinuousであって,をPDFとする.このとき

よって

Example

は非負でとする.

ここで
よって

1.1 The Case of Monotonic Functions

が狭義単調増加かつ微分可能なとき,とする.は可逆でがある.に,chain ruleによって


を代入して

が狭義単調現象の場合にもほとんど同様に

が成立して,

である.

で,から

と考えれば良い.

1.2 Linear Functions

つまりとなる場合を考える.とする.このとき
であって,

である.

Example (A linear function of a normal random variable is normal)

とする.

すなわちである.

2. Multivariate Transformations

というjointly continousなrandom variableのベクトルを考えて,joint PDFはとする.があって,とする.とするとである.
が openなで連続微分可能であるとき,が可逆とする.
このtきが存在する.
1次元の場合とほとんど同様の議論で多次元版に拡張できる.

2.1 Linear Functions

は線形で,とする.行列である.を固定してとする.
を固定する.という超立方体を考えてとする.の体積はである.
として,で連続なら

が成立する.したがって

である.両辺をで割って,が言える.
が可逆であればがあって,さらにに注意すれば,

が成立する.が非可逆ならでのみ値をとり,jointly continuousでない.はあるに同型なので,のjoint PDFとして書ける.

2.2 The General Case

rで連続微分可能な場合,におけるJacobi行列とする.は直線で囲まれた図形ではないが,1つぎのTaylor展開によっての周りで線形近似できる.が体積を持つから,線形の場合と同様に

である.ここでのJacobi行列とすれば,であって,

である.

3. A Single Function of Multiple Random Variables

があって,random variableとする.

を微分すればPDFを得られる.
もう一つの方法に,を,が可逆であるように定義して2.2で述べた公式を用いてのjoint PDFを求め,のPDFを積分によって求めるというのが有る.
最も単純なの定め方はであって,として,の第一次元とする().
このとき,Jacobi 行列は

よって

Example

は正でjointly continousで,のPDFを求める.
からであって,

とすると

から


したがって

4. Maximum And Minimum of Random Variables

は独立とする.またorder statisticsとする.すなわちの最少, の二番目に小さい要素,… である.
このoder statistics のjoint distributionとのdistributionを求める.

が成立し,また

である.
特にがi.i.d.(独立だが同じdistribution)でそのCDFが, PDFがとするとき,

であって,

5. Sum of Independent Random Variables - Convolution

は独立なdiscrete random variableとする.のPMFは

である.continuousでも,jointly continousなら

ここでとすると

で微分して

特にが独立なら

である.

2017年7月14日金曜日

Gamarnik, Tsisiklis. Fundamentals of Probability 09日目 連続確率変数の条件付き確率

David Gamarnik, and John Tsitsiklis. 6.436J Fundamentals of Probability. Fall 2008. Massachusetts Institute of Technology: MIT OpenCourseWare, https://ocw.mit.edu. License: Creative Commons BY-NC-SA.

Lecture 9. Continuous Random Variables

2. Conditional PDFs

discrete random variable の場合にはconditional CDFはによって定義された.一方continous random variableの場合はが常に成立するので,単純にdiscreteを拡張するわけには行かない。そこで、の極限と考える.ここで

この式がDef 9-1を動機づける.

Definition 9-1

(a)
があるときののconditional CDFを

なるに定める.
(b)
があるときののconditional PDFを

に定める.
(c)
があるときののconditional expectationを

に定める.
(d)
があるとき,のconditional probabilityを

に定める.

4. Conditional Expectation as a Random Variable

discreteの場合と同様,はまたrandom variableである.すなわち

はrandom variableである.
measurableながあるときである.特にを考えればE[E[X|Y]]=E[X]$である.

4.1 Optimality properties of conditional expectations

を与えられたときののestimation(推測)と考えることが出来る.実際をestimation errorと考えたときこれが他のestimationのすべてのestimation errorのうち最少とするという点で最良のestimationである.

Theorem 9-1

とする.measurable について

である.

proof.

5. Mixed Versions of Bayes’ Rule

をまだ観測されていないrandom variableで, CDFは既知なとする.と独立でないrandom variable があって,そのconditional CDF はであるとする. Yの現れを観測したときを推測することを考える.の具体的な値を1つ推測することもあるが,を条件としたconditional distributionを考えることが多い.これはBayes’ ruleを使って実現できる.
がともにdiscreteであるとき

である.がともにcontinuousであるなら

である.
一方がdiscreteでもう一方がcontinuousである場合を考える. がdiscreteでがcontinuousとし,joint distributionをとおくと

さらに


したがって

のPDFである.
であれば

であって,

と定めて良い.また別の議論で

と示せる.

Gamarnik, Tsisiklis. Fundamentals of Probability 08日目 連続確率変数

David Gamarnik, and John Tsitsiklis. 6.436J Fundamentals of Probability. Fall 2008. Massachusetts Institute of Technology: MIT OpenCourseWare, https://ocw.mit.edu. License: Creative Commons BY-NC-SA.

Lecture 8 Continuous Random Variables

1. Continuous Random Variables

random variable:が連続であるとは,CDFが

と書けるようながあるということで,またこののPDF(probability density function)と呼ぶのだった.さらにこのとき,Borel集合

が成立する.

2. Examples

2.1 Uniform

区間を考えて,

とするとはCDFの条件を満たしている.これをと書く.またこれのPDFはである.
またであるとき,probability lawは上のLebesgue measureである.

2.2 Exponential

を固定し,とする.このときはCDFの条件を満たし,そのPDFはである.この分布をと書く.
exponential distributionはgeometric distributionの極限と見ることが出来る.すなわち,を固定してに考えると,これはgeometric CDFに一致する.
直感的には,単位時間ごとに確率で表が出るコインを投げ続け,を初めて表が出るまでの時間の確率変数とするのである.
Exp()はmemorylessness property(無記憶性)という重要な性質を持つ.

Theorem 1

exponentially distributed random variableとする.このとき任意の

が成立する.

proof.

をパラメータに持つexponential random variableとする.

2.3 Normal distribution

パラメータをもつnormal (or Gaussian) distribution

というPDFで定める.これをと略記し,を特にstandard normal distributionという.normal distributionのCDFを解析的に書くことはできないが,standard normal distributionの場合には数票が与えられている.standardでないnormal distributionの場合は簡単な変数変換によって計算できる.すなわちについて,とすると,であるから,

である.ただしのCDFとする.

2.4 Cauchy distribution

というPDFをもつdistributionをCauchy distributionという.

2.5 Power law

discrete power law を離散的に拡張する.
.

3. Expected Values

discreteの場合と同じように,PDF をもつcontinuous random variable にも,expecetd value E[X]を

と定義する.この積分の収束性はが十分条件である.このとき,integrableであるという.
discrete の場合のexpectationについて得られた定理の全てがcontinuousの場合にも成立する.
ただし,総和でなく積分で表現しなければならないものもいくつかある.

Proposition 8-1

を非負なrandom variableとする.すなわち.このとき

proof.

Proposition 8-2

のPDFがとする.がmeasurableならはintegrableであって,

proof.

と,を正の部分と負の部分に分ける.とくにである.

ここで

同様に

足し合わせて

がたしかに成立する.

4. Joint Distributions

という同じprobability spaceのrandom variableの組を与えられたとき,
で,

となるようなmeasurable があるとき,jointly continuousであるといい,をjoint PDFといい,をjoint CDFという.
joint PDFが連続な点で,

が成立する.また,のBorel set に,

が成立する.さらにのLebesgue measure が0ならである.
さて,

だから,にはmarginal PDF

が得られる.
がjointly continuous ならはともにcontinous random variableであることがわかった.
一方,同じprobability spaceのcontinous random variableの組であっても,jointly continousであるとは限らない.

Proposition 8-3

はjoijntly continousで,そのPDFはとする.がBorel measurableかつがintegrableであるとき,

が成立する.

5. Independence

がindependentであるとは,

が成立することと同値であった.
discreteの場合と同様,これと同値な命題がいくつか存在する.

Theorem 8-2

はjointly continousとする.以下は同値である.
(a) X, Y はindependent
(b) 任意のというeventはindependent
(c) 任意の
(d) がそれぞれのPDFであるとき,ほとんどすべての点

proof.
Lec.6とほとんど同様.

2017年7月13日木曜日

The Rust Programming Language 2nd 14日目

https://doc.rust-lang.org/book/second-edition/
Apache License Version 2.0

Generic Types, Traits, and Lifetimes

Validating References with Lifetimes

referenceにはかならずlifetime(寿命)という,referenceが有効であるスコープをもっているが,大方の場合それは明示されずコンパイラに推測される.lifetimeを特に指定する場合には,generic lifetime parametersを使う.lifetimeはRust独特の機能であって,時に非常に重要なので,この章でその基本的な概念を述べた後,19章で応用的なlifetimeの扱い方を学ぶ.

Lifetime Prevent Dangling References

dangling(宙ぶらりん) referenceは,すでに意味を失った変数へのreferenceで,これを放置すると,あるデータにアクセスしようとして他のデータにアクセスしてしまうことがある.lifetimeの目的はdanglin referenceが出来るのを防ぐことである.
例えばlist 10-16では内側の{ }で定義されたxへのreferenceをrに代入しているが,xは内側の{ }が終了すると同時に消えてしまうので,その時点でrも有効ではなくなる.つまりxのlifetimeは内側の{ }の中で,rのlifetimeは外側の{ }の中だから,その外でのreferenceは無効になる.
list 10-16

{
    let r;

    {
        let x = 5;
        r = &x;
    }

    println!("r: {}", r);
}

The Borrow Checker

list 10-16にlifetimeの注釈を加えてみる.
list 10-17

{
    let r;         // -------+-- 'a
                   //        |
    {              //        |
        let x = 5; // -+-----+-- 'b
        r = &x;    //  |     |
    }              // -+     |
                   //        |
    println!("r: {}", r); // |
                   //        |
                   // -------+
}

rのlifetimeを'a, xのlifetimeを'bで書いた.コンパイラはそれぞれのlifetimeを比較し,rが“`x““をborrowしているのを見つけて,エラーを出す.
list 10-18はdangling referenceを持たず,正常にコンパイルできる.
list 10-18

{
    let x = 5;            // -----+-- 'b
                          //      |
    let r = &x;           // --+--+-- 'a
                          //   |  |
    println!("r: {}", r); //   |  |
                          // --+  |       rustでは,宣言した順とは逆順に
}                         // -----+       変数が無効化されていくのだった

Generic Lifetimes in Functions

2つのstring sliceを引数に与えて,長い方のstring sliceを返す関数longestを考える.
longestの実装は後回しにして,例えばlongeestはlist 10-19のように利用できる.
src/main.rs list 10-19

fn main() {
  let string1 = String::from("abcd");
  let string2 = "xyz";

  let result = longest(string1.as_str(), string2);
  println!("The longest string is {}", result);
}

は正常に動けば”abcd”を出力するはずだ.
list 10-20は longestの案だが,コンパイルできない.
src/main.rs list 10-19

fn longest(x: &str, y: &str) -> &str {
  if x.len() > y.len() {
    x
  } else {
    y
  }
}

shell

error[E0106]: missing lifetime specifier
   |
1  | fn longest(x: &str, y: &str) -> &str {
   |                                 ^ expected lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but the
   signature does not say whether it is borrowed from `x` or `y`

エラーメッセージは返り値のreferenceがx, yどちらを指せばいいのかわからないと言っている.しかしプログラマもx, yのどちらが長いかは事前にわからないし,与えられる引数のlifetimeがどうであるかもわからない.そこで,generic lifetime parameterによってrefereneたちの間の関係性を記述し,borrow checkerを助けることにする.

Lifetime Annotation Syntax

lifetime annotationは変数のlifetimeそのものを変えることはできないが,複数のreferenceを関連付けることが出来る.構文としては,アポストロフィ`'とそれに続くlifetime parameterの名前(ふつう小文字1文字)を書く.'aが最も使われる書き方である.lifetime annotation自体は,referenceの&の直後に書く.たとえば

&i32          // a reference
&'a i32       // a reference with an explicit lifetime
&'a mut i32   // a mutable reference with an explicit lifetime

などと書く.

2017年7月12日水曜日

Gamarnik, Tsisiklis. Fundamentals of Probability 07日目 離散確率変数の期待値

David Gamarnik, and John Tsitsiklis. 6.436J Fundamentals of Probability. Fall 2008. Massachusetts Institute of Technology: MIT OpenCourseWare, https://ocw.mit.edu. License: Creative Commons BY-NC-SA.

Lecture 6. Discrete random variables and their expectations

4. Expected Values(期待値)

4.1 Preliminaries: infinite sums

という級数があるとき,全ての項が非負ならその順番を並び替えても級数の和がもとと同じになる.また,項が必ずしも非負でない場合に並び替えで和が変わらない条件というのは,絶対収束性であった.すなわちをそれぞれ級数から非負の項のみ取り出した和と,負の項のみ取り出した和とするとき,がともに有限であればよかった.
また,という二重のインデックスが振られた数列の和についても,全ての項が非負であるか絶対収束すれば

と書けるのであった.

4.2 Definition of the expectation

random variable X のPMFを要約する値の一つに,expectation(期待値)がある.

Definition 6-2(Expectation)

discrete random variable とそのPMF があるとき,expected value(expectation, or mean)

と定める.これが常にはwell-definedでないことはすでに注意した.

4.3 Properties of the expectation

expectationの別の表現として,が非負の整数値しか取れないなら,

がある.

Proposition 6-3

discrete random variable があるとき,

この定理で,とすると,のexpectationがとわかる.
とも書く.second momentという.より一般に,th momentという.さらに,th central momentといい,特にの2nd central moment variance(分散)といい,とか,と書く.
さらにのvarianceの根をstandard deviation(標準偏差)といい,とか,単にと書く.

Proposition 6-4

同じprobability spaecのdiscrete random variableとする.以下,両辺でそれぞれの値に確定値が定義されているとき

(a)
(b)
(c) に,
(d)
(e)
(f) が独立なら,
(g) が独立なら

Lecture 7. Discrete random variables and their expectations (cont)

1. Comments on Expected Values

(a) がともに有限である場合にのみ有限確定値をもつ.これはと同値である.これを満たすrandom variableはintegrableであるという.
(b) 任意のを許せば常に定義されている.特にであるとき,square integrableという.
(c) から,である.よって,square integrableならばintegrableである.
(d) だから,(i)がsquare integrable ならば (ii) がintegrableだがsquare integrableでないとき,. (iii) がintegrable でないなら,は未定義.

2. Expected values of Some Common Random Variables

(a) Bernoulli
であるとき,

(b) Binomial
とする.このときと,によって書ける.
よって

(C) Geometric
とする.を使う.
から,

(d) * Poisson*
とする.

また,

これは,Poisson分布がBinomial分布のの極限であることからも言える.
(e) Power
であるとき,

これをRiemmanの functionといい,と書く.

3. Covariance and Correlation

3.1 Covariance

Definition

square integrable random variable について,そのcovariance(分散)

と定める.から,がsquare integrableという仮定のもとで,である.

が同じ符号を取りやすいときは,異なる符号を取りやすいときはと考えることができる.よって,の符号はの関係を要約する.
以下にcovarianceの重要な性質をいくつか挙げる.
(a)
(b)
(c)
(d)
また,

である.
が独立であればであって,である.逆は必ずしも成り立たない.

3.2 Variance of the sum of random variables

とすると,

である.特に,

である.

Correlation coefficient

correlation coefficient(相関係数)

と定める.正規化されたcovarianceと考えることができる.

Theorem 7-1

は正のvarianceを持ったdiscrete random variableとする.またを単にとする.このとき
(a)
(b) のとき,の確率が1となるような定数がある.

proof.

(a) とする.Cauchy-Scwartzの不等式より,


(b) なら,

逆に,とすると,である.
ここで

を考えると,というrandom variableが0をとる確率は1である.よって示せた.

4. Indicator Variables and the Inclusion-Exclusion Formula

indicator functionは,event に対して,
と定義され,である.indicator functionによって今後の様々な定理や証明を簡潔に書ける.

4.1 The inclusion-exclusion formula

,またである.
両辺のexpectationを考えると,

これを一般化する.とする.とすると,

が成立.両辺のexpectationを取って,

これをInclusion-exclusion theoremという.

5. Conditional Expectations

によって,にいてのconditional PMF が定義でき,さらににはconditional expectationが定義できる.

Definition 7-2

とdiscrete random variable があるとき,がある時のconditional expectation

と定める.

また,という形のconditional expectationとは,とした場合,すなわち

である.が非負であるかintegrableであるならconditional expectationは有限値を取る.

5.1 The total expectation theorem

の分割とする.random variable
と定める.このときである.したがって

である.

Example(The mean of the geometric)

とする.すなわち.ここで


が成立.コイントスの例をとれば,次の回目のコイントスで表が出る確率は,1回コイントスをした時点で回目のコイントスで表が出る確率に等しいということ.このようなdistributionをmemoryless(無記憶)であるという.


について解いて,.
同様に

から,

これを解いて

したがって

5.2 The conditional expectation as a random variable

をdiscrete random variableとする.を固定するとは実数として定まり,の関数と考えることができる.の関数と考えてと書くとすると,はrandom variableである.

Theorem 7-2

がmeasurableで,が非負かintegrableであるとき,

であって,特にとすれば,である.

proof.

系:
からのestimationと考えられて,はestimation errorである.この定理は,estimation errorがいかなる関数ともcorrelationを持たないことを主張している.

2017年7月9日日曜日

Gamarnik, Tsisiklis. Fundamentals of Probability 06日目 離散確率変数1

David Gamarnik, and John Tsitsiklis. 6.436J Fundamentals of Probability. Fall 2008. Massachusetts Institute of Technology: MIT OpenCourseWare, https://ocw.mit.edu. License: Creative Commons BY-NC-SA.

Lecture 6. Discrete random variables and their expectations

1. A Few Useful Random Variables

の値域がたかだか可算であるときrandom variable をdiscrete random variableといい,そのPMF(probability mass function) は,と一対一に対応するのだった.以下は特に重要なPMFたちである.

(a) Discrete uniform

に,

(b) Bernoulli

に,

(本文ではなのだが,過去に出てきたコイントスの例だと1で表,0で裏を表すようにしていたし,(c)の解説では表の場合の確率をpとしていた.おそらく誤植だろう.)

(c) Binomial

に,

binomial random variableは,表が出る確率のコイントスを回繰り返して回表が出る確率を表している.

(d) Geometric

として,

geometric random variableは表が出る確率のコイントスで回目に初めて表が出る確率を表している.

(e) Poisson

に,

Poisson random variableはbinomial random variableの極限と考えることが出来る.

(f) Power law(冪乗則)

に,

ここで

が成立する.

Notation

上で定義したPMFをそれぞれと略記することにする.またが例えばdU()が定めるPMFを持つとき,と書くように,という記号を導入する.また,
によって,が同じPMFを持つことを示すとする.

1.1 Poisson distribution as a limit of the binomial

Poisson distributionははbinomial distributionのnを大きく,pを小さくした極限で,例えばある年での事故件数のような稀な事象のモデルを作るときによく使われる.この場合はその稀な事象の平均件数を表している.

Proposition 6-1.(Binomial convergence to Poisson)

がすべてのに成立し,とする.このときによってのPMFはのPMFに収束する.つまり,

proof.


を固定してとすると,

よって

2. Joint, Marginal, And Conditional PMFs

2.1 Marginal PMFs

は同じprobability spaceのrandom variableとする.それぞれのprobability lawがPMF によって書けるとき,これらをmarginal PMFとよぶ.(ようするにただのPMF)

2.2 Joint PMFs


で定義されるjoint PMFという.より一般に,というrandom variableたちがあるとき,これらのjoint PMFは

で定義される.random variableのベクトルを定義して,上のjoint PMFを単にと書くことが有る.
のjoint PMFは,によって決められるeventの確率を決めることが出来る.例えば,がある性質を満たす集合とすると,

が成立する.ところで,marginal PMFによって,のmarginal PMFを計算できる.

である.

2.3 Conditional PMFs

が同じprobability spaceのdiscrete random variableであって,joint PMFはであるとする.このときconditional PMFを,

によって定める.定義より

である.

Independence of Random Variables

3.1 Independence of general random variables

random variable がindependent(独立)とは,一方の値が決まってももう一方の値の分布が変わらないということである.形式的には

Definition 6-1 (Independence of random variables)

(a) を同じprobability spaceのrandom variableとする.

が任意のBorel subsetたちになりたつとき,はindependent(独立)であるという.
(b) の独立性は,その任意の有限部分集合の独立性と同値とする.

Proposition 6-2

任意のに,というeventたちがindependentなら,もまたindependent.
(event がindependent )

proof. 略
random variable のjoint CDFを,

と定める.prop.2の観点から,の独立性は

と同値である.

3.2 Independence of Discrete Random Variables

有限個のdiscrete random variableの独立性はjoint PMFがmarginal PMFの積になることと同値である.

Theorem 6-1

はdiscrete random variableとする.以下は同値
(a) は独立
(b) に,というeventは独立
(c)
(d) に,なら

proof.

()

定義より明らか

()

()

明らか

()

仮定のもとで,任意のBorel set

Theorem 6-2

が独立なdiscrete random variableとする.を任意の関数とする.このときというrandom varibaleは独立である

3.3 Examples

Example

を,同じパラメータをもつBernoulli random variableたちとする.とすると,のbinomial random variableである.

Example

を,それぞれのパラメータを持つ独立なbinomial random variableとする.とすると,はパラメータをもつbinomial random variableである.

Example

確率で表が出るコイントスを回行う.を表が出た回数として,とすると,は裏が出た回数のrandom variableである.であるが,から,は独立でない.

一方で,コイントスの回数もまたランダムであるとき,表が出る回数のrandom variableと裏が出る回数のrandom variableは独立になる.をパラメータのPoisson random variableとすると,conditional PMF のbinomialであって,とすると,は独立となる.(次定理)

Theorem 3. (Splitting of a Poisson random variable)

上の条件のもとでは独立であり, である.

The Rust Programming Language 2nd 12日目 Error Handling

https://doc.rust-lang.org/book/second-edition/
Apache License Version 2.0

Error Handling

RustはエラーをRecoverableUnrecoverableに分けている.前者は生じたことをユーザーに知らせてインプットし直させたりして解決しうるエラーであり,後者はarrayの長さよりも大きいindexを指定するような,回復不能なエラーである.
RustではResult<T, E>型によって前者の発生を伝え,後者の場合panic! macro が実行を停止する.この章ではまずpanic!の扱い方を論じてからResult<T, E>を論じる.さらに,エラーから復帰するか停止するかを決めるに当たっての方法論を述べる.

Unrecoverable Errors with panic!

バグが生じて,プログラムがそれをどう処理するかわからないとき,panic! macroはエラーメッセージを出力し,メモリをきれいにしてから実行を停止する.

Unwinding the Stack Versus Aborting on Panic

デフォルトではpanic!によってプログラムはunwinding(解きほぐし?)を始める.unwindingはRustの関数が持っていたデータを削除することである.これには時間がかかるので,ただちにabortしてメモリをそのままにプログラムを停止することもできる.この場合OSがメモリを掃除することになる.プログラムのサイズをできるだけ小さくしたいときはcargo.toml[profile]panic = 'abort'を追加することでabortを指定できる.

試しにpanic!を呼んでみよう.
src/main.rs

fn main() {
  panic!("crash and burn");
}

shell

Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
 Running `target/debug/error_handling`
thread 'main' panicked at 'crash and burn', src/main.rs:2
note: Run with `RUST_BACKTRACE=1` for a backtrace.

エラーメッセージが示すsrc/main.rsの2行目には我々が書いたpanic!があるが,普通のプログラムではエラーメッセージが示している部分を更に我々が書いたコードが呼んでいることが多いので,その場合にはbacktraceによって,我々のコードが孕んでいるバグを見つけることができる.

Using a panic! backtrace

src/main.rs

fn main() {
  let v = vec![1, 2, 3];
  v[100];
}

このコードはvというVectorの割り当てられた範囲外のメモリを参照している.
Cのような言語はこうしたコードを無事コンパイルして,実行時にbufer overreadという危険な状態が生じる.Rustではunrecoverableなエラーを生じ,panic!する.
shell

Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
 Running `target/debug/error_handling`
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 100', /checkout/src/libcollections/vec.rs:1488
note: Run with `RUST_BACKTRACE=1` for a backtrace.

このエラーメッセージにはlibcollections/vec.rsというファイルが含まれる.このファイルでRustはVec<T>型を実装していて,[]vに対して使うときに呼び出される.panic!は実際にはここで起こっているのである.
最終行ではRUST_BACKTRACEを有効にすることでbacktraceを行えることがわかる.実際にやってみよう.
shell

ren@ren-ThinkCentre-Edge72:~/Projects/error_handling$ RUST_BACKTRACE=1 cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/error_handling`
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 100', /checkout/src/libcollections/vec.rs:1488
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:355

   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:371
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:549
   5: std::panicking::begin_panic
             at /checkout/src/libstd/panicking.rs:511
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:495
   7: rust_begin_unwind
             at /checkout/src/libstd/panicking.rs:471
   8: core::panicking::panic_fmt
             at /checkout/src/libcore/panicking.rs:69
   9: core::panicking::panic_bounds_check
             at /checkout/src/libcore/panicking.rs:56
  10: <collections::vec::Vec<T> as core::ops::Index<usize>>::index
             at /checkout/src/libcollections/vec.rs:1488
  11: error_handling::main
             at ./src/main.rs:3
  12: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  13: std::rt::lang_start
             at /checkout/src/libstd/panicking.rs:433
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/rt.rs:57
  14: main
  15: __libc_start_main
  16: _start

11行目で,src/main.rsの3行目がエラーに関係していることを教えてくれる.

Recoverable Errors with Result

殆どのエラーはプログラムをただちに終了させるほどのものではなく,例えば開くファイルをユーザーが指定するときに存在しないパスを入力してしまったときのような,もう一度正しいインプットをするように促すだけですむものもある.Chap.2 でみたように,Result型を使ってこのような状況を扱うことが出来る.ResultOkErrの値を取るEnumであって,以下のように定義されている.

enum Result<T, E> {
  Ok(T),
  Err(E),
}

TEはgeneric type parameterといって,Chap.10で詳しく述べる.今は,Tの場合にOkとともに返す値の型が,Eの場合にErrとともに返す値の型を表すと考えれば良い.

Result型を返す関数を使ってみよう.
src/main.rs

use std::fs::File;

fn main() {
    let f = File::open("hello.txt");
    // File::openはResult型を返す.
    // 正常に読み出すとResult<T>:std::fs::File
    // 読み出しでエラーが生じるとReulst<E>std::io::Error型が入る
}

読み出しに成功するとfOkのインスタンスで,ファイルへのhandleを持つことになり,失敗するとErrのインスタンスでエラーの詳細を持つことになる.
Resultによって挙動を変えるときには以下のようにする.

src/main.rs

use std::fs::File;

fn main() {
  let f = File::open("hello.txt");

  let f = match f{
    Ok(file) => file,
    Err(error) => {
      panic!("There was a problem opening the file \n : {:?}", error)
    },
  };
}

match構文によってfの型で場合分けし,正常な場合はfにハンドラを改めて代入し,異常な場合はpanic!する.このとき,以下のようなエラーが出力される.
shell

thread 'main' panicked at 'There was a problem opening the file
: Error { repr: Os { code: 2, message: "No such file or directory" } }', src/main.rs:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Matching on Different Errors

先程はOkErrかのみで分岐したが,Errの内容によってさらに分岐することも出来る.例えば,File::openが,開くファイルが存在しないためにエラーを出した場合,新しくそのファイルを作れば復帰できる一方で,開くファイルへのパーミッションを持っていないときにはpanic!したいとする.このときは,以下のように書く.
src/main.rs

use std::fs::File;
use std::io::ErrorKind;
fn main() {
  let f = File::open("hello.txt");

  let f = match f {
    Ok(file) => file,
    Err(ref error) if error.kind() == ErrorKind::NotFound => {
      match File::Create("hello.txt") {
        Ok(fc) => fc,
        Err(e) => {
          panic!{
            "tried to create file but there was a problem: {:?}",
            e
          }
        },
      }
    },
  };
}

Propagating Errors

関数が別の何かを呼んで,その何かがエラーを生じたときに,もとの関数がそのエラーの内容によって分岐するように出来る.これをpropagatingといい,もとの関数がエラーをどう処理するかを関数の他の内部状態で決めたいときに使われる.
以下のコードでread_username_from_fileを呼んだ関数はResultを返される.
src/main.rs, list9-5

use std::io;
use std::io::Read;
use std::fs::File;

fn read_username_from_file() -> Result<String, io::Error> {
  let f = File::open("hello.txt");

  let mut f = match f{
    Ok(file) => file,                 // fにファイルへのハンドラを代入
    Err(e) => return Err(e),          // Err(io::Error)
  };

  let mut s = String::new();

  match f.read_to_string(&mut s) {    // sにfの中身を(あれば)代入
    Ok(_) => Ok(s),                   // Ok(String)
    Err(e) => Err(e),                 // Err(io::Error)
  }
  // 返される値はResult型であり,呼んだ関数がエラー処理を行うことになる.
}

fn main() {
    let result = read_username_from_file();
    println!("The return result is \n : {:?}", result);
}

shell

Running `target/debug/error_handling`
The return result is
: Err(Error { repr: Os { code: 2, message: "No such file or directory" } })

簡潔に書く方法に?キーワードを使う方法が有る.

A Shortcut for Propagating Error: ?

先ほどと同じ機能を持つ関数を?を使って書く.
src/main.rs, list9-6

use std::io;
use std::io::Read;
use std::io::File;

fn read_username_from_file() -> Result<String, io::Error> {
  let mut f = File::open("hello.txt")?;
              // Okならfは中身(ハンドラ)をfに代入し継続
              // Errなら関数を終了してResultを呼んだもとに返す

  let mut s = String::new();
  f.read_to_string(&mut s)?;
              // Ok ならstatementはread_to_stringのOkの中身
              // Errなら関数を終了してResultを呼んだもとに返す
  Ok(s)
}

Result型の後に?がつくと,Okの場合はその中身を返し,関数を継続する.Errの場合はそれを呼んだもとに返してただちに関数を終了する.
list9-6はさらに簡潔に書ける.
src/main.rs, list9-7

use std::io;
use std::io::Read;
use std::fs::File;

fn read_username_from_file() -> Result<String, io::Error> {
  let mut s = String::new();

  File::open("hello.txt")?.read_to_string(&mut s)?;
  Ok(s)
}

? Can Only Be Used in Functions That Return Result

Err?をつけると,Err自体がその関数の返す値になるので,?キーワードを使う関数は最初から返り値の型がResultでなければならない.

To panic! or Not To panic!

多くの場合panic!でプログラムを落とすより,条件分岐を使って通常の状態に復帰することを考えるべきだが,panic!を使うべき場面もいくつか存在する.

Examples, Prototype code, and Test: Perfectly Fine to Panic

サンプルコードや青写真を書くときには,高度なエラーの取扱はロジックをわかりにくくする恐れが有るし,unwrapexpectのほうが明瞭にどこでエラーが起きたかわかりやすい場合が有る.テストを行う場合も同様である.

Cases When You Have More Infromation Than The Compiler

必ずResultOkとなるような仕組みが有るときは,unwrapexpectを使ってErrの場合の処理を書くのを省略できる.例えば

use std::net::IpAddr;
let home = "127.0.0.1".parse::<IpAddr>().unwrap();

とする.”127.0.0.1”は有効なIPアドレスだからparseは成功するはずだが,parseは本質的にResultを返すmethodだから,Errが返されたときの処理も書かないとコンパイラに怒られる.これを回避して簡潔に書くため,単にunwrapを使える.
仮にIPアドレスをユーザーが入力するプログラムなら,無効なIPアドレスを入力される場合が考えられるので,Resultによってエラー処理を書くほうが良い.