获胜者似乎是普通的动态语言。
Lisp是一个明显的反例,它是一种非常冗长的普通动态语言。另一方面,APL/J/K可能比其他任何语言都更简洁,并且它们是动态的。还有Mathematica...
Haskell和Common Lisp看起来并不比声称冗长的Java更简洁。
你的数据是针对已经针对性能进行了优化的小程序,并且使用特定设置的GZIP算法压缩后的代码大小作为度量标准,因此你不能仅凭这些数据得出一般性结论。也许更有效的结论是你正在观察到由性能优化导致的膨胀,因此从你的数据中最简洁的语言是那些无法被优化因为它们本质上是低效的(Python、Ruby、Javascript、Perl、Lua、PHP)。相反,Haskell可以通过足够的努力进行优化,以创建快速但冗长的程序。这真的是Haskell与Python相比的劣势吗?另一个同样有效的结论是,Python、Ruby、Perl、Lua和PHP在使用该设置的GZIP算法进行压缩时具有更好的效果。也许如果你使用游程编码或算术编码或LZ77/8,也许带有BWT预处理或另一种算法重复实验,你会得到完全不同的结果?
该网站的代码中还有大量无用的垃圾。看看这段OCaml代码,只有在您的OCaml安装已经过时两代时才是必需的:
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:整个程序被复制了两次,并且根据字长进行切换!我这里有一个旧版的OCaml fasta程序,大小不到那个程序的五分之一...
最后,我应该指出,我曾经为这个网站贡献过代码,但因为它太好了而被拒绝。撇开政治不谈,OCaml二叉树曾经包含“由Isaac Gouy取消优化”的声明(尽管已经删除了评论,但取消优化仍然存在,使OCaml代码变得更长和更慢),因此您可以假设所有结果都经过了主观篡改,特别是引入了偏见。
基本上,使用这样质量低劣的数据,您无法希望得出任何有见地的结论。您最好尝试找到更重要的已在不同编程语言之间移植的程序,但即使如此,您的结果也将是特定于领域的。我建议完全忘记 shootout...