ログ日記

作業ログと日記とメモ

変数に型がないということの利点について考えるが盛り上がっているらしい

http://d.hatena.ne.jp/perlcodesample/20130227/1361928810
完全に間違っているとか正反対のことを言っているとかいう場合は分かりやすいが、全体的にずれていて一部は合ってる感じなので盛り上がっている。
微妙に日本語がおかしくて、反論も微妙にずれているので平行線。


他の人とだいぶかぶってるような気もするが、とりあえず一項目ずつ分けて考える。

どのような型の値でも代入できる

my $str = 'Hello';
my $num = 1;
my $nums = [1, 2, 3];
my $person = {age => 2, name => 'taro'};
my $ua = LWP::UserAgent->new;

これは静的型付け言語でもできるので動的のメリットではない。

str = "Hello"
num = 1
nums = [1, 2, 3]
person = Person 2 "taro"
ua = UserAgent


「どのような型の値でも代入できる」という日本語は

my $a = 1;
$a = 'Hello';

こういうものを連想させる。実際にできるが、これができても嬉しくないだろう。

記述量がとても短くなる

上でHaskellの例を書いたが、Haskellの方が短い。

変数に型がないと変更に強い

変数に型がないとソースコードの変更に強くなります。たとえば右辺の返す型に変更があったとしても、受け取る側のソースコードを変更する必要はありません。

# clinetはClientA型でもClientB型でもよい
my $ua = $c->client;

これは間違い。clinetはClientA型でもClientB型でもint型でも文字列でも何でも良いのは変更に弱い。


Javaで書くと

interface Client{}
class ClientA implements Client{}
class ClientB implements Client{}
class C {
    Client client = new ClientA();
}

class Main {
    public static void main(int argc, String[] argv){
        Client client = new C().client;
    }
}

書くのはめんどくさいがClientA型でもClientB型でも受け取れるので「たとえば右辺の返す型に変更があったとしても、受け取る側のソースコードを変更する必要はありません。」をメリットに挙げるのは間違い。


Javaは右辺の返す型に変更があった場合に受け取る側のソースコードを変更する必要のないように設計するのはめんどくさい」なら賛成。

関数のオーバーロードが不要になる

変数の型を持つ言語は、型が異なるのだが、処理としては同一の処理を行いたい場合には、オーバーロードという機能を使う必要があります。

使う必要はないので間違い。

    private void func(Client client){
        if (client instanceof ClientA){
            // ClientA型なら
        }else if (client instanceof ClientB){
            // ClientB型なら
        }
    }

    private void func(Object a){
        if (a instanceof String){
            // String型なら
        }else if (a instanceof Integer){
            // Integer型なら
        }
    }

で書ける。下の例はほとんど書く機会がないが。

複数の型を受け取りたいときに、インターフェースを実装する必要がない

Javaで大きなの労力といえば、インターフェースの仕組みを覚えて、実装することでしょう。複数の型を受け取りたい変数を作成したい場合は、まずインターフェースを実装することになります。

これは確かに労力。

 けれども、変数に型がなければ、インターフェースという仕組みは不要です。変数に型がないことによって、クラスの実装が重複がなくとてもシンプルになります。

しかし型があってもクラスの実装の重複はない。インターフェースも重複はない。あったら設計がおかしい。
「インターフェースという仕組みは不要です」もおかしい。「インターフェースという仕組みが使えない。」


しかもJavaに限っているのが間違い。
Haskellで「Leaf型」または「Branch型」で構成される「Tree型」は簡単に書ける。

data Tree = Leaf String | Branch Tree Tree

Tree型の定義自体に複数の型を使うということを書ける。

C++のテンプレートのような機能も必要がない

けれども、変数に型がなければ、そもそもこのような問題に直面することがありません。関数で受け取った後に、必要に応じて、if文で型を判定すればよいだけだからです。

JavaならObjectで受け取ってif文で判定すればいいんじゃないかな。

変数に型がないとどのような型の値が代入されているかわからないという批判に答える

変数に型がないとどのような型の値が代入されているかわからないという批判があるかと思います。

これはそういう批判は特にないのでスルーで。

変数に型がないことのメリットは重複を少なくソースコードがかけること

変数に型がないことのメリットは重複を少なくソースコードがかけることです。変数の型を意識しなくてもよいということは、それを利用するクラスや関数、メソッドも、利用するときに、型を意識する必要がないということです。これは重複の少ない保守性の高いプログラムを書くときにとても役に立ちます。

難解なので文章を分解する。

  • 「変数に型がないことのメリットは重複を少なくソースコードがかけることです。」
    • 間違い。JavaよりPerlの方が記述量が短いことは分かるが、重複は関係ない。あとHaskellは短いし重複はあり得ない。
  • 「変数の型を意識しなくてもよいということは、それを利用するクラスや関数、メソッドも、利用するときに、型を意識する必要がないということです。」
    • 微妙。意識する必要がないというよりは判別する手段がないので意識したい場面があってもできない。それに文字列か数値かを意識する必要がなくプログラムが書けるってどんな環境なんだろう。
  • 「重複が少ない(間違い)」「型を意識する必要がない(微妙)」→「これは重複の少ない保守性の高いプログラムを書くときにとても役に立ちます。」
    • 前提がおかしい上に日本語が繋がっていないのでよく分からない。

スクリプト言語は保守性が低いといわれますが、そもそも根拠はないと思います。静的言語はインターフェースやクラスをそのたびに実装しなければならないので、修正や変更が行いづらいです。その点では、保守性は低いといえます。

さくっと変更してさくっと更新できることを保守性が高いと言うか低いというか、関連記事を読んでいると色々興味深い。
片方の捉え方では合ってるが片方の捉え方では間違っている。

変数に型がないことのデメリットはないのか

最初からずっとなんだけど「変数に型がない」の定義が曖昧でよくわからないことになっている。

  • 動的:変数に型を書けない
  • 動的:変数に型を書ける
  • 静的:変数の型を省ける
  • 静的:変数の型を省けない

の四段階あると思うのだが、どれを指しているんだろう。おそらく「動的:変数に型を書けない」と「静的:変数の型を省けない」の比較だとは思うが、ややこしいので置いておく。

  • 変数の宣言が書ける

というのも関係する気がする。PHPはローカルに変数宣言を書けないので、新しく作ったつもりの変数が上の方で使われていてしかも別の型で特定条件じゃないとエラーも出ないっていうのに昔ハマった。


個人的にJavaで便利だったのは変数名変更やクラス名変更のリファクタリング
PHPだと正規表現置換を使ったりしても、ちょっとめんどくさいし漏れが出る可能性がある。それからクラスや関数の削除も躊躇する。要は最初の名前付けや構造の設計が不適当だったなーという場合に修正しにくい。
Javaだと、というかEclipseだとその辺全部自動で書き換えてくれるので安心。クラスやメソッドの削除も安心。




最初読んだときは若い人かと思ったら年上だった…本も書いてた…。
http://d.hatena.ne.jp/perlcodesample/20121226/1360932311



なんだろうね。とりあえずJavaC++がめんどくさくて難しくて嫌なのは分かった。そこは別に反対しない。