ひとつの言語が使えるなら、言語の勉強は不要なのか

昨日飲み会で出てきた話題なんだけど、「ひとつの言語が使えるようになれば、他の言語は簡単にマスターできるから言語なんてずっと勉強するものじゃないよ」について。この人 (達) は、言語「だけ」じゃなくてほかの勉強もしなさいよ、ということが言いたかったんだと思う。でも、一つの言語が「使える」からと言って、他の言語が簡単だとは思えない。

そもそも、「使える」というのはどういうレベルのことを言うのかが分からないが、おそらくこの人 (達) は「ある程度書ける」レベルを言っていたんだろう。確かに、「使える」というのが「ある程度書ける」レベルなら、ひとつの言語が「使える」ようになれば、他の言語も「使える」と言っていい。ただし、このレベルでは他の言語の文化を無視して、自分の知っている言語に無理やりあてはめたコードを書くことが多い。
でも、「使える」というのは、「読める」ことも大切だ。プログラムを「読む」という行為は、その言語の文化に触れることとほとんど同じことだと思う*1。「使える」というのが「書けて読める」とするならば、ひとつの言語しか知らない人*2は他の言語が「使えない」し、理解できない。

例えば、Java がある程度書けるとしても、以下のプログラムを読むのは難しいはずだ。

#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    int a[] = { 1, 2, 3, 4, 5 };
    std::copy(a, &a[4], std::ostream_iterator<int>(std::cout, "\n"));
}

以下のプログラムも同様だ*3

template <unsigned char n>
struct arbitrary_bit
{
    enum { value = arbitrary_bit<n - 1>::value * 2 };
};

template <>
struct arbitrary_bit<1>
{
    enum { value = 1 };
};

template <>
struct arbitrary_bit<0>
{
    enum { value = 0 };
};

逆に、C++ がある程度書けるとしても、以下のプログラムを読むのは難しいと思う*4

public enum ListType {
    ORDERED {
        @Override
        public <E> E proc(Proc<E> proc, E obj) {
            return proc.ordered(obj);
        }
    },
    UNORDERED {
        @Override
        public <E> E proc(Proc<E> proc, E obj) {
            return proc.unordered(obj);
        }
    },
    DEFINE {
        @Override
        public <E> E proc(Proc<E> proc, E obj) {
            return proc.define(obj);
        }
    };
    public static interface Proc <E> {
        E ordered(E obj);
        E unordered(E obj);
        E define(E obj);
    }
    public abstract <E> E proc(Proc<E> proc, E obj);
}

class Main implements ListType.Proc<String> {
    private String tag(String tag, String str) {
        return "<" + tag + ">\n" + str + "\n</" + tag + ">";
    }
    public String define(String str) {
        return tag("dl", str);
    }
    public String ordered(String str) {
        return tag("ol", str);
    }
    public String unordered(String str) {
        return tag("ul", str);
    }
    
    public static void main(String[] args) {
        System.out.println(ListType.ORDERED.proc(new Main(), "<li>hoge"));
    }
}

JavaC++ は「似ている」とよく言われるのだが、それは浅い部分だけであって、深く学ぶと「似ていない」ことに気づくはずだ。JavaC++ でさえこんなに違うのだから、D、C#RubyJavaScriptSQL などなど、色々な言語*5を学ぶことは無意味ではない。つか、そう信じたい。

*1:読む対象のコードがその言語を理解している人が書いたものでないとそうは言えないが・・・

*2:往々にして、そういう人はその言語すらきちんと理解していない

*3:ましてや boost なんて・・・

*4:ま、JavaC++ よりも壁は低いように思うけど

*5:とその思想、文化、本質