スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門第33回(命令型プログラミング(5)Loop)

今回のお題は「命令型プログラミング(5)Loop」です。
 
まずは宿題の解答から
(宿題)arrays(配列)int []型 が与えられたとき、要素数(長さ)が5のときだけ、和をSomeでくるんで返し、それ以外のときはNoneを返す関数 sum5arrayを次につづけて定義してください。
let sum5array (a : int []) =
 
(解答例1)
 
let sum5array (a:int []) =
    match a with
    |[|x;y;z;u;v|] -> Some (x+y+z+u+v)
    | _            -> None
 
実行例
 
> sum5array [|7;3;5;5;10|];;
val it : int option = Some 30
 
> sum5array [|7;3;5;|];;
val it : int option = None
 
リストならば、List.lengthとList.foldを使うコードを使う解答が一般的だと思います。
じつは、ArrayもListと同じような関数を多数持っていて、Array.lengthもArray.foldも、ライブラリにありますので、これを使ってみます。
 
(解答例2)
 
let sum5array (a:int []) =
    if (Array.length a = 5) then
        Some (Array.fold (+) 0 a)
    else
        None
 
さて、今回の話題はLoopです。Loopにはwhile loop とfor loopがありますが、まずはwhile loopから。
 

 
let mutable i = 0
while (i < 3) do
    i <- i + 1
    printfn "i = %d" i
    
実行例

i = 1
i = 2
i = 3
 
val mutable i : int = 3
 
while の後には、trueかfalseを返す式を書きます。この式はループが始まる前にチェックされ、tureならwhileのdo以下の部分が評価された後、再びtrueかfalseか評価されます。最終的にこの式がfalseと評価されるまで同じことが繰り返されます。
さてそれでは、次のコードを実行するとどうなるでしょうか?
 
let i = 0 // (1)
while (i < 3) do //(2)
    let i = i + 1 //(3)
    printfn "i = %d" i //(4)
 
答えは、「ずっとi=1と表示され続ける。」です。
(2)における、iは(1)で定義導入されたiですから、ずっと値は0のままです。
(3)でやっているのは、iという名前の同名の識別子の導入で,右辺の評価時に、スコープ内にあるiは(1)のi(値0)なので、1が束縛され、i = 1と表示されます。再び(3)に戻ってきても、右辺の評価時に、スコープ内にあるiは(1)のi(値0)なので、ずっとi=1と表示され続けます。
くれぐれも、whileやforでの、終了条件は、mutableな値で扱うようにしましょう。当たり前ですが、immutable(不変)な値をつかうと、一回も実行されないか、永遠に実行し続けるかのどちらかになります。
 
上を再帰版で書くと、たとえば次のようになります。
 
let rec test00 ct =
    if ct >= 3 then
        ()
    else
        printfn "ct = %d" (ct + 1)
        test00 (ct + 1)
test00 0
 
ちなみに、F#のwhile loopにはbreak や continueはありません。
 
つぎにfor loopに入ります。
 
まずは単純な形で、整数で、ある値からある値まで、カウントアップもしくは、カウントダウンする形です。
 

 
let mutable sum = 0
for i = 1 to 10 do
    sum <- sum + i
printfn "sum = %d" sum
 
ちなみにリスト版は
 
printfn "sum = %d" (List.fold (+) 0 [1 .. 10])
 
再帰関数版は
 
let rec mySum accum i =
    if i > 10 then
        accum
    else
        mySum (accum + i) (i + 1)
 
printfn "sum = %d" (mySum 0 1)
 
カウントダウン版は
 
let mutable sum = 0
for i = 10 downto 1 do
    sum <- sum + i
printfn "sum = %d" sum
 
となります。
 
最後に一番応用力のある、for loopを紹介します。
これは、一つずつ要素をとりだしてこれるようなタイプ(seq typeといいます。詳しくはまた、紹介したいと思いますが、seqはsequence(数列)の先頭の3文字で、例えば、listやarrayがseq typeです。)に対して、ひとつずつパターンマッチをして、その結果マッチすれば、do以下が評価されていくという形です。

for i in [1 .. 5] do
    printfn "%d" i
実行例
1
2
3
4
5
val it : unit = ()
 

for Some (i) in  [Some (7) ; None; Some (2)] do
    printfn "%d" i
実行例
7
2
val it : unit = ()
 
例(要素数が2のリストの要素を表示)
 
for [x;y] in  [[1;2;3];[4;9];[];[1];[2;5]] do
    printfn "%d %d"x y 
 
実行例
 
4 9
2 5
val it : unit = ()
 
それでは宿題です。
discriminated unionとリストが次のように定義されているとします。
 
type Fig =
    | Triangle of float*float*float
    | Rectangle of float*float*float*float
 
let figLst  =[Triangle(3.0,2.0,2.0);Rectangle(1.0,1.0,1.0,2.0);
              Triangle(5.0,6.0,3.0);Rectangle(2.0,1.0,2.0,3.0)]
 
このとき、for loopを使って、Triangleの3つの要素を
三辺の長さは3.000000と2.000000と2.000000です。
三辺の長さは5.000000と6.000000と3.000000です。
というように表示してください。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。