Why learning Haskell/Python makes you a worse programmer « All Unkept
Why learning Haskell/Python makes you a worse programmer
Haskell や Python を学ぶことがなぜあなたを劣ったプログラマーにしてしまうのか
I've found, contrary to what you sometimes read, that learning Python and Haskell has
not improved my programming using other languages. Haskell in particular, being so
different from imperative languages, is supposed to give new insights into programming
that will help you even when you are not using the language. My current experience
doesn't exactly tally with this, and here is why:
あなたが時折り見かけることとは逆に、Python や Haskell を学んでも他の言語を使ったわたし
のプログラミングを改良したりはしないということにわたしは気がつきました。特に Haskell
は命令型言語とはとてもかけ離れているので、たとえそれを使ったことがなかったとしてもあな
たを助けてくれるであろうプログラミングに対する新しい insights を提供してくれると考えら
れています。
わたしの current experience は doesn't exactly tally with this,
以下にその理由を挙げます:
1. Demotivation. (やる気を失わせる)
I find I think in Python, and even in Haskell to some extent, even though I have used
Haskell very little. I constantly find myself wanting to use idioms from these
languages, or noticing how much less code I'd be able to write if I was using one of
these languages (which, although very different from each other, are both much more
powerful than the language I use at work, C#). It's very common for me to notice that
using either of these languages I could decrease a chunk of code by a factor of 2-5,
and not rare to see a factor of 10-20 in certain parts of the code base.
わたしは自分が Python と、ほとんど使ったことがないので制限はありましたが Haskell です
ら考えていることに気がつきました。わたしは、Haskell や Pyhtonにあったようなイディオムを
使ってみたいとか、あるいは仮にそれらの言語を使ったときに自分がどのくらい少ないコードで
それを書けるのか認識したいと常に思っていました (これら二つの言語はかなり違ったものでは
ありますが、どちらもわたしが使っている言語である C# と比較するととても強力なものです)。
It's very common for me to notice that
それはわたしにはとても当たり前のことで
認識するための
using either of these languages I could decrease a chunk of code by a factor of 2-5,
Python や Haskellといったわたしが chunk of code を
decrease できる
and not rare to see a factor of 10-20 in certain parts of the code base.
ほとんど見られない
Further, my experience with Haskell means that I now see potential bugs everywhere in
imperative code. Before, I was fairly well aware of the problems that stateful
programming and side-effects can cause, having dealt with many scores of bugs related
directly to this, and spent countless hours debugging these problems. But without any
alternative, I guess I had just lived with it. Now I know there are other ways of
doing these things, I find it difficult to be satisfied with any of the code I write.
I am constantly aware that I am writing traps that other people are likely to fall in.
さらに言えば、わたしの Haskell の経験は命令型コードの部分のいたるところで潜在的なバグを
見つけさせることに繋がりました。以前は、 stateful programming と副作用が引き起こす可能
性があり、それに直接関係する数多くのバグを扱ってそれらの問題をデバッグするのに
countless hours を費やされるという問題に注意していました。けれども何の代替案もないので
あれば、わたしはそれと共に生きていただろうと思います。今わたしはこれらのことがらを行う
のに別のやり方があるということを知り、わたしの書いたどんなコードでも満足するのは難しい
ことを理解しました。他の人が嵌り易い自分がトラップを書いてしまうことをわたしは常に気を
つけています
I also find C# code very ugly compared to both Python and Haskell. On the visual level,
the mandatory use of braces everywhere (OK, they're not mandatory everywhere but are
enforced by coding standards with good reason) makes code contain a lot of line noise
and empty space, and combined with the verbosity of the libraries and type declarations
etc, you find that a page of C# hardly does anything. I'm also thinking of beauty on the
mathematical level, C# is a grubby mud hut compared to the breathtaking, elegant tower
that is Haskell.
わたしは C# で書いたコードが Python や Haskellで書いたそれに比べるととても ugly なことに
も気がつきました。visual なレベルでは、あらゆるところで強制される (mandatory) ブレース
(ああ、たしかにあらゆるところでは強制 (mandatory) されはしないかもしれませんが、good reason
つきのコーディング規約で enforce はされますよね) は行ノイズと空スペースを抱え、verbosity of
the libraries (ライブラリの冗長さ) と型宣言などとが合体したコードを作り出します。わたしは
また、数学のレベルで美しさについて考えるのですが、息を呑むほどの elegant tower である Haskell
と比較するとC# は grubby で泥でできた小屋です
The net result of these things is to make me very depressed and demoralised. I feel
like a human compiler, translating the Haskell or Python in my head into a language
which is a whole level lower.
these things の net result はわたしをとても落胆させ、やる気を失わせるものでした。
わたしは自分の脳内に浮かんだ Haskell や Python のコードを水準の低い言語に変換する人間
コンパイラーのようなものだと感じたのです。
2. Using functional style obfuscates your code when using other languages.
関数型のスタイルを使うことで他の言語を使うときにあなたのコードが読みにくいものになってしまう
C# has begun to get some features that are more friendly to functional style programming.
So, the other day, when faced with a very common situation I tried a functional solution.
I have a list of Foo objects, each having a Description() method that returns a string. I
need to concatenate all the non-empty descriptions, inserting newlines between them.
C# はより関数スタイルのプログラミングがやりやすいようないくつかの機能を取り入れ始めました。
ですから、先日わたしが非常に良くあるシチュエーションに直面したときにわたしは関数的ソリュー
ション (functional solution) に挑戦したのです。Foo というオブジェクトのリストがあって、それ
ぞれが文字列を返す Description() というメソッドを持っていました。そして空ではない description
の全てを間に改行を挟んで連結する必要がありました。
The code I wanted to write was this Python code:
わたしが書きたかったコードはPython での以下のようなコードです:
"\n".join(foo.description() for foo in mylist
if foo.description() != "")
Or this Haskell:
Haskell ではこうです:
concat $ List.intersperse "\n" $ filter (/= "") $ map description mylist
Using generics from C# 2.0 and the methods they contain, the best I got was:
C# 2.0 以降で使えるジェネリクスをメソッドで使うとすると
string.Join("\n", mylist.ConvertAll<string>(
delegate(Foo foo)
{
return foo.Description();
}).FindAll(
delegate(string x)
{
return x != "";
}).ToArray());
If I had been starting with a different data structure, the C# version would have
been even worse -- and C# seems to have hundreds of different collection classes,
used inconsistently in the .NET libraries. Also I should point out that if you write
any methods that accept 'delegates' (the nearest thing to first class functions) you
have to declare the function signature for them separately if one doesn't exist
already (or if you don't know where to find one that already exists), further adding
to the bloat of any functional style code.
もしわたしが別のデータ構造で始めたとしたならば、C# は .NET ライブラリの中で一貫性なく
使われている異なるコレクションクラスを数百も持っているように思われるので、C# バージョ
ンはより劣ったものになってしまうでしょう。同様に、'delegates' (first class functions
に最も近い何か) を受け付けるなんらかのメソッドを書くならば、そのメソッドが既出でない場
合 (もしくはどこにあるのかわからない場合) には関数のシグネチャ (function signature) を
分割して宣言する必要があって、すべての関数的な形式のコードに追加して膨張させてしまいま
す。
There are some big problems with the C# version. The first is that there is very little
reduction in size versus the imperative style code, if any. Compare to the tedious loop
I would have written otherwise:
C# バージョンには大きな問題が幾つかあります。第一に、命令型スタイルのコードに比べて大きさ
の減少が、あったとしてもとても小さいということです。わたしが別に書いた tedious loop と比
較してみましょう
string retval = "";
foreach (Foo foo in mylist)
{
string desc = foo.description();
if (desc != "")
{
if (retval != "")
retval += "\n";
retval += desc;
}
}
There isn't much in it.
Second, it took me longer to write. I had to do some experimenting to see how much
type information I had to add to get it to compile (e.g. adding an explicit cast for
the delegate turned out not to be necessary, but I did have to specify ConvertAll<string>
instead of ConvertAll).
第二に、それはわたしにとって書くのに長すぎるのです。わたしは以前、コンパイルのために
取得し追加しなければならなかった型情報がどのくらいなのかを確認するためのちょっとした
実験をする必要がありました
(e.g. delegate に対する明確なキャストの追加は必要なくなりましたが、ConvertAll の代わ
りに ConvertAll<string> と指定しなければなりませんでした)。
Finally, there is the problem that this code will get me into trouble with my colleagues.
Why am I writing such complex code -- using such advanced features as anonymous delegates
-- when a simple loop would have sufficed? I actually left my functional version in, but
was so embarrassed about it I had to add a brief explanatory note.
最後がこのようなコードには同僚に対するトラブルを引き起こすという問題があるということです。
なぜわたしは単純なループでも十分なときにも anonymous delegates (無名デリゲート) のような
高度な機能を使ってこんなに複雑なコードを書いているのでしょうか? 実際にわたしが関数的なも
のを書いたときには同僚がそれに困惑してしまうので、説明のための文章を追加しなければなりま
せんでした。
The fact is that functional idioms work badly in languages that don't have syntactic
support for them. Java, from what I know, would have been much worse. C# suffers in
that although some features that enable more functional programming have arrived in
C# 2.0 (along with various other language improvements), huge chunks of .NET libraries
have not been updated to take advantage of them, and our own code certainly hasn't.
現実には関数型的なイディオムは、構文的にそれをサポートしていない言語では悪い方向に働き
ます。わたしの知っているところでは Java がかなりひどくなっています。C# は 2.0 になって、
より関数型プログラミングを可能にするいくつかの機能を (その他の言語の改良と一緒に)サポー
トしてはいますが、.NET ライブラリの巨大な chunks はまだその利点を活かすように更新されて
はいないし、わたしたち自身のコードもそうなっていないのです。
It might be argued that you can still use the principles of functional programming
(no side effects, functions depend only on their inputs etc) and get benefits that
way, even if you can't use the idioms. In reality, libraries and frameworks designed
for imperative languages just don't work like that. ASP.NET is an especially bad
example. You develop controls by inheriting from Control and then overriding various
methods. Most of these methods have no return value and no inputs, and work solely by
mutating the state of the object (or other objects). They are then called by the
framework in a somewhat subtle and complex order (yes, it is a nightmare to debug).
あなたがたとえイディオムを使えなかったとしても関数型言語の原則 (副作用がなく、入力の
みに依存する関数など) を使うことができて、それによる利益を得られるという主張があるか
もしれません。実際には、ライブラリやフレームワークは命令型言語向けに設計されているの
で関数型言語的には動作しないのです。ASP.NET は特に悪い例です。あなたは Control から
継承しておいてから様々なメソッドをオーバーライドしてコントロールを開発します。このよ
うな手法 (methods) の大半は return value も input もなく、そのメソッドを抱えているオ
ブジェクトの(もしくは他のオブジェクトの)状態を変更することにより単独で動作します。そ
うしたコントロールはその後、とてもわかりにくく複雑な順序(そう、それはデバッグ時の悪夢
です)でフレームワークから呼び出されます。
In fact, applying the principles of functional programming would lead me to use only
static methods (no instance methods) as much as possible, avoiding anything that mutates
states (or even has the possibility of mutating state). I would use a few ubiquitous,
'dumb' datatypes, and keep algorithms separate from them. This flies in the face of the
teachings, or at least the practices, of the main programming paradigm popular today, OOP.
I can't apply what I think are good principles for writing code without rejecting the very
paradigm of the language and libraries I am surrounded with. It's fairly hopeless.
現実として、関数型プログラミングの原則を適用することはわたしに可能な限り (インスタンス
メソッドではなく) スタティックメソッドだけを使うようにさせ、状態を変更するあらゆることを
排除 (or even has the possibility of mutating state) するようにさせました。
I would use a few ubiquitous, 'dumb' datatypes, and keep algorithms separate from them.
これは今日ポピュラーな主流のプログラミングについてのパラダイムである OOP の教え、すくな
くとも practices とは反しています。コードを書くための良い原則であるとわたしが考えている
ものを、わたしを囲んでいる言語やライブラリの very paradigm を reject することなしに
わたしは適用することができませんでした。それはとても希望のないことなのです。
So, learning Python and Haskell has demoralised me and encouraged me to write code
that is bizarre and difficult to understand, and, in the context of an OOP code base,
provides little benefit over imperative programming. I have no doubt that in general I
am a better programmer for learning these languages, but in my current situation, I am
not a better software developer -- my productivity has in fact nose-dived. When I get
frustrated with the C# code I write, I then go and write it again in Haskell and
Python, to demonstrate to myself how much better they are, which is a pointless
exercise that only demotivates me further.
ですから Python や Haskell を学ぶことはわたしを demoralised (やる気を挫く、混乱する)
させ、奇妙で理解しにくいコードを書かせるようにしてしまったのです。そして OOP コードベ
ースの文脈では、命令型プログラミング (imperative programming) に対してはわずかな利益し
か与えられません。わたしは自分が、一般論として Haskell や Python のような言語を学ぶ
better プログラマーであるということに疑いを持っていません。しかし私が現在置かれている
状況においてはわたしは better software developer ではありません。-- my productivity
has in fact nose-dived.わたしの productivity は nose-dived してしまいました。わたしが
自分の書いた C#のコードに不満を覚えていたとき、わたしはそれを、自分のやる気を無くすた
めだけの pointless exercise として自分自身にそれらの言語がいかに素晴らしいかを
demonstrate するためにHaskell や Python で書き直してみました。
The moral of the story: don't bother improving yourself, unless you have the freedom
to improve your environment accordingly. That's rather depressing. Can anyone put a
better spin on this and cheer me up?
The moral of the story:
自分の置かれている環境を accordingly に improve できる
自由をあなたが手に入れるまでは
あなた自身を improving させることに飽きてはいけません
それはとてもがっかりさせられることです。
Can anyone put a better spin on this and cheer me up?
Update: I probably should have made it more obvious for some people that the title of
the post is not entirely serious, and mainly I'm just griping.
更新:
I probably should have made it more obvious for some people that the title of
the post is not entirely serious, and mainly I'm just griping.