23

言語シュートアウトゲームの言語を、コードサイズのみで比較しました。これが私が得たものの要約です(最初に最短で、同様のスコアでグループ化されています)。

  1. Python、Ruby、JavaScript、Perl、Lua、PHP、Mozart / OZ
  2. OCaml、Erlang、Racket、Go、Scala、F#、Smalltalk
  3. Pascal、Clean、Haskell、Common Lisp、C#、Java、C
  4. C ++、Ada、ATS

なんでだろうか。勝者は、昔ながらの動的言語のようです。Erlang、Racket(nee PLTスキーム)、およびF#は問題なく動作しています。HaskellとCommonLispは、主張されているJavaよりも簡潔に見えません。

アップデート:

このトピックに関する洞察に満ちた投稿をグラフで見つけました。私はまた、より大きなプログラム(単純なレイトレーサー)の言語の同様の比較を見つけました。全体として、私は「その」答えを得たとは言いませんが、私は考えるためのいくつかの食べ物を手に入れました。

4

8 に答える 8

24

関数型言語が本当に簡潔なら...

1- 大規模なプログラミングは小規模なプログラミングとは異なります。

これらの小さなベンチマークゲームプログラムについては、各言語によって提供される抽象化とモジュール化が大規模なプログラミングにどのように適用されるかを示す例として取り上げるべきではありません。

2-ベンチマークゲームの概要ページに表示される内容のほとんどは、各言語の実装に貢献した最速のプログラムのみを示しています(通常、遅いプログラムはしばらくするとWebサイトから削除されます-いつ、どの遅いプログラムが削除されるかはほとんど任意です)。

{編集:アダム、要約ページは最速のプログラムのみを参照しているという私の言葉を受け入れたくないので、「どのプログラミング言語が最適ですか?」のデータ行をフィルタリングするスクリプトを見てください。ページ。lib_scorecard.phpの関数ValidRowsAndMinsの80行目と82行目を見てください-Aliothは独自のセキュリティ証明書を発行しているので、ブラウザは文句を言います。}

したがって、Haskellを例にとると、貢献された最速のHaskellプログラムのコードサイズを見ていることになります。

3-どの流星コンテストプログラムも削除されておらず、流星コンテストは制限のないプログラミングコンテストです-最小の流星コンテストHaskellプログラムは最も遅い流星コンテストHaskellプログラムです。

于 2010-08-27T03:06:02.997 に答える
19
  1. 他の言語より常に優れている言語はありません(いくつかの例外があります...;))。したがって、広く分類された言語のグループにも同じことが当てはまります。ベンチマークは幅広いトピックをカバーしており、XはYよりも1つには適していない可能性があります。
  2. ソースコードはgzipで圧縮されており、プログラムの長さが何行であるかはわかりません(ええ、それはインジケーターです)
  3. かなりの数の関数型言語は、広く普及している命令型の静的言語よりもはるかに優れています-関数型プログラミング言語が簡潔ではないというわけではありませんが、動的言語はさらに簡潔なプログラムを可能にします
  4. 少なくともHaskellでは、簡潔にするための多くの可能性は、自分で構築できる抽象化からもたらされますが、自分で構築してソリューションに含める必要があります。賢いHaskellハッカーは20行のモナドを実装して30行ではなく20行の小さな問題を解決することができます-抽象化は小さなプログラムには効果がありませんが、より大きな行(たとえば200行)で多くの行を節約できます300の)プログラム。同じことがLispにも当てはまると思います(モナドではなくマクロのみ)
  5. ファンボーイをあまり真剣に受け止めないでください。FPは素晴らしく、調べる価値がありますが、癌を治すことはなく、コードを魔法のように25%短縮することもありません。
  6. たとえば、ツリーのようなデータ構造とその処理は、代数的データ型とパターンマッチングのおかげで、多くの関数型言語で非常に自然に表現されます。
于 2010-08-26T22:08:36.020 に答える
9

これは、むち打ちの機会のようです。

Pythonが「より生産的」であることを示す統計的研究はありますか?

重要なのは、元の質問は、プログラミング言語間の比較について一般化するために、いくつかの(わずかな、不適切な)データを使用しようとしているということです。しかし実際には、プログラミング言語に関する合理的な一般的な定量的比較を行うためにデータを使用することはほぼ不可能です。

