OCaml批判:それはまだ有効ですか?


15

私はOCamlの完全な初心者です。最近、このページに出会って OCamlに対するかなりの批判を挙げました。

ページがかなり古いことを確認します(2007):そこにリストされている箇条書きのどれが、今日でもまだ真実ですか?たとえば、汎用オブジェクトを印刷することは不可能であることはまだ本当ですか?

私はそこに表明された意見の議論を探していないことを明確にしたいと思います。整数が警告なしでオーバーフローするという事実など、リストされている情報が、OCamlのより新しいバージョンに対してまだ正しいかどうかを尋ねています。



3
それらが修正されたかもしれないフォークがあります:tryfsharp.org
Den

7
もちろん、あなたがリンクしたそのエッセイの意見は有効ですが、これらの批判があなたに関連するかどうかはまったく別の問題です。著者はCommon Lispのバックグラウンドから来ているため、Lispish値を持っていることに注意してください。Lispと比較するよりもOCamlに別のアプローチをとる場合(例えば、「OCamlは単なる人間のためのHaskell」または「Cが関数型言語であれば、OCamlを持っているでしょう」)、あなたはそれをはるかに満足するでしょう。OCamlはすべての欠点があるため、すばらしい言語です。
アモン

5
私の知る限り、ハードウェアで整数オーバーフローを検出する方法はないので、それを検出するために場所全体にランタイムチェックを挿入する必要があります。しかし、著者はパフォーマンスに基づいて「bignum」を使用して却下しました!静的なタイピングに関する苦情は、自動車事故で死ぬことはないと思うかもしれないので、シートベルトが悪いということです。モジュールの不変性に関する苦情は、彼が物事を修正することを望んでいるということです-反モジュラーでエラーが発生しやすい方法です。「小さなタイプの動物園」は、タイプの推論とは関係ありません。彼の偏見どこにあるかは明らかです。
ドーバル

2
@Doval:もちろん、ハードウェアのオーバーフローを検出できます。 ただし、それに対処することはソフトウェアの問題です。
メイソンウィーラー

回答:


13

この記事はいくつかの場所で議論されています:

要約すると、はい、OCamlはLispではありません。いいえ、完璧ではありません(それはどういう意味ですか?)。ブログの投稿で言及されている点は、日々のO'Camlプログラマーに関係があるとは思わない。

O'Camlを学んだので、C / C ++ / Javaで書かないようなプログラムを作成するのに役立つ興味深い言語だと思います。たとえば、Frama-Cを見てください 。

O'Camlの最新の説明については、その機能について読むことをお勧めします。この言語は、強力で静的な型チェック技術を促進し、実装がパフォーマンスの高い安全なランタイムの生成に集中できるようにします。

重要:私はOCamlの専門家ではありません。あなたがそれらの1人であり、私が恐ろしく間違った何かを書いたのを見たら、私を修正してください。それに応じてこの投稿を編集します。

