= Kokaチュートリアルの適当日本語訳 = <> <
> これはC/C++やC#、JavaScriptなどのプログラマのためのKokaプログラミング言語の短い紹介文です "Koka"は副作用を伴う計算から純粋な値を分離した''function-oriented''(関数指向?)な言語です('効果'の意味は英語でいうところの"effect"や"effective"です)。Kokaは柔軟で、ラージスケールなプログラムにおいてもデータの型の変更を容易にし、コードを正しくまとめる手助けを行うような機能を豊富に持っていて、JavaScriptに似た文法で小さな強い型付けを言語機能として持っています より多くの背景情報が必要な場合は[[http://research.microsoft.com/en-us/projects/koka|Koka research page]]やLang.(2012/8)で発表した際の[[http://research.microsoft.com/en-us/projects/koka/2012-overviewkoka.pdf|スライド]]を見てください == Hello world == 慣習に倣って、まずは''Hello world''プログラムから始めましょう {{{#!highlight javascript function main() { println("Hello World!") //println output } }}} 関数は'''function'''か'''fun'''キーワードを使うことで定義されます。慣習的には'''function'''キーワードはトップレベルに対して、'''fun'''キーワードは無名関数に対して使用されます == シーザー暗号化 == ここでは文字列をシーザー暗号によって文字列中の小文字をアルファベットで3つだけ大きい方向に置き換える短いプログラム例を示します {{{#!highlight javascript function encode( s : string, shift : int ) { fun encodeChar(c) { if (c < 'a' || c 'z') return c base = (c - 'a').int rot = (base + shift) % 26 return (rot.char + 'a') } s.map(encodeChar) } function caesar( s : string ) : string { s.encode( 3 ) } }}} この例では、''encodeChar''という1文字を受け取り、エンコードするローカル関数を定義しています。最後の文では''s.map(encodeChar)''のように、''encodeChar''関数をstring型な''s''内の文字に対してそれぞれ適用し、シーザー暗号化された新しい文字列を返しています。関数内の最終文の結果も関数の値として返されますが、ふつうは明示的に'''return'''キーワードで関数を抜けます このサンプルでは各文の終わりのセミコロンや定義がないことが見て取れます。"Koka"に文にセミコロンを自動で追加させたり、ブレース("{"と"}"のことです)の間で整理された形で定義を自動で入れさせたりすることでシンプルなレイアウト規則を使うことができます。長い文はさらにインデントを使うことで次の行に記述することができます。もちろん、必要であれば1行に複数の文を記述するなどのようにいつでもセミコロンを入れることができます "Koka"は(例のオブジェクトとは対照的に)関数やデータを言語のコアから生成するような''function-oriented''な言語です。特に、''s.encode(3)''という式はstring型のオブジェクトから''encode''メソッドが選ばれているわけではなく、''s''が最初の引数となる''encode(s,3)''のような関数呼び出しの単純な糖衣構文です。同じように、''c.int''は''int(c)''を呼ぶことで文字を整数に変換しています(どちらの式も同値です)。ドット記法は {{{#!highlight javascript fun showit( s : string ) = s.encode(3).length.println }}} のように複数の呼び出しをまとめてチェインすることができ、直感的で非常に便利なものです。この例ではこの式は''println(length(encode(s, 3)))''に解釈されます。関数呼び出しの糖衣構文としてのドット記法の利便性はちょうど第1引数として型をとるような新しい関数を書くように、任意のデータ型をとる"組み込み"関数の拡張を簡単にするところです。ほとんどのオブジェクト指向言語では、例としてクラスがライブラリから提供されているような場合、クラス定義自身へメソッドを追加する必要がますが、これはいつでも可能というわけではありません == 型 == "Koka"は強い型付け言語です。ほとんどの型を推論できるような強力な型推論機構を使用し、ふつう、型が邪魔となることはありません。特に、いつでもローカル変数の型を省くことができます。これは例の''base''と''rot''からもわかります。関数の引数や関数の返り値の型を書いておくことで型推論を補助することができ、また、コンパイラからよりよいフィードバッグとともに便利なドキュメントを提供できます ''encode''関数において、''s''引数の型情報はlist型とstring型のどちらにも定義された''map''関数からいえるように型の注釈がない多相的なプログラムにおいて肝心です == 無名関数 == "Koka"は無名関数式が許されています。例として、''encodeChar''関数を定義する代わりに、''map''関数に関数式を直接渡してみましょう {{{#!highlight javascript function encode2( s : string, shift : int ) { s.map( fun(c) { if (c < 'a' || c 'z') return c base = (c - 'a').int rot = (base + shift) % 26 return (rot.char + 'a') }); } }}} 少しばかり、最後のブレースのあとの括弧がうっとおしいですね。"Koka"は便利なことに、関数呼び出しの代わりに無名関数を渡すことが許されています。たとえば、次の例では1から10までの数字を表示します {{{#!highlight javascript function print10() { for(1,10) fun(i) { print(i) } } }}} これは ''for( 1, 10, fun(i){ print(i) } )''に解釈されます。実際には、''i''を直接引数として''println''に渡していますが、''(1,10,println)''と書くことで、直接関数に渡すこともできます。 引数なしの無名関数は''fun''キーワードを除去し、"()"を除去するようなより短い記述が可能です。たとえば {{{#!highlight javascript function print10() { repeat(10) { println("hi") } } }}} この分は''repeat( 10, fun(){println("hi")} )''に解釈されます。この記法は特に、"Koka"の組み込み演算子ではないけど、ふつうの関数であるような''while''ループを記述するような場合に有用です。例えばこんな風に {{{#!highlight javascript function print11() { var i := 10 while { i >= 0 } { println(i) i := i-1 } } }}} "Koka"はいつでも明示的に、コードが(ブレースの間の)関数が呼ばれる前に評価されたり(潜在的に複数回の)呼び出された関数(ブレースの間)によって評価される、ということを行います。 == 効果 == "Koka"には自動で関数の内部で副作用が発生するかを推論することができる奇抜な機能があります。任意の作用がないことは''total''(あるいは''<>'')で表され、純粋数学関数と同じものとなります。もし関数が例外を上げるならば、作用は''exn''となり、関数が終了しないかもしれない場合は、作用は''div''(分岐を意味している)となります。''exn''と''div''の組み合わせは''pure''となり、ちょうど、Haskellの純粋性の概念と直接対応しています。非決定的な関数は''ndet''作用によって得ることができます。'''最悪'''の作用は''io''であり、それはプログラムが例外を上げたり、終了しなかったり、非決定的であったり、ヒープに読み書きを行ったり、任意の入出力操作を行うことを示しています。次のサンプルでは作用が現れる関数についての例を示しています。 {{{#!highlight javascript function square1 x : int ) : total int { return x*x } function square2( x : int ) : io int { println( "a not so secret side-effect" ) return x*x } function square3( x : int ) : div int { square3( x ) return x*x } function square4( x : int ) : exn int { error( "oops" ) return x*x } }}} ''total''作用であるとき、普通は次のように型注釈を省きます。 {{{#!highlight javascript function square5( x : int ) : int = x*x }}} 時には作用のある関数を書きますが、明示的に作用を書き下すのは面白くありません。そのような場合においては推論型を表す''ワイルドカード型''を使うことができます。ワイルドカード型はアンダースコアが付加されている識別子を記述するかアンダースコア自身を記述することで表されます。例えば次のように {{{#!highlight javascript function square6( x : int ) : _e int { println("I did not want to write down the io effect") return x*x } }}} ''_e''で推論された作用を表しています。 == 意味論 == == オプション引数と名前付き引数 == == さらなるデータ型 == == マッチ == todo