スポンサーサイト

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

F#入門第13回(モジュールとスコープ)

今回のお題は「モジュールとスコープ」です。
 
まずは宿題の答えから。
 
(宿題)
二つのfloat型の数を引数にして、足して2で割った数(相加平均)から、掛け合わせて平方根をとった数(相乗平均)を引いた数をかえす関数testを定義してください。
ただし、testの内部で、二数から相加平均を返す関数ave1と二数から相乗平均を返す関数ave2を定義して、これを使って値を返してください。引数が正かどうかの確認は要りません。(平方根を返す関数は、sqrtです。)
 
答えは例えば次のようになります。
 
 let test x y =
    let ave1 u v = 
        (u + v) / 2.0
    let ave2 u v =
        sqrt (u * v)
    (ave1 x y) - (ave2 x y)
    
それでは今回の内容です。
コードが大きくなってくると、管理が難しくなってくるので、プログラムをある程度の大きさのグループで、グループ分けすることが役にたちます。グループ分けの方法の一つがモジュールという考え方です。特に自分で指定せずに、ソースファイルをつくると、一つのソースファイル(**.fs)が、一つのモジュールを形成します。このような一つのファイル全体で構成されるグループをトップレベルモジュールといいます。特に指定しない場合は、ファイル名の先頭を大文字にしたトップレベルモジュール名が暗黙的かつ自動的につきます。
(例 ファイル名がprogram.fsなら、トップレベルモジュール名はProgram)
自分でトップレベルモジュールに特に名前を付ける場合は,ソースファイルの先頭で
module 名前 とします。
(トップレベルモジュールにさらに含まれるローカルモジュールというのもありますが、これについては後日紹介したいと思います。)
 
次はスコープの話です。
F#のプログラム中で、定義された値はそれぞれ、「どこからは見える」というように、見える範囲があります。これを、スコープといいます。
F#では、基本的に値はモジュールスコープをもちます。これは、定義された後であれば、同一モジュール内のどこからでも使えるということです。
ただ、関数の中で定義された値は、その関数内でしか、使うことができません。
 

 
let a = 7
let b = a + 7 //同一モジュール内なのでaにアクセス可能
let kansuu x y =
    let c = 9
    x + y + a + b + c //同一モジュール内なのでa,bにアクセス可能
                      //また、関数の中で定義されたx,y,cにもアクセス可能
let d = a + c //これは、エラー
              //(cは関数の中で定義された値なので、ここからはアクセス不可)
 
次に関数の中で関数を定義した場合を見ていきます。(これをネストされた関数といいます。)
 
例(意味不明な関数ですが、スコープだけを見てください。)
 
let parentFunc x y =
    let a = 2
    let childFunc1 u =
        let b = 3
        x + a + u + b + 4//上のレベルの親関数内のx,y,aにアクセス可能
    let childFunc2 v =
        y + v + b + 5//これは、エラー y,vにはアクセス可能だが、
                 //同一レベルで定義されたchildFunc1内で定義された
                 //bにはアクセス不可
    5 
 
さて次に同一の名前(識別子)を複数回定義すると、どうなるかを調べていきます。
モジュールレベルではエラーになることに留意しておいてください。
次に関数内ですが、これはエラーになりません。次の例を見てください。
 
let test x =
   let k = 3 //この行までは、k=3
   let k = 30//この行で、kという同名の識別子
             //が導入されるので,この行以下では
             //上の行の3に束縛されているkにはアクセス不可能になる
   x + k     //この時はkの表す値は30
   
コメントをつけておきましたが、例えばkという名の識別子を導入し、ある行でのkの値を調べるとき、スコープ内で一番近いkの値が与えられます。
kの値が変わっているのではなく、(kは値に束縛されて不変(immutable)であることを思い出してください。)同名の識別子で、近い方の値をとってきていることに注意してください。
 
次の例をみてください。
 
let test2 x =      //1
     let x = x + 1  //2
     let x = 2 * x  //3
     x // 4
    
例えばこの関数を3に適用すると1行目で、まずxが3となります。次に2行目の右辺を評価しますが、これは3+1で4となります。これが2行目のxに束縛されます。次に3行目の右辺を評価しますが、スコープ内にあって、一番近いxは2行目で4に束縛されたxですから、2*4で8と評価され、3行目のxは8に束縛されます。4行目では、スコープ内にあって、一番近いXは3行目の8に束縛されたxなので、4行目は8と評価され、この値が返り値となります。
 
それでは宿題です。
次の(*1*)から(*5*)までのそれぞれの場所でアクセス可能な識別子(a,b,c,x,y,z)をすべて答えてください。(この関数はなんの意味もない関数です)
 
let a = 1
let test x  =
    (*1*)
    let b = 2
    let sub1 y =
        (*2*)
         y
    let sub2 z =
        (*3*)
         z
    (*4*)
    x 
    
(*5*)
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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