静的型チェック

  • 誤った安心感

    これは事実ですが、明らかです。

    静的型付けは、プログラムのプロパティのサブセットについて信頼できる証明を提供します。すべてを正式に受け入れない限り、平均的な(おもちゃではない)プログラムは、実行時にのみ目撃できるプログラミングエラーバグの影響を受けます。

    OCamlコンパイラには、デバッグ情報などを含む実行可能ファイルを生成するフラグがあります...または、プログラマを盲目的に信頼し、可能な限り型情報を消去するコードを生成できます。堅牢なプログラムが必要なプログラマは、動的チェックを明示的に実装する必要があります。

    同じことは、たとえばCommon Lispにも当てはまりますが、逆になります。最初に動的型、次にオプションの型宣言とコンパイラディレクティブがあります。

  • いくつかの基本的なタイプ

    まだ適用されます:コア言語は変更されていません(または劇的ではありません)。

  • サイレント整数オーバーフロー

    これは、整数オーバーフローが手作業でチェックされるほとんどの言語の標準です。オーバーフローが発生する可能性があるかどうかを確認するための操作を型チェックするライブラリは知りません。

  • モジュールの不変性

    1. 著者はFunctorsに言及していますが、彼の例をどのように実装できないのか、私は理解できません。https://realworldocaml.orgFirst Class Modulesの章を読むと、モジュールを使用して新しいモジュールを作成および構築できるようです。もちろん、既存のモジュールを変更するにはソースコードを変更する必要がありますが、これもプログラミング言語では珍しいことではありません。

    2. 意味的に、関数はインラインでコンパイルされます」

    上記のredditスレッドは、バインディングがリンク時に解決されると言って同意しません。ただし、これは実装の詳細であり、強調されているのは、機能の解決方法に意味的に関連していると思います。例:

     let f x y = x + y ;;
     let g a b = f b a ;;
     let f x y = x * y ;;
     exit (g 2 3) ;;
    

    上記のプログラムはコンパイルされ、実行されると5を返します。これgは、の最初のバージョンで定義されているため、呼び出し関数がの呼び出しをインライン化した場合fと同じです。ちなみに、これは「悪い」ことではなく、O'Camlの名前シャドウイングルールと一致しているだけです。gf

    要約すると、はい、モジュールは不変です。しかし、それらは構成可能でもあります。

  • ポリモーフィズムによりランタイムタイプエラーが発生する

    上記のエラーを再現できません。コンパイラエラーの疑いがあります。

マクロなし

実際、プリプロセッサ(OcamlP4、OcamlP5、...)以外のマクロはありません。

  • ラッパー(with-open-file)

    UNWIND-PROTECTがどのように役立つかを知っていると、これは多くの言語に存在しないのを見るのは本当に痛いです。以下にいくつかのオプションを示します。

    1. OCamlでの例外管理の改善
    2. OCaml構文の拡張
  • 場所

    OCamlには一般化された参照が存在するとは思わない。

軽度の言語しゃぶり

  • レコードフィールド命名地獄

    本当ですが、モジュールを使用する必要があります。

    1. OCamlで2つのレコードの2つのフィールドに同じラベルがあります
    2. フィールド名の解決
  • 構文

    まだ適用されます(しかし、実際には、これは単なる構文です)。

  • ポリモーフィズムなし

    まだ当てはまりますが、どういうわけかLispの数値タワーの代わりにそれを好む人がいます(理由はわかりません)。型推論に役立つと思います。

  • 一貫性のない関数セット

    OCaml Batteries Includedプロジェクトを参照してください。特に、 配列の例についてはBatArraymap2

  • 動的変数なし

    実装可能:

    1. http://okmij.org/ftp/ML/dynvar.txt
    2. http://okmij.org/ftp/ML/index.html#dynvar
  • オプションの〜引数サック

    言語の制限により、Common Lispではオプション引数とキーワード引数を混在させることはできません。それは吸うという意味ですか?(もちろん、これはマクロで変更できます(たとえば、私の回答を参照))。O'Camlのオプションおよび名前付き引数については、O'Camlのドキュメントを参照してください。

  • 部分的な引数アプリケーションの不整合

    これが実際に迷惑だとは思わない。

  • 算術の読みやすさ

    保持されますが、数値問題にはRまたはPythonを使用できます。

  • サイレント名の競合解決

    それでも適用されますが、これは十分に文書化されていることに注意してください。

  • オブジェクトの入出力なし

    まだ適用されます。

実装、ライブラリ

これらは毎日変化し続けています。決定的な答えはありません。

最後に、

「OCaml(または、さらに良いことに、Haskell)を試してみるべきです。たとえそれがひどいと思い、それを使用する予定がないとしても、それなしでは、LispとCがなければ不完全であるかのように、コンピューターサイエンスの教育は不完全です(または、より良い、アセンブリ)露出。」

...まだ適用されます。


ありがとうございます、リンクを見ていきますが、私はそれらの意見が正当化されるかどうかを本当に尋ねていません。私は事実がまだ成り立つかどうかを尋ねています。たとえば、代数的なデータ型を出力する方法はありますか?警告なしで整数がオーバーフローすることはまだ正確ですか?今日、エラーが発生した場合にファイルを閉じる処理にボイラープレートを書くたびにファイルを操作し、それらを破棄する方法はありますか?
アンドレア

