OCaml

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ
OCaml
OCaml Logo.svg
パラダイムマルチパラダイム機能的命令型モジュラー型[1] オブジェクト指向
家族ML
によって設計されたXavier Leroy、JérômeVouillon、Damien Doligez、 DidierRémy、AscánderSuárez
デベロッパーINRIA
初登場1996 ; 26年前 (1996
安定リリース
4.13.1 [2] ウィキデータでこれを編集する / 2021年10月1日; 4ヶ月前 (2021年10月1日
規律の入力推測された、静的な強い構造的な
実装言語OCaml、C
プラットホームIA-32x86-64PowerSPARCARM 32-64
OSクロスプラットフォームUnixmacOSWindows
ライセンスLGPLv2.1
ファイル名拡張子.ml、.mli
Webサイトocaml .org
に影響を受けた
CCamlModula-3PascalStandard ML
影響を受ける
ATSCoqElmF#F *HaxeOpaRustScala

OCaml/ oʊˈkæməl / oh - KAM - əl、以前はObjective Caml は、オブジェクト指向機能を備えたMLのCaml方言を拡張する、汎用マルチパラダイムプログラミング言語です。OCamlは、1996年に、Xavier Leroy、JérômeVouillon、Damien DoligezDidierRémy 、AscánderSuárezなどによって作成されました。

OCamlツールチェーンには、インタラクティブなトップレベルインタープリターバイトコード コンパイラー、最適化ネイティブコードコンパイラー、リバーシブルデバッガー、およびパッケージマネージャー(OPAM)が含まれています。OCamlは当初、自動定理証明のコンテキストで開発され、静的分析および形式手法ソフトウェアで非常に大きな存在感を示しています。これらの領域を超えて、他のアプリケーションドメインの中でも 、システムプログラミングWeb開発、および金融工学で真剣に使用されています。

頭字語のCAMLは元々CategoricalAbstract Machine Languageの略でしたが、OCamlはこの抽象機械を省略しています。[3] OCamlは、フランス国立情報学自動制御研究所(INRIA)によって管理および保守されている、無料のオープンソースソフトウェアプロジェクトです。2000年代初頭、OCamlの要素は多くの言語、特にF#Scalaに採用されました。

哲学

MLから派生した言語は、静的型システム型推論コンパイラで最もよく知られています。OCamlは、MLのような型システムの下で、機能的命令的、およびオブジェクト指向プログラミングを統合します。したがって、プログラマーはOCamlを使用するために純粋な関数型言語パラダイムに精通している必要はありません。

OCamlは、静的型システムの制約内で作業することをプログラマーに要求することにより、動的型付け言語に関連する型関連のランタイム問題の多くを排除します。また、OCamlの型推論コンパイラは、ほとんどの静的型付け言語で必要とされる手動の型注釈の必要性を大幅に減らします。たとえば、変数のデータ型と関数のシグネチャは、 JavaC#などの言語のように、通常は明示的に宣言する必要はありません。、コード内の変数やその他の値に適用される演算子やその他の関数から推測できるためです。OCamlの型システムを効果的に使用するには、プログラマーの側である程度の洗練が必要になる場合がありますが、この分野には信頼性の高い高性能ソフトウェアが備わっています。

OCamlはおそらく、パフォーマンスに重点を置いていることで、学界を起源とする他の言語と最も区別されています。その静的型システムは、実行時の型の不一致を防ぎ、動的に型付けされた言語のパフォーマンスに負担をかける実行時の型と安全性のチェックを不要にし、配列境界チェックがオフになっている場合やシリアル化などの型に安全でない機能が使用されている場合を除いて、実行時の安全性を保証しますこれらは非常にまれであるため、実際には回避することができます。

型チェックのオーバーヘッドは別として、関数型プログラミング言語は、 funarg問題などの問題のために、一般に、効率的な機械語コードにコンパイルするのが困難です。OCamlの最適化コンパイラは、標準のループ、レジスタ、および命令の最適化に加えて、静的プログラム分析メソッドを使用して値のボックス化とクロージャの割り当てを最適化し、関数型プログラミング構造を多用している場合でも、結果のコードのパフォーマンスを最大化するのに役立ちます。

Xavier Leroyは、「OCamlはまともなCコンパイラのパフォーマンスの少なくとも50%を提供する」と述べていますが、[4]直接比較することは不可能です。OCaml標準ライブラリの一部の関数は、他の言語の標準ライブラリの同等の関数よりも高速なアルゴリズムで実装されています。たとえば、OCaml標準ライブラリでのセットユニオンの実装は、理論上、必須言語(C ++、Javaなど)の標準ライブラリでの同等の関数よりも漸近的に高速です。これは、OCaml実装がセットの不変性を利用して入力の一部を再利用するためです。出力に設定します(永続データ構造を参照)。

機能

OCamlは、静的 型システム型推論パラメトリック多相末尾再帰パターンマッチング、ファーストクラスの字句クロージャファンクター(パラメトリックモジュール)例外処理、および増分生成自動ガベージコレクションを備えています。

OCamlは、MLスタイルの型推論を汎用言語のオブジェクトシステムに拡張することで注目に値します。これにより、構造的サブタイピングが可能になります。オブジェクトタイプは、宣言された継承に関係なく、メソッドシグネチャに互換性がある場合に互換性があります(静的に型付けされた言語では珍しい機能)。

CプリミティブとFortranの両方と互換性のある形式での効率的な数値配列の言語サポートを含む、Cプリミティブにリンクするため外部関数インターフェースが提供されます。OCamlは、CのメインプログラムにリンクできるOCaml関数のライブラリの作成もサポートしているため、OCamlの知識やインストールがないCプログラマーにOCamlライブラリを配布できます。

OCamlディストリビューションには以下が含まれます:

ネイティブコードコンパイラは、 UnixMicrosoft WindowsApplemacOS などの多くのプラットフォームで利用できます移植性は、主要なアーキテクチャ( IA-32X86-64(AMD64)、PowerRISC-VARM、およびARM64 )のネイティブコード生成サポートによって実現されます。[5]

OCamlバイトコードとネイティブコードプログラムは、プリエンプティブなコンテキスト切り替えを使用して、マルチスレッドスタイルで記述できます。ただし、INRIA OCamlシステムのガベージコレクター(現在利用可能な唯一の言語の完全な実装)は同時実行用に設計されていないため、対称型マルチプロセッシングはサポートされていません。[6]同じプロセスのOCamlスレッドは、タイムシェアリングによってのみ実行されます。ただし、 Functoryocamlnet / Plasmaなど、分散コンピューティング用のライブラリがいくつかあります

開発環境

2011年以来、多くの新しいツールとライブラリがOCaml開発環境に貢献してきました。

  • 開発ツール
    • opamはOCamlのパッケージマネージャーです。
    • Merlinは、タイプスローバック、go-to-definition、オートコンプリートなど、複数のエディターにIDEのような機能を提供します。
    • DuneはOCaml用の構成可能なビルドシステムです。
    • OCamlformatはOCamlのオートフォーマッターです。
    • ocaml-lsp-serverは、OCamlIDE統合のための言語サーバープロトコルです
  • Webサイト:
    • OCaml.orgはこの言語の主要なサイトです。
    • Discussion.ocaml.orgは、 OCamlの主要なディスカッションサイトとして機能するDiscourseのインスタンスです。
  • OCamlの代替コンパイラ:
    • Ocsigenチームによって開発されたjs_of_ocamlは、OCamlからJavaScriptへの最適化コンパイラです。
    • BuckleScriptは、 JavaScriptも対象としており、読みやすい慣用的なJavaScript出力の生成に重点を置いています。
    • ocamlccは、サポートされていないプラットフォーム用のネイティブコードコンパイラを補完する、OCamlからCへのコンパイラです。
    • INRIAによって開発されたOCamlJavaは、OCamlからJava仮想マシン(JVM)へのコンパイラです。
    • Lip6によって開発されたOCaPicは、PICマイクロコントローラー用のOCamlコンパイラです。

コード例

OCamlコードのスニペットは、トップレベルのREPLに入力することで最も簡単に調査できますこれは、結果または定義された式の推測されたタイプを出力するインタラクティブなOCamlセッションです。[7] OCamlトップレベルは、OCamlプログラムを実行するだけで開始されます。

$ ocaml
      Objective Camlバージョン3.09.0 

その後、「#」プロンプトでコードを入力できます。たとえば、1 + 2 * 3を計算するには:

1 + 2 * 3 ;; 
-:int = 7

OCamlは式の型を「int」(機械精度の 整数)であると推測し、結果「7」を返します。

Hello World

次のプログラム「hello.ml」:

print_endline  "Hello World!"

バイトコード実行可能ファイルにコンパイルできます。

$ ocamlc hello.ml -o hello

または、最適化されたネイティブコード実行可能ファイルにコンパイルされます。

$ ocamlopt hello.ml -o hello

実行された:

$ ./hello
 Hello World!
$

ocamlcの最初の引数「hello.ml」はコンパイルするソースファイルを指定し、「-ohello」フラグは出力ファイルを指定します。[8]

整数のリストを合計する

リストはOCamlの基本的なデータ型の1つです。次のコード例は、整数のリストであると想定される1つの引数integersを受け入れる再帰関数sumを定義します。関数が再帰的であることを示すキーワードに注意してください。この関数は、指定された整数のリストを再帰的に繰り返し、要素の合計を提供します。matchステートメントは、はるかに一般的ですが、 Cスイッチ要素と類似しています。rec

let  rec  sum  integers  =                    (*キーワードrecは「再帰的」を意味します。*)
  整数|と一致させます。 [] -> 0 (*整数が空の                                            リストの場合は0を返します[]。*)| 最初::残り->最初+合計残り;; (*整数が空でないリストの場合の再帰呼び出し                                            。最初はリストの最初の                                            要素で、残りは                                            残りの要素のリストです。 
                                   

            



                                            おそらく[]。*)
   合計 [ 1 ; 2 ; 3 ; 4 ; 5 ] ;; 
  -   int  =  15

もう1つの方法は、リストで 機能する標準のfold関数を使用することです。

 整数の合計 =リストとます。fold_left 楽しいアキュムレータx- >アキュムレータ+ x 0整数;; 
           
   合計 [ 1 ; 2 ; 3 ; 4 ; 5 ] ;; 
  -   int  =  15

匿名関数は単に+演算子を適用するだけなので、これは次のように短縮できます。

 整数の合計 =リストとます。fold_left (+)0整数 
     

さらに、部分適用を利用することでリスト引数を省略できます。

 sum  = 
  Listとます。fold_left  (+) 0

クイックソート

OCamlは、再帰的アルゴリズムを簡潔に表現するのに役立ちます。次のコード例は、リストを昇順で並べ替える クイックソートに似たアルゴリズムを実装しています。

  rec  qsort = function | _  [] -> [] | ピボット:: rest- > let is_less x = x <ピボットインletleft right = List _ パーティションis_less残りqsort@ [ピボット] @qsort_ 
      
       
            
            
           

誕生日の問題

次のプログラムは、完全に一意の誕生日の確率が50%未満である部屋の最小人数を計算します(誕生日の問題、1人の場合は365/365(または100%)、2人の場合は364 / 365、3の場合は364/365×363/365など)(回答= 23)。

year_size  = 365とします  

let  rec  Birthday_paradox  prob  people  = 
  let  prob  =  year_size  -  。floatpeople  / year_size *。prob < 0場合はprobin 5次にPrintf printf "answer =%d \ n " people + 1 else Birthday_paradox prob people + 1 ;;      
      
      
  
      


誕生日のパラドックス 1 01 _ 

チャーチ数

次のコードは、後継(succ)と加算(add)を使用した自然数のチャーチエンコードを定義します。チャーチ数値は、関数と値を受け入れ、正確に時間に適用される高階関数です。チャーチ数値を関数値から文字列に変換するには、入力と定数文字列の前に文字列を付加する関数を渡しますnfxfxn"S""0"

let  zero  f  x  =  x 
let  succ  n  f  x  =  f  n  f  x 
let  one  =  succ  zero 
let  two  =  succ  suc  zero 
let  add  n1  n2  f  x  =  n1  f  n2  f  x 
let  to_string  n  =  n  楽しい k-  >  "S"  ^  k "0" 
let  _  =  to_string  add  suc  two  two 

任意精度階乗関数(ライブラリ)

さまざまなライブラリにOCamlから直接アクセスできます。たとえば、OCamlには任意精度の算術演算用のライブラリが組み込まれています。階乗関数が非常に急速に大きくなると、マシン精度の数値(通常は32ビットまたは64ビット)がすぐにオーバーフローします。したがって、階乗は任意精度の算術の適切な候補です。

OCamlでは、Numモジュール(現在はZArithモジュールに取って代わられています)は任意精度の算術演算を提供し、以下を使用して実行中のトップレベルにロードできます。

## 「  topfind を使用 ;; ##num」が必要;; #Num開く;;
  
  

次に、階乗関数は、任意精度の数値演算子= /* /、および-/を使用して記述でき ます。

#let  rec fact n  = if n = / Int 0 then Int 1 else n * / fact n- / Int 1 ;; val fact Num num- > Num num = <楽しい>   
                  
       

この関数は、120などのはるかに大きな階乗を計算できます。

#string_of_num  fact  Int 120 ));; - string = "6689502913449127057588118054090372586752746333138029810295671352301633 55724496298936687416527198498130815763789321409055253440858940812185989 8481114389650005964960521256960000000000000000000000000000"  
   



トライアングル(グラフィックス)

次のプログラムは、 OpenGLを使用して回転する三角形を2Dでレンダリングします。

let   = 
  ignore  Glut .init Sys .argv ; グラットinitDisplayMode〜double_buffer true ; _ 無視Glut。createWindow〜title " OpenGLデモ" ; 角度t = 10とます。*。t *。t in let render ()= GlClear クリア[ `カラー 
    
    
           
     
       ]; 
    GlMat load_identity  (); 
    GlMat 回転 角度:( 角度Sys .time 〜z 1 _ (); GlDraw `三角形を開始します; リストiterGlDraw _ 頂点2 [ -1 。、- 1 。; 0。1 。; 1 。、- 1 。];    
     
           
    GlDraw 終了 (); 
    グラットGlMat swapBuffers () モード`モデルビュー; グラットdisplayFunc〜cb render ; _ _ グラットidleFunc〜cb :(一部Glut。postRedisplay ; _ _ グラットmainLoop ()
   
   
    
   

OpenGLへのLablGLバインディングが必要です。次に、プログラムを次のようにバイトコードにコンパイルできます。

  $ ocamlc -I + lablGL lablglut.cma lablgl.cma simple.ml -o simple

またはネイティブコードに:

  $ ocamlopt -I + lablGL lablglut.cmxa lablgl.cmxa simple.ml -o simple

または、もっと簡単に言えば、ocamlfindビルドコマンドを使用します

  $ ocamlfind opt simple.ml -package lablgl.glut -linkpkg -o simple

実行します:

  $ ./simple

はるかに洗練された高性能の2Dおよび3DグラフィカルプログラムをOCamlで開発できます。OpenGLとOCamlの使用のおかげで、結果として得られるプログラムはクロスプラットフォームになり、多くの主要なプラットフォームで変更を加えることなくコンパイルできます。

フィボナッチ数列

次のコードは、入力された数値nのフィボナッチ数列を計算します。末尾再帰とパターンマッチング を使用します。

let  fib  n  = 
  let  rec  fib_aux  m  a  b  = 
    m|と一致させる  0- > a | _- > fib_aux m --1 b a + b in fib_aux n 0 1 _ 
       
              
      

高階関数

関数は、関数を入力関数として受け取り、結果として関数を返す場合があります。たとえば、関数fに2適用すると、引数に fを2回適用する関数が生成されます。

 2回 f ' a-  > ' a = fun x ' a -> f f x ;; inc x int int = x + 1 ;; _ add2 = 2inc ;; inc_str x 文字文字列= x ^            
          
    
          ""  ^  x ;; 
add_str  = 2inc_str  );; 
   add2  98 ;;
  -   int  =  100
  #add_str  " テスト" ;;
  -   string  =  "テストテストテストテスト"

この関数は、型変数'aを2回使用して、 int-> int関数だけでなく、型' aからそれ自体にマッピングする任意の関数fに適用できることを示します。特に、2回はそれ自体に適用することもできます。

   4f = 2回2f  ;;     
  val  fourtimes  :( ' a- > ' a - > ' a- > ' a = < fun >        
   add4 = fourtimes  inc ;; _   
  val  add4 int-  > int = < fun >     
   add4  98 ;;
  -   int  =  102

派生言語

MetaOCaml

MetaOCaml [9]は、実行時に新しいマシンコードのインクリメンタルコンパイルを可能にするOCamlの多段階プログラミング拡張です。状況によっては、マルチステージプログラミングを使用すると、処理するデータに関するより詳細な情報が通常のコンパイル時よりも実行時に利用できるため、大幅な高速化が可能になります。これにより、インクリメンタルコンパイラは、条件チェックなどの多くのケースを最適化できます。

例:コンパイル時に何らかのべき関数 が頻繁に必要であることがわかっているが、の値が実行時にのみわかっている場合、MetaOCamlで2段階のべき関数を使用できます。 x -> x^nn

  rec  power  n x = n  = 0の場合。< 1 >とします。それ以外の場合はnでもsqr power n / 2 x else 。<。〜x *。。〜(power n --1 x >  
      
    
   
       
         
            

実行時にわかるとすぐnに、特殊で非常に高速なべき関数を作成できます。

 。< funx  -> 。〜(power5。<x > >     

結果は次のとおりです。

 fun  x_1  ->  x_1  * 
     let  y_3  =  
         let  y_2  =  x_1  *  1 
         in  y_2  *  y_2 
     in  y_3  *  y_3 ))

新しい関数は自動的にコンパイルされます。

その他の派生言語

OCamlで書かれたソフトウェア

ユーザー

数十の企業がある程度OCamlを使用しています。[15]注目すべき例は次のとおりです。

参考文献

  1. ^ 「モジュール」2020年2月22日取得
  2. ^ https://ocaml.org/releases/4.13.1.html
  3. ^ 「OCamlの歴史」2016年12月24日取得
  4. ^ Linuxウィークリーニュース
  5. ^ 「トランクのocaml / asmcomp・ocaml / ocaml・GitHub」GitHub 2015年5月2日取得
  6. ^ 「Camlメーリングリストのアーカイブ> XavierLeroyからのメッセージ」2015年5月2日取得
  7. ^ "OCaml-トップレベルシステムまたはREPL(ocaml)"ocaml.org 2021-05-17を取得
  8. ^ 「OCaml-バッチコンパイル(Ocamlc)」
  9. ^ oleg-at-okmij.org。「BERMetaOCaml」okmij.org
  10. ^ 「Messenger.comが50%Reasonに変換されました・Reason」reasonml.github.io 2018年2月27日取得
  11. ^ 「フロー:JavaScriptの静的型チェッカー」フロー
  12. ^ 「静的アナライザーを推測する」推測します。
  13. ^ "GitHub --facebook / pyre-check:Pythonのパフォーマンスタイプチェック"2019年2月9日–GitHub経由。
  14. ^ 「WebAssembly / spec:WebAssembly仕様、リファレンスインタープリター、およびテストスイート」World WideWebコンソーシアム2019年12月5日2021-05-14を取得–GitHub経由。
  15. ^ 「OCamlを使用している会社」OCaml.org 2021-05-14を取得
  16. ^ 「BuckleScript:1.0リリースが到着しました!|ブルームバーグの技術」ブルームバーグの技術2016年9月8日2017年5月21日取得
  17. ^ ヤロンミンスキー(2011年11月1日)。「大衆のためのOCaml」2015年5月2日取得

外部リンク