ただし、ここにいくつかの考えの糧があります。

  • すべてが同じで、動的に型指定された言語は、データ型の記述に時間を費やす必要がないため、より簡潔になる可能性があります。
  • 静的に型付けされた言語の中で、すべてが同じである場合、型推論された言語は、あちこちで型を宣言する必要がないため、より簡潔になる可能性があります。
  • 静的に型付けされた言語の中で、すべてが等しい場合、ジェネリック/テンプレートを使用する言語は、コードまたはキャストと間接参照を繰り返す必要があるため、簡潔になる可能性が高くなります。
  • すべてが同じであれば、ラムダは繰り返しや定型文を回避するためのプログラミングでおそらく最も重要な抽象化であるため、ラムダ構文が簡潔な言語はより簡潔になる可能性があります。

とは言うものの、すべてが平等ではなく、長い目で見たものでもありません。

于 2010-08-28T06:09:04.623 に答える
2

Aliothゲームのプログラムは、一般的にこれらの言語のプログラムを実際に代表するものではありません。1つは、Shootoutの特定のインフラストラクチャに向けて高度に最適化された実装です。これにより、関数型言語の慣用句が少なくなり、コードが肥大化する可能性があります。これは、一部のRubyライブラリがCでパフォーマンスが重要なコードを作成する方法と似ています。そのCコードを調べて、Rubyが肥大化し、低レベルであると宣言しても、言語が大きく揺れることはありません。

もう1つは、関数型言語が非常に簡潔であると宣伝されている理由の大部分は、関数型言語が抽象化に優れていることです。これは、1つの機能の驚異よりも大きなプログラムで役立つ傾向があるため、簡潔にするために特別に設計された言語が大きな効果を発揮します。Python、Perl、Rubyは、短いプログラムを短くするように特別に設計されていますが、ほとんどの関数型言語には他の目標があります(ただし、コードサイズを無視するだけではありません)。

于 2010-08-28T05:35:55.257 に答える
2

私は最近、比較的短いJavaプログラムをOCamlに移植しました。私は過去にSMLとHaskellに手を出し、さらにCでの豊富な経験を持っています。

この回答では、命令型コードと純粋に機能的なコード(つまり、突然変異なし)の比​​較について説明します。命令型コードが他の機能的なプログラムに侵入することを許可する場合、何を比較しますか?

私の経験では、純粋関数型プログラミング(PFP)はエレガントですが、命令型よりも簡潔ではありません。PFPには「宣言」ボイラープレートは少なくなりますが、「変換」ボイラープレートは多くなります。たとえば、タプルからの解凍、末尾再帰ヘルパー関数などです。したがって、どちらのパラダイムでも、プログラムの純粋な「肉」を邪魔されずに表現することはできません。

PFPは、何かを実行するためのコストが低く、特定のアルゴリズムが原則として機能することを実証するプログラムを作成することは、PFPでうまく機能します。しかし、それを「現実世界」にするために拡張し、エラー状態や不正な入力および印刷診断に対処することで、命令型言語ではより簡単に解決できたであろう多くの肥大化が追加されます。

于 2015-03-10T09:09:12.797 に答える
1

レベル1のほとんどの言語で利用可能な拡張OOPライブラリと、シェル呼び出しのバックティックやperl正規表現構文などの単純な古いハックと関係がある必要があります。Pythonから離れる

pw = file("/etc/passwd")
for l in pw:
    print l.split(':')[0]

システム上ですべてのユーザー名を印刷する場合、オブジェクト指向言語が散らかっている抽象化がなければ、より多くのコードが必要になります。他のパラダイムではできないと言っているわけではありませんが、どのタイプにも多くのメンバー関数があり、面倒な作業を簡単にする傾向があります。個人的には、純粋に関数型言語は学術的な目的にのみ役立つと思います(しかし、私は何を知っていますか)。

于 2010-08-26T21:54:21.127 に答える
1

グループ1の言語(スクリプト)はC / C ++よりも30〜100倍遅いという事実を考慮する必要があります。関数型言語の場合、同じことが2〜7倍です。リスト内のプログラムは速度が最適化されており、他のものを測定することは二次的な問題であり、言語の実際の状態を示す良い指標ではありません。コードサイズと実行時間の重みがそれぞれ1である表
を見ると、さらに興味深いものになります。このようにして、速度/保守性の比率を比較できます。これは、コードサイズだけよりも優れた指標のようです。