@Andrea回答を編集しました。
コアダンプ

1
「... Lispの数値タワーの代わりにそれを好む人がいます(理由はわかりません)。それが型推論に役立つと思います。」ビンゴ。SMLおよびOCamlの型システムでは、すべての式に1つの型のみが必要です。SMLの数学演算子のオーバーロードは、言語に組み込まれている例外です。これはHaskellにも当てはまります。そのようなオーバーロードを可能にすることが、型クラスの背後にある動機でした。キャッチは、タイプごとに1つのタイプクラスインスタンスしか持てないことです。また、整数を同じサイズのフロートに盲目的に変換することはできません。64ビットのフロートの精度は54ビットのみです。
ドーバル

@Doval ラケットの数値タワー入力するようなものはどうですか?多相数学演算子を提供するために、型クラスまたは一般化代数データ型(GADT)を活用するOCamlライブラリを想像できますか?変換に関して:すべての操作が可能というわけではありませんが、入力できるものもあります。
コアダンプ

2
@Doval:「Re:多態性数学演算子、Haskellの型クラスを実装しないと方法はないと思う」F#には、型クラスのない多相数学演算子があります。
ジョンハロップ

7

ページがかなり古いことを確認します(2007):そこにリストされている箇条書きのどれが、今日でもまだ真実ですか?

  • 誤った安心感。これはナンセンスです。

  • いくつかの基本的なタイプ。OCamlにはバイトとバイト配列がありますが、組み込みのユニコード文字列、16ビット整数、符号なし整数、32ビット浮動小数点数、ベクトルまたは行列はありません。サードパーティのライブラリはこれらの一部を提供します。

  • サイレント整数オーバーフロー。変わらないが、それは問題ではなかった。

  • モジュールの不変性。関数とモジュールは変更可能であるべきであるという彼の推奨は、Lispへの厳しい反論であり、本当に悪い考えです。include必要に応じてモジュールを置き換えることはできますが、もちろん変更することはできません。

  • ポリモーフィズムにより、実行時タイプエラーが発生します。これはOCamlの大きな問題であり、修正されていません。型がポリモーフィックな等価性を進化させると、関数のような型に遭遇すると比較とハッシュが失敗し始め、問題のデバッグは非常に困難になります。F#には、この問題に対する優れたソリューションがあります。

  • マクロはありません。皮肉なことに、彼がこのOCamlを書いたとき、実際にはマクロを完全にサポートしていましたが、今では機能を引き出すことにしました。

  • ラッパー。これは実際の問題であり、修正されていません。try ... finallyOCaml言語にはまだ構造がなく、stdlibにそれを実装するラッパーもありません。

  • 場所。変化はありませんが、問題はありません。

  • 地獄の命名フィールドを記録します。モジュールを使用してコードを適切に構造化します。

  • 構文。変化はありませんが、問題はありません。

  • ポリモーフィズムなし。彼が書いたとき、これはほとんどナンセンスであり、何も変わっていません。

  • 一貫性のない関数セット。OCamlにはまだcons機能がありません。それはいいです。私の言語でLispのものを欲しくない、ありがとう。

  • 動的変数はありません。OCamlについては良いことでした。OCamlについてはまだ良いことです。

  • オプションの〜引数は吸う。オプションの引数は揺れ動く。Microsoftにバッジを付けて、F#にオプションの引数を追加してもらいました。

  • 部分的な引数アプリケーションの不整合。え?

  • 算術の読みやすさ。これは、8年前にOCamlの使用を停止してから変更されました。どうやら今あなたができるInt64.((q * n - s * s) / (n - 1L))

  • サイレント名の競合解決。彼は、あなたがLispでするように、REPLで本格的なソフトウェア開発をしようとしていました。OCamlでそれをしないでください。REPLに依存するファイルとバッチコンパイルは、テスト、使い捨てコードの実行、インタラクティブなテクニカルコンピューティングにのみ使用してください。

  • 評価の順序。彼が書いたとき、これは間違っていました。評価の順序はOCamlでは定義されていません。

  • オブジェクトの入出力はありません。彼は、この「問題」をすでに解決したサードパーティのライブラリを引用しました。

  • コンパイラは最初のエラーの後に停止します。え?

  • ネイティブにコンパイルされた実行可能ファイルのスタックトレースはありません。修繕。

  • デバッガーは吸う。デバッガーを使用したことはありません。静的型チェックは、ほとんどすべてのバグをキャッチします。

  • GCは吸います。1つの大きな問題を除いて、OCamlのGCが優れていることがわかりました。グローバルロックは並列プログラミングを妨げます。

  • 暗黙の前方宣言はありません。相互再帰は、すべてのMLで設計上明示的です。唯一の奇妙な点は、typeデフォルトでは定義が再帰的であるのに対し、letバインディングはデフォルトでは非再帰的であるということです。

  • 関数ラウンドはありません。OCamlにはまだ標準のstdlibがありますが、Jane St's Coreなどのサードパーティのライブラリが提供roundしています。

  • リストList.mapまだ末尾再帰ではありません。このような深刻なバグを修正するパッチを提出し、リリースに登場するまで何年も待たなければなりませんでした。もちろん、リストは不変です。そして、そうあるべきです。

  • スピード。大きなポリモーフィックバリアントのコンパイル時間が修正されたと思います。

  • パターンマッチング。現実に対する希望の勝利。Lispコミュニティはこれをすることに失敗しました。したがって、私の10番目のルール:十分に複雑なLispプログラムには、OCamlのパターンマッチコンパイラの半分の、アドホックで、非公式に指定され、バグが多い実装が含まれています。

