スポンサーサイト

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

F#入門第12回(関数を複数行で書く)

今回のお題は「関数を複数行で書く」です。
 
まずは宿題の答えから。
(1)一つの引数をとり、3加えた数を返す関数plus3を(+)と部分適用を利用して定義してください。
(答え)
> let plus3 = (+) 3;;
val plus3 : (int -> int)
 
(実行例)
> plus3 5;;
val it : int = 8
 
(2)一つの引数をとり、それが2より大きいときtrue、それ以外のときfalseを返す関数isMorethan2 を(<)か(>)と部分適用を利用して定義してください。
 
(答え)
> let isMorethan2 = (<) 2 ;;
val isMorethan2 : (int -> bool)
 
(実行例)
> isMorethan2 1;;
val it : bool = false
 
(3)二つのfloat型の数に対し、これらの和の2乗を返す中置演算子 $++を定義してください。
 
(答え)
> let ($++) (x : float) y = (x + y) * (x + y);; 
val ( $++ ) : float -> float -> float
 
(実行例)
> 1.5 $++ 3.5 ;;
val it : float = 25.0
 
それでは今回の内容です。
以前、最初に関数を定義したとき次のような方法で行いました。
fun x -> x + 1
これは、まだ名前が付いていませんので「匿名関数(anonymous function)」といいます。
また「関数式(function expression)」とか「ラムダ式lambda expression)」ともいいます。
形としては fun 仮引数 -> body という形をしています。
関数は実際の値について呼び出されたときに、body内の仮引数の部分が実際の値として、次々計算され(評価evaluate)されてゆき、何らかの値が返されるわけです。
 
次に名前の付け方ですが、let 構文を使い
let iden = (fun args -> body)と名前をつけるのでした。(idenは識別子、argsは引数、bodyは本体です。)
これの略記が
let iden args = bodyなのでした。
 
F#のライトシンタックスを使ってコードを書く場合スペース(インデント)が重要な役割を果たします。(スコープ等がこれによって、コントロールされるのです。)
 
let iden args = body の複数行のパターンは、
 
let iden args =
    body01
    body02
    ......
    bodyEnd
 
というように、body部分をインデントします。(頭は揃えます。)
body01からbodyEndまではそれぞれ、式(expression)(大雑把に言うと、仮引数が実際の値で置き換わっていったとき、評価(計算)されて、値を返すもの)や、let構文(値は返しません)等です。
全体としての返り値として、body01からbodyEndまでで、一番最後に評価された式の値が返されます。
 

let plus1 x =
    x + 1
 
上の例で例えばplus1 2 とすると、xが2に置きかわり、x + 1 は 2+1 となり、3と評価(計算)されます。これが、一番最後に評価された式なので、3が返ります。
 

let cir r =
    let pi = 3.1415
    2.0*r*pi
 
この例で例えばcir 3.0 とすると、rが3.0に置き換わります。2行目のlet 構文ではpiが3.1415に束縛されます。さらに、3行目で2*r*piが2*3.0*3.1415と評価され、18.849が返り値として返されます。
 

let cir2 r =
    let pi = 3.1415
    let result = 2.0 * r * pi
    
この例ではエラーが出ます。let構文だけで、最後に式が存在しないからです。
次のようにすればOKです。
 
let cir2 r =
    let pi = 3.1415
    let result = 2.0 * r * pi
    result
    
また次のように、インデントもできます。
 
let cir2 r =
    let pi = 
         3.1415
    let result = 
        2.0 * r * pi
    result
 
次は直径を与えて面積を返す関数Areaの例です。
 
let Area diameter = 
    // ここより後ろに書かれている部分は関数"Area"のbody 
    let pi = 3.14   // 関数内での値の定義 
    let Radius d =  // 関数内での関数の定義 
        // これは関数"Radius"のbody 
        d / 2.0 
    let r = Radius diameter 
    pi * r * r 
    
どうでしょう、この例では関数が入れ子になってます。
 
また、式が長くなって途中を改行をするときは、式の先頭部分より、後ろにずらすことに注意してください。
 

 
let k = 1 + 2 + 3 + 4 + 5//これはok
 
次のように改行してはダメ
let k = 1 
+ 2 + 3 + 4 + 5
 
次はダメ
let k = 1 
    + 2 + 3 + 4 + 5
 
次はOK
let k = 1 
       + 2 + 3 + 4 + 5
 
次もOK
let k =1 + 2 
       + 3 
       + 4 
       + 5
 
変に並べると分かりにくいので、普通は=の後ろのポジションくらいに、並べます。
こんな感じです。
 
let k = 1 + 2 + 3 + 
          4 + 5

 
とにかく、複数行にかかる、関数を書くには次のことに注意しましょう。
(1)最後に値を返す式を置く。
(2)入れ子構造になった時に、さらにインデントする。
(3)長い式を改行するときは、その式の頭くらいに、インデントする。
 
また複数行にわたって、コメントを書くときは(* と *)で囲めばよいです。

(* これは
    複数行に
    わたる
    コメント *)
 
 
それでは、宿題です次のような関数を定義してください。
二つのfloat型の数を引数にして、足して2で割った数(相加平均)から、掛け合わせて平方根をとった数(相乗平均)を引いた数をかえす関数test。
ただし、testの内部で、二数から相加平均を返す関数ave1と二数から相乗平均を返す関数ave2を定義して、これを使って値を返してください。引数が正かどうかの確認は要りません。
(平方根を返す関数は、sqrt です。)

 

スポンサーサイト

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

コメントの投稿

非公開コメント

No title

いつもこのサイトで勉強させてもらっています。
誤字の指摘ですが、「インシデント」ではなく「インデント」が正かと思います。

No title

御指摘ありがとうございます。訂正しました。(ずーっとインシデントだと思い込んでおりました。お恥ずかしい限りです。)
プロフィール

T GYOUTEN

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

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

この人とブロともになる

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