スポンサーサイト

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

F#入門第20回(リストを引数にとる関数(3)とprintf)

今回のお題は「リストを引数にとる関数(3)とprintf」です。
 
まずは宿題の答えです。
 
(1)F#にはfloat 型のリストを引数にして、それの平均を返す関数List.averageが準備されていますが、List.fold とList.lengthを使って自分でmyListAveを定義してみてくだい。
引数が[]の時のことは、考えなくてもよいです。
(Hint :vをfloat 型に変換するにはfloat v とします。)
 
(答え)
 
let  myListAve lst  =
    (List.fold (+) 0.0 lst) / (float (List.length lst))
 
(2)float*floar型のタプルのリストを引数にして、タプルの第一成分が第二成分より大きい要素の個数、等しい要素の個数、小さい要素の個数をタプルにして返す関数myCountを定義してください。
例えばmyCount [(2.0,1.1);(3.0,3.0)]は(1,1,0)を返します。
 
(答え)
 
let myCount lst =
    let grow (mt,eq,lt) (a,b) =
        if a > b then
            (mt+1,eq,lt)
        elif a = b then
            (mt,eq+1,lt)
        else
            (mt,eq,lt+1)
    List.fold grow (0,0,0) lst
    
(注意)実際には(float*float) list 型だけでなく、('a * 'a) list 型に適用できる関数になってます。(ただし、型'aには比較演算子が定義されていることが必要)
 
実行例
 
> myCount [(2.0,1.1);(3.0,3.0)];;
val it : int * int * int = (1, 1, 0)
 
> myCount [(2,1);(3,3)];;
val it : int * int * int = (1, 1, 0)
 
今回は、まずはprintfという関数を紹介したいと思います。(すでに、何回か出てきてますけど)
まずは、型を調べてみます。
 
> printf;;
val it : (Printf.TextWriterFormat<'a> -> 'a) = <fun:clo@0>
 
ここで、Printf.TextWriterFormat<'a>というのは型'aに対して、どのような形で出力するかという形式になります。いくつか例をあげてみます。
 
> printf "値は%d" 3;;
値は3val it : unit = ()
 
"値は%d"の%dの部分にint型の数値3を組み込んで表示してくれます。
string 型に対しては%s,float型に対しては%f,char 型に対しては%cが使われます。
あと、珍しい形として、どんな型に対しても、適当に表示してくれる%Aというのがあります。

 
> printf "値は%A" ([1;2],(3,4),'a',"this");;
値は([1; 2], (3, 4), 'a', "this")val it : unit = ()
 
改行が必要な時はprintf で\nを使うか、printfnを使います。
 
> printf "%A \n" (1,2);;
(1, 2) 
val it : unit = ()
 
> printfn "%A" (1,2);;
(1, 2)
val it : unit = ()
 
型を見ても分かるように、部分適用もできます。
 
> let myPrintInt = printf "その値は%dだよ。\n";;
val myPrintInt : (int -> unit)
 
> myPrintInt 7;;
その値は7だよ。
val it : unit = ()
 
文字列を作りたいときは、sprintfを使います。
 let s = sprintf "その値は%dです。" 15;;
val s : string = "その値は15です。"
 
それでは、List.iterを紹介したいと思います。
まずは型を調べてみます。
 
> List.iter;;
val it : (('a -> unit) -> 'a list -> unit) = <fun:clo@0>
 
この関数はリスト内の各要素('a型)に('a -> unit)型の関数を次々に適用させていく関数です。返り値はunit型すなわち()です。
これは、リストの要素を次々表示したりするのに、よく使われたりします。
 

 
> List.iter (fun x -> printfn "%d" x) [3;2;1];;
3
2
1
val it : unit = ()
 
それでは、リストを引数にして、「0番目は何だ」、「1番目は何だ」と改行しながら、表示する関数を作ってみます。名前はmyListPrintfnとします。
 
let myListPrintfn lst  =
    let forPrint i v =   //vを表示しながら、種であるindexを増やす関数
        printfn "%d :: %A" i v //表示
        i + 1                    //インデックスを一つ増やして
                                 //次の種にする
    List.fold forPrint 0 lst
    
実行例
> myListPrintfn [5;4;3;2;1];;
0 :: 5
1 :: 4
2 :: 3
3 :: 2
4 :: 1
val it : int = 5
 
ほぼ予定道理に動きましたが、ただ返り値として育ちきった種(index)の5が返って来ました。これは、余分なので、無視してunit型を返すようにします。
このようなとき、使うのがignoreという関数です。
調べてみます。
 
> ignore;;
val it : ('a -> unit) = <fun:clo@0-1>
 
よって、これを使って最後の返り値であるList.fold forPrint 0 lstを包みます。
 
let myListPrintfn lst  =
    let forPrint i v =
        printfn "%d :: %A" i v
        i + 1
    ignore (List.fold forPrint 0 lst)
    
実行例
 
> myListPrintfn ['a';'b';'c'];;
0 :: 'a'
1 :: 'b'
2 :: 'c'
val it : unit = ()
 
> myListPrintfn [(1,2);(2,5);(3,9);(1,6)];;
0 :: (1, 2)
1 :: (2, 5)
2 :: (3, 9)
3 :: (1, 6)
val it : unit = ()
 
またList.initという関数があり、これは次のように、リストを作ってくれます。

 
> List.init 10 (fun x -> x);; 
val it : int list = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]
 
> List.init 10 (fun x -> 2*x-1);; 
val it : int list = [-1; 1; 3; 5; 7; 9; 11; 13; 15; 17]
 
型は
 
> List.init ;;
val it : (int -> (int -> 'a) -> 'a list) = <fun:clo@0-2>
       (要素数) (要素を作る関数)(結果)
 
ただ、関数に0から、(要素数-1)が代入されることに注意してください。
これを使うと先ほどの関数は次のようにも書けます。
 
let myListPrintfn lst  =
    let iLst = List.init (List.length lst) (fun x -> x)
    let tupLst = List.zip iLst lst
    ignore( List.map (fun (i,v) -> printfn "%d :: %A" i v) tupLst )  
 
それでは宿題です
色々な型のものを,文字列に直すmy_any_to_stringという関数(引数一つ)を定義してください。(ヒント sprintfを使ってください。)
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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