たとえば、汎用オブジェクトを印刷することは不可能であることはまだ本当ですか?

彼はあなたが単純にできないと書いたとき:

print value

ただし、ライブラリコールとしてトップレベルからプリティプリンタを呼び出して、必要なタイプ情報を提供できます。また、きれいなプリンターを自動生成するために、データ構造に注釈を付けるために使用できるマクロがありました。


パターンマッチング:OCamlソースコードoptimaはどちらも同じペーパー「Optimizing Pattern Matching」を参照しています。ここでは、「アドホック」、「バグに乗った」、「非公式に指定された」のいずれも現実的に適用できないと思います。「F#にはこの問題に対する優れた解決策があります」:可能であれば、これについてもう少し詳しく知りたいと思います。答えは良いのですが、話すときconsの悪口は悪い調子を与えます(元の記事は暴言ですが、そこからコピーする必要はありません)。
コアダンプ

2
@coredump:「可能であれば、これについてもう少し詳しく知りたい」F#には、特定の演算子および関数でユーザー定義のアドホックポリモーフィズムがあります。したがって+、int、float、complexで使用できますが、独自の型を定義+し、型で作業するためのオーバーロードを追加することもできます。これにより、LispまたはHaskellの簡潔さと読みやすさが、SMLまたはOCamlの予測可能なほど優れたパフォーマンスで提供され、他の言語にはない何かが実現されます。
ジョンハロップ

@coredump:「OCamlのソースコードとoptimaはどちらも同じ論文を参照しています」。その論文で説明されている技術は、ML型システムに完全に基づいています。Lispにはない型システム。Optimaは、その論文で説明されていることの多くを実行しておらず、実行できません。セクション4.2「網羅情報の使用」をご覧ください。バリアント型がないため、Lispには網羅的な情報はありません。例えば、OCamlはリーフの数に基づいてネストされたジャンプまたはディスパッチテーブルを選択しますが、その情報はLispでは不明です。
ジョンハロップ

LispとOCamlは、異なるもの(ダイナミズム、画像ベースのプログラミングなど)用に設計されています。しかし、Lisp Hindley-Milnerとは異なる型システムを持ち、実装コンパイル中にそれを利用します。このSBCLセッション、このペーパーの4.2セクションの例をご覧ください。網羅性は、型推論と宣言からコンパイラによってすでにチェックされています。Optimaは、コンパイル時マクロ展開(またはSBCL VOP)の実装固有のコードを追加して他の戦略を立てることができますが、それを行うための十分なインセンティブがありません。
コアダンプ

それはユーザー定義の代数データ型にどのように適用されますか?
ジョンハロップ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.