于 2010-08-27T10:55:49.027 に答える
-1

勝者は、昔ながらの動的言語のようです。

Lispは明らかな反例であり、非常に冗長な単純な古い動的言語です。一方、APL / J / Kはおそらく他のどの言語よりもはるかに簡潔であり、動的です。またMathematica...

HaskellとCommonLispは、主張されているJavaよりも簡潔に見えません。

データは、パフォーマンスが最適化された小さなプログラム用であり、測定値は、特定の設定でGZIPアルゴリズムを使用して圧縮した後のコードサイズです。したがって、それらだけから一般的な結論を引き出すことはできません。おそらく、より有効な結論は、パフォーマンスの最適化から生じる肥大化を観察しているため、データから最も簡潔な言語は、基本的に非効率的であるために最適化できない言語(Python、Ruby、Javascript、Perl、Lua、PHP)です。逆に、Haskellは、高速で冗長なプログラムを作成するのに十分な努力を払って最適化することができます。それは本当にHaskell対Pythonの欠点ですか?もう1つの同様に有効な結論は、Python、Ruby、Perl、Lua、およびPHPは、その設定でGZIPアルゴリズムを使用すると圧縮率が高くなるということです。おそらく、ランレングスエンコーディング、算術コーディング、またはLZ77 / 8を使用して、おそらくBWTの前処理、または別のアルゴリズムを使用して実験を繰り返すと、まったく異なる結果が得られますか?

また、そのサイトのコードには、価値のない大量のくだらないものがありますOCamlのインストールが2世代古い場合にのみ必要なOCamlコードのこのスニペットを見てください。

(* This module is a workaround for a bug in the Str library from the Ocaml
 * distribution used in the Computer Language Benchmarks Game. It can be removed
 * altogether when using OCaml 3.11 *)
module Str =
struct
  include Str

  let substitute_first expr repl_fun text =
    try
      let pos = Str.search_forward expr text 0 in
      String.concat "" [Str.string_before text pos;
                        repl_fun text;
                        Str.string_after text (Str.match_end())]
    with Not_found ->
      text

  let opt_search_forward re s pos =
    try Some(Str.search_forward re s pos) with Not_found -> None

  let global_substitute expr repl_fun text =
    let rec replace accu start last_was_empty =
      let startpos = if last_was_empty then start + 1 else start in
      if startpos > String.length text then
        Str.string_after text start :: accu
      else
        match opt_search_forward expr text startpos with
        | None ->
            Str.string_after text start :: accu
        | Some pos ->
            let end_pos = Str.match_end() in
            let repl_text = repl_fun text in
            replace (repl_text :: String.sub text start (pos-start) :: accu)
                    end_pos (end_pos = pos)
    in
      String.concat "" (List.rev (replace [] 0 false))

  let global_replace expr repl text =
    global_substitute expr (Str.replace_matched repl) text
  and replace_first expr repl text =
    substitute_first expr (Str.replace_matched repl) text
end

シングルコアバージョンには、並列処理のための多くのコードが含まれていることがよくあります。たとえば、OCamlのregex-dnaです。OCamlでfastaである怪物を見てください:プログラム全体が2回複製され、ワー​​ドサイズがオンになります!私はここのディスクに古いOCamlバージョンのfastaを持っていますが、それはそのサイズの5分の1未満です...

最後に、私はこのサイトにコードを提供したが、それが良すぎたために拒否されたことに注意する必要があります。政治はさておき、OCamlのバイナリツリーには「IsaacGouyによって最適化されていない」というステートメントが含まれていました(コメントは削除されましたが、最適化されていないため、OCamlコードは長くなり、遅くなります)。結果は、バイアスを導入するために特に主観的に調整されています。

基本的に、このような質の悪いデータでは、洞察に満ちた結論を引き出すことは期待できません。言語間で移植されたより重要なプログラムを見つけようとする方がはるかに良いでしょうが、それでも、結果はドメイン固有になります。シュートアウトを完全に忘れることをお勧めします...

于 2010-09-05T12:38:45.427 に答える