ブログトップ 記事一覧 ログイン 無料ブログ開設

サンプルコードによるPerl入門 - ゼロからPerlを始めてプロの技術を学ぼう

ゼロから初めて、プロの実力がどんどん身につく、サンプルが豊富なPerlの入門サイト。テキスト処理ならPerlにお任せ。if文,for文,配列,ハッシュ,正規表現を覚えれば、ログ解析も自由自在。Webサイトを作って独自のサービスの展開も! 関数とモジュールを覚えれば業務効率が劇的に改善。初級から上級まで、Perlのすべてが学べます。情報を得るだけではなく、プロとして生きていくために、プログラミングの確かな実力を「サンプルコードによるPerl入門」で身に着けてみませんか。Twitterフォローで、Perlの最新情報と学び方解説。

2013-02-27

変数に型がないということの利点について考える

 PHPやPerlやRubyやPythonなどのスクリプト言語に対して、変数に型がないということを否定的にとらえる人もいるかと思います。特にC言語やJavaなどの静的言語を使ってきた人にとっては、型がないということが不安材料として目に映ることが多いのではないかと思います。 

 けれども、型がないということは、本当に素晴らしいことです。型がないことによって、たくさんの面倒から解放されるからです。

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

 まず基本的なこととして変数に型がなければどのような型の値でも代入できるということです。つまり、受け取るときに、どのような型の値を受け取るのかを意識する必要がありません。

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

 文字列であろうと、数値であろうと、配列であろうと、連想配列であろうと、オブジェクトであろうと、それを意識する必要がありません。

記述量がとても短くなる

 変数の型がないことによって記述量がとても短くなります。

my $ua = LWP::UserAgent->new;

 もし変数に型があれば、次のようになるでしょう(Javaの例)。

LWP::UserAgent ua = new LWP::UserAgent();

 型推論で解決できるという意見があるかもしれませんが、型推論は不完全だと思います。まず右辺で型が明示されていない場合に使えないので、右辺に型がない場合は、結局型を書かないといけないからです。また型推論はソースコードのコンパイルの時間を遅くしてしまいます。ソースコードが大きくなってきた場合に、すばやく書いて、すばやく実行結果をもらうことができなくなります。また統合開発環境での、メソッドの自動補完の機能の実装が少し難しくなります。

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

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

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

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

 変数の型を持つ言語は、型が異なるのだが、処理としては同一の処理を行いたい場合には、オーバーロードという機能を使う必要があります。変数の型がなければ、オーバーロードの機能は必要ではなく、ただ単にif文で分岐すればよいだけなのでとても楽です。

sub sum {
  my $value = shift;
  
  if ($valueがA型なら) {
  
  }
  elsif ($valueがB型なら) {
  
  }
}

 変数に型がないことによって、関数の重複を減らすことができるという大きなメリットがあります。

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

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

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

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

 関数の引数が配列を受け取る場合を考えてみてください。そして、配列に含まれている変数の型が、定まっていない場合を考えます。また配列自体が、普通の配列なのか、動的配列なのか、特殊なリストなのかということがわからない場合についても考えてみてください。変数に型があると、このようなたくさんのことを個別に考えて、うまくインターフェースを実装したり、C++のテンプレートのような複雑でデバッグしにくい機能を使ったりしなければなりません。

 けれども、変数に型がなければ、そもそもこのような問題に直面することがありません。関数で受け取った後に、必要に応じて、if文で型を判定すればよいだけだからです。ですから、変数に型がないことによって、関数やメソッドの実装が重複なく簡単に書けます。

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

 変数に型がないとどのような型の値が代入されているかわからないという批判があるかと思います。可読性の問題です。でも、僕は型のない言語の可読性が低いと感じたことはないです。それは、そもそも静的言語を読むときとは、違う読み方をしているからだと思います。

 スクリプト言語を読むときには、文脈を追って読むとどんな値が入っているかが、たいていはすぐにわかります。たとえば変数が次のような使われ方をしているとします。

$nums->[3];

 $numsは配列(へのリファレンス)です。

$ages->{age};

 $agesはハッシュ(へのリファレンス)です。

my $ua = LWP::UserAgent->new;

 $uaにはLWP::UserAgent型の値が入っています。

my $c = Client->new;
my $ua = $c->ua;

 $uaってなんだろう? Clientクラスのuaメソッドが何を返しているかを調べればわかるな。

 こんな風に読んでいってスクリプト言語を読むことに慣れてしまえば、何の問題もないと思います。

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

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

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

 もう型のない言語は終わった、これからはハイブリッド型の言語の時代だという論評もときどき聞かれますが、その人は、型がないことのメリットを理解していないように思います。たぶんその人は、ソースコード上の見栄えという面しか理解していないんじゃないかと思います。

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

 あげるとすれば、パフォーマンスです。値の型が事前にわかっていれば、数値演算は圧倒的に速くなります。それが整数であることがわかっていれば、それを前提に計算ができるので、数値計算のパフォーマンスは、静的言語が圧倒的によいです。

 でもパフォーマンスが問題にならない局面では、スクリプト言語を利用するのがよいと思います。

 もうひとつは、メソッドや関数名の補完の実装がうまくできないので、統合開発環境には頼れないということですね。スクリプト言語を書く場合は、まるっとたくさん暗記して、統合開発環境に頼らないのが、開発効率がよいと思います。

はてなブックマークコメントへの返信

型がないことのデメリット:型があれば静的にコンピューターが発見できるバグを発見できないので人間様がやる必要がある というのはあると思う

(nkgt_chkonkさん)

 これはコンパイル時に、コンパイルエラーがわかるという意味だと思います。でもスクリプト言語というのは、コンパイルと一緒に実行してしまいます。すると、バグがその時に見つかるので、バグの発見しやすさは変わらないと思います。

いくらなんでもポジティブすぎるのでは…!

(gfxさん)

 ポジティブすぎる箇所を教えてください。

工エエェェ(´д`)ェェエエ工

(choplinさん)

 工エエェェ(´д`)ェェエエ工となる箇所を教えてください。

一人で把握出来る規模のものを一人で作って保守していた頃は同じことを考えていた気がする

(Dolpenさん)

大規模になったとき動的言語の型がないデメリットを実感すると思う

(t2y-1979さん)

 大規模になってくると、保守できなくなるという発想は、そもそも間違いだと思います。Cookpad、Github、mixi、はてな、faccbook、amazon、みんな動的な型を持つスクリプト言語を使って、大規模サイトを作っています。そう思うのは、思い込みや、プロジェクト管理の問題ではないかな。

型がない言語、書いた人間のマインドモデルに依存しすぎるので、よっぽど優れたマインドモデル持ってないと辛い

(mizchiさん)

 それは静的な型がソースコードの中に見えれば、マインドモデルに依存しないといっているように聞こえます。静的な型を持つ言語で書いても、ひどいソースコードはたくさんあります。

冗長に書くことでコンパイル時にそれらの間に矛盾がないか部分的ながらチェックできるのが静的型システムの一つの利点なんです

(nakag0711さん)

 なんでみんな、コンパイル時、コンパイル時って呪文のようにとなえるの? 一回プログラム実行したらわかるんじゃないのかなと思う。

実行時までエラーが判明しないというのは、アプリケーションの質を高める阻害要因になりかねないのですよ。

(mohnoさん)

 プログラムを一回実行したらいいだけじゃないの。というよりも、もし統合開発環境使っているのだったら、コンパイルと実行は、同時じゃないのかなと思う。

変態整数型仕様(変数に型があるくせに代入時エラーもなく暗黙に型変換しやがる)のせいで阿鼻叫喚が絶えない,あの酷い言語に聞かせてやりたい.

 どの言語のことかわからないです。

変更に強い/弱いの考え方がズレてないか?

 ずれてないです。たとえば、インターフェースを作成して、実クラスにメソッドをひとつ追加しようと思うと、インターフェースにも重複して変更を加えないといけないです。動的な型を持っていれば、そこを修正する必要がないので、変更に強いんです。

PythonとRubyは同列に並べるがPHPは入れないところに謎の序列を感じた / 型推論のある言語をマジメに使ったことがあるとは思えない / 大規模になると、LLでも型を明示してIDEの補完を活用した方が断然生産性上がるよ

 PHPを抜いたことには深い意図はないです。PHPはデプロイのしやすさ、Webに特化した関数がコアに初めから入っているので、利用しやすいという点ではWebプログラミングをしやすい言語だと思っています。型推論に関しては、僕の認識が甘かったです。LLでも型を明示するということの意味は、ちょっとわからないです。

爆釣ですなぁ。自分もJavaやってからRuby始めたころは、こんな感想だった。いいんじゃない、いろんな言語のよい所わかるのは。次はscalaあたりに手を付けてみると全然違う世界が広がると思う。

(kabisukeさん)

 釣ってないです。普段どおり、普通に書いたら、ブックマークいっぱいついちゃっただけです。 

「一回プログラム実行したらわかる」 一度携帯電話のプログラム書いてみろ「110番に緊急呼している最中に月が変わってプリペイド契約が切れその瞬間に緊急地震速報がきた」みたいなのとかテストできんの?

(naoya2kさん)

 これはもっと試験の一般的な問題だと思います。静的な型でそのプログラムを作ったから安全ということとはぜんぜん関係がないと思います。

そもそもPHPもPerlもRubyもPythonも型はあるんだけど、明示して宣言しないだけで。

(rokujyouhitomaさん)

 このお話は、内部的な値の型について議論しているのではなくって、変数が型を要求しないので、どんな型を持つ値でも代入できるメリットについて書いています。

一回実行したらわかる、というのがおかしい。Perlにまともなカバレッジ分析ツールがあるのなら使ってみれば、一回では済まないことがわかるはず。

(tproさん)

 一回実行したらわかるということの意味は、その部分を一回実行したら、バグが判明するという意味です。カバレッジをすべて通すという意味ではないです。カバレッジの問題は、また別問題です。分岐が正しいかというのは、そもそも静的な型付けをある言語が持っているかということとは全然別のはなしです。

これはPerlユーザーに背中から刺されるレベル

(Nkznさん)

 内容がないですね。

追記

 以下は勘違いしていました。

型推論で解決できるという意見があるかもしれませんが、型推論は不完全だと思います。まず右辺で型が明示されていない場合に使えないので、右辺に型がない場合は、結局型を書かないといけないからです。

 型推論はもっと多くの場合うまく型を推論してくれるようです。型推論に対する利点の議論は取り下げます。

 でもそんなに的外れな議論はしていないと考えていますよ。


読み物へ

faith_and_bravefaith_and_brave 2013/02/27 17:36 > でもスクリプト言語というのは、コンパイルと一緒に実行してしまいます。すると、バグがその時に見つかるので、バグの発見しやすさは変わらないと思います。

いえ、コンパイルは通らないパスも検査しますが、動的型付け言語は、構文エラー以外は通ったパスしか検査しません。網羅的なパスを自動実行するコードを書かない限り、静的型付けと同じエラー検出は期待できません。

nkgt_chkonknkgt_chkonk 2013/02/27 17:48 https://gist.github.com/Shinpeim/5046338

上記のようなコードでは、 動的な言語の場合は $complex_condition が真のときにしかエラーになりません。が、静的な型をもつ言語ではコンパイル時にエラーになります。複雑な条件かつレアなケースでしか通らないようなところにあるバグは、「実行すればわかる」とは言えないだろうと思います。

あるいは、 Perl では Smart::Args などを利用すればそれなりに厳格な型チェックができますが、これも実行時チェックなので実際にその行が実行されなければエラーを見つけることはできません。

もちろん、適切にテストを書くことでこのデメリットはある程度軽減することができますが、このレベルのバグはコンパイラが見つけてくれればそれだけ人間は楽ができるというのが私の主張です。

わたしも Perl は好きですし動的な型付けはサクサク書けるし柔軟で良いなーと思いますが、それは安全性とのトレードオフであるという認識です。

choplinchoplin 2013/02/27 18:22 では気になったところから3つほど

前提として、perlについて書かれているようなので、型がない -> 動的型付け、として捉えています。

> まず右辺で型が明示されていない場合に使えないので、右辺に型がない場合は、結局型を書かないといけないからです。

静的型付け言語が長くなる理由としてこの理由を挙げられていますが、意味がよく分かりません。
もし型名と同じコンストラクタが型推論に必須という意味であれば間違っています。
scalaの例ですが、次の式ではsumはIntと推論されます。Intの+(Int)メソッドがIntを返すと定義されているからです。

val sum = 1 + 2

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

変更に強いの捉え方によりますが、私は変更に強いとは変更してもプログラムが壊れないという意味だと考えています。
例として挙げられているコードですが、もし$uaがClientBにないメソッドを呼び出していると、そのメソッドを呼ぶパスが実行時に通るまでプログラムが壊れていることに気づきません。

my $ua = $c->client;

$ua->method_only_in_client_a # 変更後に実行されて初めてエラー

テストで意識的にパスを通すことでエラーを拾うしかありません。

静的型付け言語であればコンパイル時に存在しないメソッドの呼び出しでエラーになり、そもそも実行することができません。

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

もしどうしてもオーバーロードしたくないのであれば、scalaであればAnyでうけてisInstanceOf[T]かパターンマッチで挙げられている例と同等のことが可能です。
意図しない型が入ってきた時に弱くなるので、強い理由がない限りやらないと思いますが。

scala> def f(a:Any) = if (a.isInstanceOf[String]) "String" else "other"
f: (a: Any)java.lang.String

scala> f("hoge")
res1: java.lang.String = String

scala> f(1)
res2: java.lang.String = other

全体的に静的型付けであることのメリットデメリットを捉えちがえているように感じます。特に保守性の部分について。

個人的にですが、動的型付け言語のメリットは、プログラム書き始めの試行錯誤のスピードが早い、初学者の学習曲線がなだらかであることだと思っています。

noronoro 2013/02/27 18:47 pythonの2.xで日本語を使ってると型宣言したくなります。書いてるうちにunicodeなのかstrなのかわからなくなってしまうので。

ほげほげ 2013/02/27 18:58 どのような型の値でも代入できる: これ自体は良いとも悪いとも言えない
記述量がとても短くなる: 「型推論」についての理解が不十分
変数に型がないと変更に強い: 「変更に強い」の問題点はchoplinの挙げている通り
オーバーロード・インターフェース・テンプレート: 比較対象の言語の選び方が恣意的
変数に型がないことのメリットは重複を少なくソースコードがかけること: 「保守性」とは?

全体的にズレてます。

ほげほげ 2013/02/27 18:59 「choplinさん」と書いたつもりが、「choplin」と呼び捨てにしてしまっていました。
すみません。

__ 2013/02/27 19:25 この記事で型推論が不完全というのの意味が明らかでないのが気になるところですが、例えば ML という言語に対する健全かつ完全な型推論アルゴリズムが存在するというのは良く知られている事実です。健全性に関する証明は、Milner の A Theory of Type Polymorphism in Programming という論文にあります。(完全性の証明も探しているのですが、良さそうなのがなかなかみつからないのでまた後で)
型推論アルゴリズムの健全性(soundness)とは、そのアルゴリズムにプログラム p を入力したときに型 t が付くと出力されれば、必ずプログラム p は型 t で型付けできるという性質です。
型推論アルゴリズムの完全性(completeness)とは、そのアルゴリズムに型を付けられるプログラムを入力すると、必ず型が付くという出力が得られるという性質です。
これらの性質を満たすとしても"不完全"でしょうか? また、複雑な体系であれば完全性の成り立つ型推論アルゴリズムが存在しないこともありますが(実際に使われているプログラミング言語の型推論器も完全でないことは多い)、代入の右辺に型が明示的に書いてないからというような理由で型を決定できないことは、あまり無いように思います。実用する上ではほとんど困りません。

matsulibmatsulib 2013/02/27 20:00 この記事はCやJavaなどの静的言語とPerlを比較してと言ってるから、関数型言語についてまで言及しているとは思えない。ここで言ってる型推論の不完全性・冗長性というのは、C#の型パラメータが省略できないということに限定されるのでは。なんとかという関数型言語ではできるという指摘はごもっとも。でもちょっと意地悪な気もする。

通りすがり通りすがり 2013/02/27 21:01 長くなったんで、匿名ダイアリーに書いときました。
http://anond.hatelabo.jp/20130227205911

perlcodesampleperlcodesample 2013/02/27 21:40 faith_and_braveさん

>いえ、コンパイルは通らないパスも検査しますが、動的型付け言語は、構文エラー以外は通ったパスしか検査しません。網羅的なパスを自動実行するコードを書かない限り、静的型付けと同じエラー検出は期待できません。

 どうして通らないパスを持つソースコードを書くのでしょうか? 機能として必要だとしたら、その部分にエラーがあれば発見できると思います。また、それほど品質を高めたいのであれば、自動試験を書けばよいと思います。

perlcodesampleperlcodesample 2013/02/27 21:46 nkgt_chkonkさん

>複雑な条件かつレアなケースでしか通らないようなところにあるバグは、「実行すればわかる」とは言えないだろうと思います。

 高品質を求めるのであれば、バグは自動試験で見つけたほうがよいと思います。静的型だから、バグが減ることを期待するのはどうかなと思います。

perlcodesampleperlcodesample 2013/02/27 22:05 _さん、choplinさん

 僕の型推論の理解が不十分でした。ほとんどの場合推論してくれるそうですね。勘違いしていました。これは取り下げです。

perlcodesampleperlcodesample 2013/02/27 22:15 choplinさん

>静的型付け言語であればコンパイル時に存在しないメソッドの呼び出しでエラーになり、そもそも実行することができません。

 実行時に関数名が間違っていたり、存在しなくなって、エラーになったとしても、そこでソースコードを修正すればよいと思います。

 ソースコードを書くときは、試験を行うのですから、バグが見つかるのがコンパイル時か実行時かということは、よい悪いの比較にはならないかと思います。

faith_and_bravefaith_and_brave 2013/02/27 22:16 > それほど品質を高めたいのであれば、自動試験を書けばよいと思います。

そう書いたつもりです。そして以下のコメントに戻ります:

> 型がないことのデメリット:型があれば静的にコンピューターが発見できるバグを発見できないので人間様がやる必要がある というのはあると思う

アプリケーションレイヤーの自動試験のうち、型に関するテストを人間が書かなくて済みます。間違ったコードは静的型によってライブラリ側で保護され、実行することができないので、自動試験をアプリケーション側で書く必要がなくなります。
コンパイル時にできる限りのエラーを検出するのと、とりあえず動くコードを書いてあとで自動試験で保護するのは、開発方針によるトレードオフであって、メリット/デメリットの話ではありません。

また、アプリケーションレイヤーの自動試験は、まだまだ「全てを自動試験可能である」とは言いにくい段階だと思います。一部のコードは、手動で検証する必要がどうしても出てきます。そして人間が試験をする以上、漏れは発生します。そういったところで「通らないパス」は生まれます。

perlcodesampleperlcodesample 2013/02/27 22:18 noroさん

>pythonの2.xで日本語を使ってると型宣言したくなります。書いてるうちにunicodeなのかstrなのかわからなくなってしまうので。

pythonの事情がよくわからないので、なんともいえないのですが、出力してみれば、すぐにわかるのではないかなぁと思います。

perlcodesampleperlcodesample 2013/02/27 22:21 choplinさん

>全体的に静的型付けであることのメリットデメリットを捉えちがえているように感じます。特に保守性の部分について。

 静的型を持つ言語は、保守性が高いというのは、ある種の迷信や神話だと僕は思っています。コード量や、重複が多くなると、保守性は下がると思います。

perlcodesampleperlcodesample 2013/02/27 22:27 ほげさん

>どのような型の値でも代入できる: これ自体は良いとも悪いとも言えない
 これはオーバーロードやテンプレートのような機能を使わないでも書けるという点で、大きなメリットがあると考えています。

>記述量がとても短くなる: 「型推論」についての理解が不十分

 これはそのとおりでした。追記しました。

>変数に型がないと変更に強い: 「変更に強い」の問題点はchoplinの挙げている通り

 たとえば、インターフェースを実装していて、実クラスにメソッドが増えたとすると、インターフェースも直さなくちゃいけないじゃないですか。変数に型がなければ、そもそも意識する必要がなくなるので、変更に強いというのは、本当のことです。

>オーバーロード・インターフェース・テンプレート: 比較対象の言語の選び方が恣意的

 オーバーロードは、C++やJavaを意識しています。インターフェースはJavaです。テンプレートはC++です。静的な型を持つ代表的な言語だと思います。恣意的ではないです。

>変数に型がないことのメリットは重複を少なくソースコードがかけること: 「保守性」とは?

 保守性が高いコードというのは、繰り返しが少ないソースコードのことをいっています。たとえば「Object obj = new Object」よりも「my $obj = Object->new」のほうが、繰り返しが少ないので、保守性が高いという認識です。

perlcodesampleperlcodesample 2013/02/27 22:30 matsulibさん

 型推論については、完全に僕の理解の足りないことが原因でした。言語の比較は「Perl, Ruby, Pytho」vs「C, C++, Java」ですね。

perlcodesampleperlcodesample 2013/02/27 22:41 faith_and_braveさん

>アプリケーションレイヤーの自動試験のうち、型に関するテストを人間が書かなくて済みます。

 型に関する試験は書かないでよいと思います。試験するのは、入力と出力で正しい結果が得らればよいと思います。

>間違ったコードは静的型によってライブラリ側で保護され、実行することができないので、自動試験をアプリケーション側で書く必要がなくなります。

 静的型を持っていればコンパイル時に、型間違いを防いでくれるというのは事実ですが、実際に弊害になる場合をうまくイメージできません。doubleのつもりがintだったとかでしょうか?

 単なる試験不足のように感じますし、潜んでいるバグの多くが型間違いの部分にあるとも思えないです。

oneshotlife_tomoneshotlife_tom 2013/02/27 22:48 myとか、$とか@とか%とか書くの面倒じゃないですか?!その辺もインタープリタが解釈してくれるとめっちゃ楽なんですがね。

perlcodesampleperlcodesample 2013/02/27 22:51 通りすがりさん

>今時のパソコンならコンパイル時間なんて大したことない。

CPU一個あたりの性能は上がりにくくなってきています。コンパイルの遅さが不満になっているというのは、現場の声として実際に存在します。

Scala 2.9.1 final 雑感
http://d.hatena.ne.jp/kmizushima/20110901/1314879295

>実行時間に影響がなく、開発者の待ち時間で済む方が実はよいのでは?

本番でパフォーマンス要求を満たせるならば、開発者の開発速度が上がったほうがよいです。

>実行するまで意図したインスタンスが返ってこなくなった事実に気づかないから。

 これはよく聞かれますが、迷信に近いと思っています。開発中に試験をするのだから、どんなインスタンスが返ってくるかを確認しないわけがないと思います。

>とあるインスタンスしか入ってないつもりのリストに実は全然ちがうものが混ざってた!

 間違ったインスタンスが入っていたら、試験したら、その時にすぐに判明します。そのための試験なんだから、それでいいと思います。

>インスタンスが何を持ってるのかわからない方が可読性に問題がある。

 クラスのドキュメントを読めば、どんなメソッドを持っていて、どんなオブジェクトを返すのかがわかると思います。

faith_and_bravefaith_and_brave 2013/02/27 22:54 > 単なる試験不足のように感じますし、潜んでいるバグの多くが型間違いの部分にあるとも思えないです。

ここから先はもう、コメント欄で一つひとつ型が大事なケースを挙げていくと話が終わりません。strong typedefや依存型など、型によってアプリケーションのエラーを未然に防げる例は数多くありますので、興味があるなら調べてみてください。

perlcodesampleperlcodesample 2013/02/27 22:55 oneshotlife_tomさん

>myとか、$とか@とか%とか書くの面倒じゃないですか?!その辺もインタープリタが解釈してくれるとめっちゃ楽なんですがね。

 歴史的にPerlはそうなっているので、そこは仕方がない部分ですね。タイピングの少なさでいうなら、Rubyのほうがちょっと少ないと思います。「-> が .」「my $num が num」「セミコロン -> なし」なので。

 でもmyがあると変数宣言がどこでされたのかがひと目でわかるし、$がついていると、変数であることがひとめでわかるし、関数名とぶつからないという利点もあります。

...... 2013/02/27 22:56 > 保守性が高いコードというのは、繰り返しが少ないソースコードのことをいっています。たとえば「Object obj = new Object」よりも「my $obj = Object->new」のほうが、繰り返しが少ないので、保守性が高いという認識です。
なんでこれが「保守性が高い」ということになるの?

choplinchoplin 2013/02/27 22:58 > ソースコードを書くときは、試験を行うのですから、バグが見つかるのがコンパイル時か実行時かということは、よい悪いの比較にはならないかと思います。

faith_and_braveさんの繰り返しになりますが、コンパイラが検査してくれることによって、型レベルでは
* 人の手でテストを書く必要がなくなる
* 網羅性が保証される(但しコンパイラが保証してくれる範囲で)
という点で優れています。

後者の網羅性が特に厄介で、カバレッジが100%でない限り本当に全部のパスをテストで通せたか保証することは難しいのではないでしょうか。

> 静的型を持つ言語は、保守性が高いというのは、ある種の迷信や神話だと僕は思っています。

保守性は言語や設計に大きく依存するので、一概に静的型言語だから保守性が高いとはもちろん言えません。
ただ、静的型、動的型という対立軸にのみ注目するのならば、上記の通り型のレベルでの安全性が高まるという点で保守性が高いというのは正しいと思います。
実行時の値レベルまで保証してくれるわけではないので、そこはテストが必要ですが。

> コード量や、重複が多くなると、保守性は下がると思います。

重複についてはその通りですね。ただ、静的型言語であるがゆえに重複が多くなるというのは偽だと思います。
コード量については短ければいいというものではないですが、型推論を始めとして冗長な記述を減らし短く書ける仕組みは色々と取り入れられているので、恐らく考えている程には長くならないと思いますよ。

DryadDryad 2013/02/27 23:02 ○万行規模のコードの”C0 100%”に駆り出されるという悲しみに満ちた経験から、一つ言えることがあります。それは、正常系のパスは何とかなっても、異常系のパスを潰すテストを一つ一つ書いていく作業が、いかに大変な労力を伴うかということです。
この問題に対しては、色々な手法が提唱されています。型を利用するのは、有力な手段のひとつです。うまく型を使うことで、ケアレスミスや異常系の検討漏れを予防し、コードの正しさを証明することができます。その恩恵は、コードの規模が大きくなればなるほど大きいはずです。
具体的な解説については、私より詳しい方が大勢いらっしゃると思うので、他の方のご意見も伺ってみてください。先ほど、ひとつ参考になりそうなリンクがあったので、それだけご紹介しておきます。 https://sites.google.com/site/faithandbrave/error_handling

anonymousanonymous 2013/02/27 23:03 変更に強いというのは全く逆の意見です。
HaskellやOCamlの場合ですが、関数の引数の数や型を変更すると、その型が一致しない箇所がコンパイラで全てピックアップされます。
あとはそこを直していけばいいわけなので、影響を受ける範囲を限定しやすくなります。

「テストを書けばそんなの分かる」と主張されるかもしれませんが、だったら型を書いたほうがラクというのが静的な型付きを好む人達の見解でしょう。

コメントにある、

>>静的型付け言語であればコンパイル時に存在しないメソッドの呼び出しでエラーになり、そもそも実行することができません。
> 実行時に関数名が間違っていたり、存在しなくなって、エラーになったとしても、そこでソースコードを修正すればよいと思います。
> ソースコードを書くときは、試験を行うのですから、バグが見つかるのがコンパイル時か実行時かということは、よい悪いの比較にはならないかと思います。

に関しても、「バグが見つかるのがコンパイル時か実行時か」という差は大きいと思います。
Rubyを書いていてよくであるのが、ある変数やメソッドの返り値が意図せずnilになっていて、そこから生やしたメソッドが見つからず例外が投げられるということです。
変数の値やメソッドの返り値は動的な型付き言語では実行の度に変わる可能性があるので、コンパイル時にこの種のバグを見つけることはできませんし、テストで全てのケースをチェックすることはできませんから本番でこれが起きるかもしれません。

u4u4 2013/02/27 23:15 変数に入ってるインスタンスの型がわからないならテストを書けばいいってのはちょっと乱暴な気がします。
テストを書くのも人間なのでミスはありえますし、カバレッジ100%を目指すとなるとすべてのテストが正しい事を保証するのは至難の業です。
テストの正当性を保証するテストを書けとでもいうのかと。
静的型付け言語であればそもそも型に関する間違いはコンパイラが教えてくれるのでテストを書く必要もありません。
テストを含めた記述量を考えれば静的型付け言語の方がコード量は少なくて済みます。

perlcodesampleperlcodesample 2013/02/27 23:18 ...さん

>なんでこれが「保守性が高い」ということになるの?

DRYという考え方です。

http://ja.wikipedia.org/wiki/Don't_repeat_yourself

「論理的に関連した要素は予測できる形で統一的に変更され、したがってそれらの変更は同期が取れたものとなる。」という意味で、保守性が上がります。

perlcodesampleperlcodesample 2013/02/27 23:21 Dryadさん

>型を利用するのは、有力な手段のひとつです。うまく型を使うことで、ケアレスミスや異常系の検討漏れを予防し、コードの正しさを証明することができます。

 これには根拠がないです。バグを含むのであれば、型間違い以外の部分にももちろんバグが含まれていると思います。なぜ型があれば、バグが少なくなるという発想をするのかが、僕にはちょっとわかりません。

...... 2013/02/27 23:22 OCamlは強力な型推論があるから型を明示する必要は無いし、
参照透過性により移植性は優れているし、
多相型によりオーバーロードに相当する機能も動的型付けと同等に楽にできる。

型クラスのあるHaskellはオーバーロードについてはもっと強い。
しかしこちらはその分型推論は若干弱い。

perlcodesampleperlcodesample 2013/02/27 23:26 anonymousさん

>「テストを書けばそんなの分かる」と主張されるかもしれませんが、だったら型を書いたほうがラクというのが静的な型付きを好む人達の見解でしょう。

 静的な型があれば、バグが減るという見解は信じられません。バグをつぶすのは試験を行う作業だと思います。

>Rubyを書いていてよくであるのが、ある変数やメソッドの返り値が意図せずnilになっていて、そこから生やしたメソッドが見つからず例外が投げられるということです。

 静的に型宣言していても、nullポインタのようなものは、含めることができるので、それを参照しようとすると例外が発生するのではないでしょうか。

 Rubyの場合は、メソッドが呼び出されるときに遅延するだけで、早いか遅いかだけの違いだと思います。

...... 2013/02/27 23:26 > これには根拠がないです。バグを含むのであれば、型間違い以外の部分にももちろんバグが含まれていると思います。なぜ型があれば、バグが少なくなるという発想をするのかが、僕にはちょっとわかりません。
「コンパイルが通れば(型さえ合っていれば)少なくとも実行は可能である」という考え方はあるでしょう。
本当なら依存型 (dependent type) が実装されたマトモな言語があればよいのですが、
そこまで言わなくても例えばOCamlについて言えばコンパイルが通ればあとは実行時に困るのはゼロ除算とスタックオーバーフローぐらいでしょう。

...... 2013/02/27 23:29 どうもこの筆者はテスト工程を過信しすぎている気がする。
コンパイル時に検査できる内容はコンパイラに任せた方が当然バグは減る。

perlcodesampleperlcodesample 2013/02/27 23:30 u4さん

>静的型付け言語であればそもそも型に関する間違いはコンパイラが教えてくれるのでテストを書く必要もありません。

 試験をするときは型の試験なんてしないです。入力と出力のチェックをするだけです。レアケースが、それほど重要な意味を持つなら、ちゃんと自動試験書くべきです。静的な型を持っているから動的な型を持つ言語よりも、安心だとは、僕は思わないです。

oneshotlife_tomoneshotlife_tom 2013/02/27 23:33 書いてあることは理解出来るのだが、はじめてのPythonに書いてある売り文句のようでした。メリットと書いてあるところの恩恵を受けやすいのは、PythonとかRubyのほうじゃないかと。Perlはもっと雑多としているイメージがあります。Perlの良いところは、CPANから持ってこれるところかな・・・。CPANから拝借すれば、自分でコードを書く量が少ないのと、いろいろな人が叩いてくれているため品質が担保される、などなどではないかと。乗りこなしにくい、野生のじゃじゃ馬みたいな感じ。

perlcodesampleperlcodesample 2013/02/27 23:33 ...さん

>どうもこの筆者はテスト工程を過信しすぎている気がする。コンパイル時に検査できる内容はコンパイラに任せた方が当然バグは減る。

 みなさんが、コンパイル時の型チェックを過信しすぎていると思いますよ。結局は、試験をしないと、バグはとれないです。

...... 2013/02/27 23:39 > みなさんが、コンパイル時の型チェックを過信しすぎていると思いますよ。結局は、試験をしないと、バグはとれないです。
誰が試験をしないと言った?
バグを減らす工夫は多いほうが良い、という当たり前の事実を述べているまでである。

DryadDryad 2013/02/27 23:41 >perlcodesampleさん
> なぜ型があれば、バグが少なくなるという発想をするのかが、僕にはちょっとわかりません。

残念ながらあまり広くは知られていませんが、関数型言語を始めとした言語に備わっている強力な型システムを利用すると、ある種のバグを防ぎやすくなるのです。今気づいたのですが、先ほど挙げさせて頂いたドキュメントはfaith_and_braveさんがお書きになったもののようですね。今すぐでなくとも結構ですので、一度、目を通してみることをお勧めします。

u4u4 2013/02/27 23:55 >試験をするときは型の試験なんてしないです。

関数のオーバーロードが不要になる の例で$valueの型で条件分岐してますよね。

静的型付け言語であれば引数の型によって呼び出される関数が静的に決まるので、その関数のテストの際に型の違いを気にしなくていいと思うのですが。


というか自動試験というものに幻想を持ちすぎてるような…
コンパイラに任せられるものは任せたほうがプログラマの負担が減るという話なのに

PocoPoco 2013/02/28 00:04 >>なんでこれが「保守性が高い」ということになるの?

>DRYという考え方です。

違うでしょ。
何か適切な修正例を挙げて
「Object obj = new Object」
より
「my $obj = Object->new」
の方が修正範囲が小さい事示さなきゃ、保守性が高いなんて言えないのでは?
#というかわずか1行のソースで保守性の高さを示すには、上を変更する修正例でかつ下を一切修正しなくて済むような修正例挙げないと。。。
#トークンの出現回数なんて、入力補完の前ではゴミですよね?

YY 2013/02/28 00:05 静的型付けは型チェックしてくれるけどYコンビネータみたいな型付けできない式を書くことができない。表現力を狭めてでも高い品質が必要な時に利用する。動的型付けは逆で、品質を多少下げてでも表現力が必要な時に利用する。

XX 2013/02/28 00:58 再帰型でYコンビネータも型付けできますよ

heisseswasserheisseswasser 2013/02/28 01:58 22:27の時点で回答されているこちらですが
>>変数に型がないと変更に強い: 「変更に強い」の問題点はchoplinの挙げている通り
>
> たとえば、インターフェースを実装していて、実クラスにメソッドが増えたとすると、インターフェースも直さなくちゃいけないじゃないですか。変数に型がなければ、そもそも意識する必要がなくなるので、変更に強いというのは、本当のことです。

そうでしょうか?
僕が思うに、これは単に変更しやすいだけです。逆に言えば、変更されてしまいやすいのです。

もちろん変更しやすいというのはスピーディな開発には役立ち、その点で見れば利点です。

しかし、変更されやすいという点で見れば、
* 自分で実装しているクラスで、メソッドから返すオブジェクトをObjectAからObjectBに内部的に変更したり、
* 使用しているライブラリのクラスで、バージョンアップに伴ってメソッド名が変わった
というようなインターフェースが変更があった場合に、
動的型付け言語では、実行時に、変更があったクラスを使用する側の、変更箇所に関係する部分に運良く実行が到達するまで、インターフェースの変更が検知できません。(*)

変更があった場合に、使う側でそれが分からないのであれば、それは変更に強いとは言えず、むしろ弱いのでは?

もちろん、実行時のテストが必要だというのは、動的型付け/静的型付け言語に関係なく共通ですが、ここで僕が言いたいことは、
動的型付けな言語は、単に変更が容易なだけで、変更に強いという観点はちょっと違うんじゃないかなと。

(*)もちろんテストによっても発見できますが、網羅的にテストしないと発見できない可能性があります。

anonymousanonymous 2013/02/28 05:09 > 静的な型があれば、バグが減るという見解は信じられません。バグをつぶすのは試験を行う作業だと思います。

静的な型はバグが減るとかバグをつぶすというレベルの話ではなく、コードの明らかなミスを無くすものです。
例えば、"foo" + 100みたいなコードはバグ以前にただのミスでしょう。
関数が意図しない型の引数で呼び出されてしまって例外が投げられることはよく経験していらっしゃると思います。
動的な型のチェックではこんなミスも防げなくなってしまいます。
こうしたミスが起きないことを試験で確かめるのはかなり困難でしょう。

> 静的に型宣言していても、nullポインタのようなものは、含めることができるので、それを参照しようとすると例外が発生するのではないでしょうか。
> Rubyの場合は、メソッドが呼び出されるときに遅延するだけで、早いか遅いかだけの違いだと思います。

C言語などのポインタではそうでしょうが、ポインタ以外の変数はもちろんNullポインタにはなりません。int xのxには値がありますし、関数の返り値としてポインタでない型が指定された場合もそうです。
また、HaskellやOCamlなどには望みの値が含まれないかもしれないことを表現できるMaybeやoption型があります。

perlcodesampleperlcodesample 2013/02/28 09:04 oneshotlife_tomさん

>メリットと書いてあるところの恩恵を受けやすいのは、PythonとかRubyのほうじゃないかと。

 メリットは変数に型を持たない言語全般に当てはまります。Pythonは言語仕様がコンパクトなので、だれが書いても同じになりやすいという利点がありますが、今回の議論とは、観点が違うんです。

perlcodesampleperlcodesample 2013/02/28 09:14 >Dryadさん

>残念ながらあまり広くは知られていませんが、関数型言語を始めとした言語に備わっている強力な型システムを利用すると、ある種のバグを防ぎやすくなるのです。

ドキュメント先を読みましたが、一般的な例外処理のお話であって、静的な型を持つことがバグを防ぐという内容ではないように思います。

 みなさん静的な型を持っていると「ある種のバグ」が減ると思っていらっしゃるようですが、もし型が間違っていれば、試験をしたときにどちらにしろ発見できるので、バグの多い少ないには影響しないと思います。

 それを実行時に確認するのは、それほどめんどうなことでもないです。コンパイル時か実行時かという、発見の時期が異なるだけだと思います。

perlcodesampleperlcodesample 2013/02/28 09:26 u4さん

>関数のオーバーロードが不要になる の例で$valueの型で条件分岐してますよね。

 それはプログラムのロジックなので分岐しています。試験の場合は、ひとつひとつの関数ではなくって、この入力があった場合に、このような出力が得られるということを試験します。だから、型の試験というのは、普通は必要ないんです。

>というか自動試験というものに幻想を持ちすぎてるような…
>コンパイラに任せられるものは任せたほうがプログラマの負担が減るという話なのに

 負担は減らないと思います。型がおかしければ静的な型を持つ言語の場合はコンパイル時に、動的な型を持つ言語だと実行時にわかるというタイミングの違いだと思います。

perlcodesampleperlcodesample 2013/02/28 09:31 Pocoさん

>>なんでこれが「保守性が高い」ということになるの?
>DRYという考え方です。

>違うでしょ。
>何か適切な修正例を挙げて
>「Object obj = new Object」
>より
>「my $obj = Object->new」
>の方が修正範囲が小さい事示さなきゃ、保守性が高いなんて言えないのでは?
>#というかわずか1行のソースで保守性の高さを示すには、上を変更する修正例でかつ下を一切修>>正しなくて済むような修正例挙げないと。。。
>#トークンの出現回数なんて、入力補完の前ではゴミですよね?

 これはひとつの例です。たとえばオーバーロードを書かなくて、関数がひとつだけなら、重複を減らせます。またインターフェースを書くという重複もなくせます。ポリモーフィズムを実現したいときに、C++テンプレートのような特殊な実装を使わなくてもすみます。

 だから、動的な型を持つ言語は、ソースコード全体として、かなり重複を減らすことができるんです。

perlcodesampleperlcodesample 2013/02/28 09:34 Yさん

>動的型付けは逆で、品質を多少下げてでも表現力が必要な時に利用する。

 どうしてみなさん、動的型付けは、品質が下がるようなイメージをもっていらっしゃるのでしょうか。動的型付け言語で、大規模でバグの少ないWebサイトが作られているので、品質が下がるということはないと思いますよ。

perlcodesampleperlcodesample 2013/02/28 09:40 >heisseswasser


>しかし、変更されやすいという点で見れば、自分で実装しているクラスで、メソッドから返すオブジェクトをObjectAからObjectBに内部的に変更したり、使用しているライブラリのクラスで、バージョンアップに伴ってメソッド名が変わったというようなインターフェースが変更があった場合に、動的型付け言語では、実行時に、変更があったクラスを使用する側の、変更箇所に関係する部分に運良く実行が到達するまで、インターフェースの変更が検知できません。

 機能として利用されているのであれば、試験したときにわかるので、タイミングの問題だと思います。また本当に100%近くの品質を保証したいのであれば、その部分に関しては、試験を書くべきで、コンパイルチェックにたよるべきではないと思います。

.. 2013/02/28 09:42 > みなさん静的な型を持っていると「ある種のバグ」が減ると思っていらっしゃるようですが、もし型が間違っていれば、試験をしたときにどちらにしろ発見できるので、バグの多い少ないには影響しないと思います。

静的な型を持っていない場合、型が間違っていることを試験しないと発見できない。
静的な型を持っている場合、型が間違っていることを試験せずともコンパイルする際に発見できる。

> それを実行時に確認するのは、それほどめんどうなことでもないです。コンパイル時か実行時かという、発見の時期が異なるだけだと思います。


静的な型を持っていない場合、それほどめんどうなことでなかったとしても実行時に確認する必要がある(手動)。
静的な型を持っている場合、コンパイル時に確認される(自動)。

わた春香わた春香 2013/02/28 09:48 ここでの問題は perlcodesample 氏が想定している C++, Java などのやや古典的(?)な型付き言語と、型と聞いて条件反射的にヒャッハーとやってくるモヒカン達が考える強力な型付き言語との間には幾らかのギャップがあるということですね。
ぶっちゃけその両者は別物と考えてください。後者は計算機科学者たちが数々の数式による証明を元に作り上げた「ぼくのかんがえたさいきょうのぷろぐらむげんご」なので実務畑から叩き上げられた言語とは毛色が違うんです。

モヒカンさん達の言っているのは、「機械的な計算で除去できる間違いは機械に探させたほうが良い」ということです。例えば java のヌルポや一般的な LL の意図しない nil 値エラーの類は強力な型付けによって除去できることが数学的に証明できるとか。

Ruby で書いていると「こんなエラーは静的に指摘できるはずだろ」と本人の能力は棚に上げてPCを窓から放りたくなりますが、Haskell で書いていると「なんでこれで型エラーが出るんじゃい」と本人の能力は棚に上げてPCを窓から放りたくなるのです。

TANUKIMARUTANUKIMARU 2013/02/28 09:55 精鋭ばかりのチーム/個人的趣味内で実装:多いに賛成、利便性を最大限に利用しましょう。
ただ現実を見れば、、安全性、保守性の点でどうしても手放しでは賛成できない。

このプログラム言語に関するエントリを拝読させていただき、純然たる言語である日本語にも
通じるものを感じました。日本語はよく省略される言語だと言われます。
それはつまり、多少の言葉が省かれていてもコンテキストを通じて意味・意思を伝えることができるが
同時に文脈(とその理解)が不十分であれば伝え方、解釈のされ方は多様なものとなります。
我々ネイティブは、貴殿が挙げられているような素晴らしい利便性を享受できていますが
はたしてそれはマジョリティとなり得るのかどうか…。

sumiisumii 2013/02/28 09:59 「完全(complete)な実行時テストを行えばコンパイル時検査は要らない」というのは正しいと思いますが、一般には入力は無限にありうるため「完全な実行時テスト」は不可能なので、前提が成り立たないですよね。

もちろん、(今のところは)静的型つけでは(現実的には)検査できない性質も多いので、コンパイル時検査があるからといって実行時テストが不要になるわけでもないです。単に実行時テストの「一部」が不要(かつ完全)になるだけです。ただし、(Javaぐらいだと微妙ですが)MLやHaskellのようなバリアント型(直和型)とそれに対するパターンマッチングの網羅性検査は、よく言われるNull (None)チェック等を含め「場合分けの漏れ」も防いでくれるので、その「一部」が大きいだけだと思います。

ちなみにいろいろなところでしつこく言っていてすみませんが、"static typing language"ではなく"statically typed languageなので、日本語で言うと「静的型付け言語」ではなく「静的型付き言語」です。:-)

perlcodesampleperlcodesample 2013/02/28 10:03 .さん


>静的な型を持っていない場合、型が間違っていることを試験しないと発見できない。
>静的な型を持っている場合、型が間違っていることを試験せずともコンパイルする際に発見できる。

>静的な型を持っていない場合、それほどめんどうなことでなかったとしても実行時に確認する必要がある(手動)。静的な型を持っている場合、コンパイル時に確認される(自動)。

 型間違いが、頻繁に起こるのであれば、コンパイルチェックは開発効率を上げるかも知れませんが、型間違いなんて、普通にプログラムを書いていれば、あまり起こらないと思うんです。

 静的な型を持つ言語で開発していても、一回は絶対試験しますよね。そのときにバグがあれば、型間違いを見つけることができます。だから、タイミングの問題だけで、手間はあんまり変わらないと思います。

わた春香わた春香 2013/02/28 10:06 あとあれですね、そもそも Haskell なんかには変数自体が存在しないっていう。代入とは人類の犯す最も恐るべき悪徳だとか何とか。

わた春香わた春香 2013/02/28 10:08 > 型間違いなんて、普通にプログラムを書いていれば、あまり起こらないと思うんです。

それが死ぬほど起こるんですなこれが。静的型付き関数言語のプログラミングは型エラーとの格闘です。

anonymousanonymous 2013/02/28 10:10 input/outputのテストだけとおっしゃいますが、それはあくまでビヘイビアであってユニットテストとしては不足していますよね。カバレッジ100%を目指す場合、動的型付言語であろうと型に関するテストも必要だと思います(発生頻度の問題ではありません。)し、そうなるとテストコードは膨れ上がります(しかも人手で書くテストコードはバグが存在する可能性があります)。
少なくともこの1点について、静的型付き言語はコンパイル時にコンパイラによって保障されたチェックが可能なわけですから、テストコードまで含めて一つのプロダクトだと考えると一長一短ではありませんか。どなたかがおっしゃっていましたが、トレードオフの関係です。どちらが優れているというのではなく、*あなたが*重要視しているコードの簡潔性を実現するためには動的型付き言語が適している、というだけではありませんか。

perlcodesampleperlcodesample 2013/02/28 10:12 わた春香さん

>モヒカンさん達の言っているのは、「機械的な計算で除去できる間違いは機械に探させたほうが良い」ということです。例えば java のヌルポや一般的な LL の意図しない nil 値エラーの類は強力な型付けによって除去できることが数学的に証明できるとか。

 それは、理論的に、コンパイル時にチェックできるという意味ですよね。実際の開発のことを考えれば、型間違いのコンパイルエラーなんて普段そんなに目にしないと思うんです。プログラムするときに、数値を意図している変数に文字列を代入したりはしないし、その逆もないと思います。オブジェクトを代入しようと意図している変数に、数値を代入したりはしないと思います。

 もし仮に間違えていれば、一度実行したときに気づいて修正できると思うんです。

perlcodesampleperlcodesample 2013/02/28 10:28 anonymousさん

>input/outputのテストだけとおっしゃいますが、それはあくまでビヘイビアであってユニットテストとしては不足していますよね。

 不足しません。条件分岐のすべてをとおる試験を用意すれば、関数の単体試験しなくっても、その条件分岐に関して、カバレッジは100%になります。試験は必要でなければ、細かくしすぎないほうがよいと思います。型チェックのための試験の量が増えるというのは、間違いです。


>少なくともこの1点について、静的型付き言語はコンパイル時にコンパイラによって保障されたチェックが可能なわけですから、テストコードまで含めて一つのプロダクトだと考えると一長一短ではありませんか。

 スクリプト言語は、コンパイルチェックを行うので、多くの文法エラーをはじいてくれます。しないのは、型に関してです。静的な型をコンパイル時にチェックしてくれるから、品質があがるというのは、信じられません。やっぱり品質は、試験で担保すべきです。

perlcodesampleperlcodesample 2013/02/28 10:34 わた春香

>静的型付き関数言語のプログラミングは型エラーとの格闘です。

 Perlではあんまり闘った記憶がないなぁ。

perlcodesampleperlcodesample 2013/02/28 10:41 TANUKIMARU

>ただ現実を見れば、安全性、保守性の点でどうしても手放しでは賛成できない。

 これはJavaやC#を使うという意味でしょうか? どうして、静的な型づけ言語を使うと、安全性が上がるのかが理解できないです。

 安全性、保守性というのが、多くの人が経験を持っていて、人員が確保しやすいという意味であれば、この議論とはぜんぜん関係のない話です。

perlcodesampleperlcodesample 2013/02/28 10:49 sumiiさん

>単に実行時テストの「一部」が不要(かつ完全)になるだけです。

 はい。そのとおりだと思います。でも結局、静的型付き言語でも、実行時試験をしなくっちゃいけないので、確認する項目が減るわけでもないと思います。

わた春香わた春香 2013/02/28 11:01 > オブジェクトを代入しようと意図している変数に、数値を代入したりはしないと思います。

僕はするね!(確信

まあ静的型付き関数言語の型というのは、単に数値型かオブジェクトかというような違いではなくもっと面倒なものなので、感覚は違うかと思います。

> もし仮に間違えていれば、一度実行したときに気づいて修正できると思うんです。

運が良ければ。悪かったらロケットが墜落しますね^^

> Perlではあんまり闘った記憶がないなぁ。

前述しましたが、型の概念が違うからです。強力な型付けというのは、型エラーをたくさん出すことによって、実行可能なコードが出来た時にある一定レベルの間違い(このレベルが動的な方の言語よりもかなり高い)が存在しないことを保証しているんです。perl で書くのと同じ感覚で haskell や ocaml を書くと、型エラーに振り回されてPCを投げ捨てたくなるのも前述したとおりです。

> でも結局、静的型付き言語でも、実行時試験をしなくっちゃいけないので、確認する項目が減るわけでもないと思います。

試験の項目は減ります。原理的にそうですし、経験上でもそうです。型を決めてコードを書いてコンパイラが型チェックをするという部分で、LL で書く試験のうちのいくらかを代わりに行なっていると考えてください。違いは、後者はそれをしなくても「動き」ますが,前者はそれをしないと実行すら出来ないということです。

要は、多くのエラーは「慎重にやれば」除けますが、モヒカンという人間は手を抜くことに全力を注ぐので、そんな作業はハノイの塔を動かすのと同義なのです。あとは手作業では 100% 取り除いたと確信するのは難しいのだから、それを 100% にする手段があるならそうするべきでは?という理性的な意見も一部にはあります。

大規模開発の話でも触れられていましたが、LL 系の言語の最大の利点は習得のしやすさだと思います。人手がかかるものを作るときには特に重視されますね。多少の厳密さを犠牲にしても、その分を「慎重にやる」事によってカバーしているんです。そのための優秀な手法やツールもたくさんありますしね。

結局言語もツールにすぎないので、要は適材適所ということではないかと。あとは宗教の話になりますから。それでも、型理論というのは C++ や Java では語り尽くせない深淵が広がっている世界です。一つ覗きこんでみるのも一興かと。除き返された時にはモヒカンになっているかもしれませんが。

anonymousanonymous 2013/02/28 11:13 > 条件分岐のすべてをとおる試験を用意すれば、関数の単体試験しなくっても
条件分岐の全てを通るのに、関数の単体試験をしないとはどのような状況でしょうか。
(そもそも条件分岐の全てを通る試験はinput/outputだけの試験ではないですよね。)

> スクリプト言語は、コンパイルチェックを行うので、多くの文法エラーをはじいてくれます。しないのは、型に関してです。静的な型をコンパイル時にチェックしてくれるから、品質があがるというのは、信じられません。やっぱり品質は、試験で担保すべきです。
どなたも、静的型付き言語なら試験を行わないとはおっしゃっていないと思いますよ。
それに、コンパイラによる型チェックも試験の一種でしょう。テストコードを書いていないというだけです。

恐らく想定している環境・対象がperlcodesampleさんと他の方々とで異なるのだと思うのですが、
例えば世の中には万が一にも失敗してはいけないシステムというものが存在します。そういったものは往々にして複雑なロジックを有していて、
単純に動作確認をしてエラーが起きたら修正すればよい、というわけには行かないものです。
そのようなシステムの場合、エラーが起きる*可能性*は極力排除しなければなりません。
動的型付き言語の場合、どんなに慎重に頑張っても型によるエラーが起きる*可能性*は0ではありません。その点で、静的型付き言語を選択するメリットが出てくるのです。

また、プロジェクトの規模が何十人規模になってくると、(良くないことではありますが)自分のあずかり知らぬところで関数の型が変わるというようなことも有り得ます。

あくまで想定するプロダクトの性質や開発方針によって選択するものであって、すべてにおいてどちらの方が優れている、というような基準は存在しないのではないかと。
あなたが接しているプロダクトがこの世の全てではない、ということを理解して頂けると、他の方がコメントで言及されているいろいろな事が腑に落ちると思います。

foofoo 2013/02/28 11:22 Haskell勉強しないでこんな文章かけるなんてすごい!
(無知を公開する勇気が)

くけーくけー 2013/02/28 11:34 > Cookpad、Github、mixi、はてな、faccbook、amazon、みんな動的な型を持つスクリプト言語を使って、大規模サイトを作っています

このうちの1つの中の人ですが, 紹介されたようなコードは保守性が低いという理由でレビューで拒否される可能性が高いです.

perlcodesampleperlcodesample 2013/02/28 11:42 くけーさん

>このうちの1つの中の人ですが, 紹介されたようなコードは保守性が低いという理由でレビューで拒否される可能性が高いです.

 どのコードでしょうか。

perlcodesampleperlcodesample 2013/02/28 11:44 fooさん

>Haskell勉強しないでこんな文章かけるなんてすごい!(無知を公開する勇気が)

 すべての知識なんてだれも持ってないんですから、議論するのに全部知っているという前提はおかしいと思います。そういう風に言うと、何の話もできなくなっちゃいます。

sumiisumii 2013/02/28 11:54 > でも結局、静的型付き言語でも、実行時試験をしなくっちゃいけないので、確認する項目が減るわけでもないと思います。

まっとうな型システムは健全なので、型システムやコンパイラのバグがなければ、型システムが保証している性質は実行時テストが不要になるので、減ります。

(すみません、書く場所を間違えた&削除できないので再投稿です)

perlcodesampleperlcodesample 2013/02/28 12:01 anonymousさん

>条件分岐の全てを通るのに、関数の単体試験をしないとはどのような状況でしょうか。
>(そもそも条件分岐の全てを通る試験はinput/outputだけの試験ではないですよね。)

 どうして入り口から到達できない条件分岐があるのかを知りたいです。その処理は、どこからアクセスされるのでしょうか?

>例えば世の中には万が一にも失敗してはいけないシステムというものが存在します。
>そういったものは往々にして複雑なロジックを有していて、
>単純に動作確認をしてエラーが起きたら修正すればよい、というわけには行かないものです。

 そのシステムは、ソースコードの変更をした後に、確認をしないで、本番に投入されるのでしょうか。複雑なロジックを有していることは、静的な型の議論とは何の関係もないと思います。

>また、プロジェクトの規模が何十人規模になってくると、(良くないことではありますが)自分のあずかり知らぬところで関数の型が変わるというようなことも有り得ます。

 試験したら見つかると思いますよ。コンパイルチェックか実行時チェックかの差だけであると思います。

>あくまで想定するプロダクトの性質や開発方針によって選択するものであって、すべてにおいてどちらの方が優れている、というような基準は存在しないのではないかと。

 そんなことを議論しているのではないです。「変数に型がないということの利点」についての議論です。他の言語の用途を否定したことは、一度もないです。

perlcodesampleperlcodesample 2013/02/28 12:13 わた春香さん

>運が良ければ。悪かったらロケットが墜落しますね^^

 シミュレーターなどで、試験せずに、ロケットに投入ということを意味しておられますか。試験で、一度実行すれば、エラーがわかるということを僕はいっているのであって、本番でいきなり実行するということは言っていないです。

>要は、多くのエラーは「慎重にやれば」除けますが、モヒカンという人間は手を抜くことに全力を注ぐので、そんな作業はハノイの塔を動かすのと同義なのです。あとは手作業では 100% 取り除いたと確信するのは難しいのだから、それを 100% にする手段があるならそうするべきでは?という理性的な意見も一部にはあります。

 ソースコードの中では、プログラムのロジックを記述する部分が圧倒的に多いのに、、なぜ型の部分のチェックで信頼性を高めることができると考えているのかがわからないです。

 型チェックの分岐なんてソースコード全体の5%にみたないはずです。5%の信頼性をあげても、残りの95%の信頼性は上がらないです。

>結局言語もツールにすぎないので、要は適材適所ということではないかと。

 それはそのとおりで、僕がもともと認めているところです。でも今回の議論はぜんぜんそんな話をしているのではないです。「変数に型がないことの利点」について議論しているんです。言語否定とかは、一切していないです。

perlcodesampleperlcodesample 2013/02/28 12:18 sumiiさん

>まっとうな型システムは健全なので、型システムやコンパイラのバグがなければ、型システムが保証している性質は実行時テストが不要になるので、減ります。

 試験と言うのは、必ずしも型の試験をする必要があるわけではないです。ある入力に対して、正しい出力が得られることを試験すれば、十分なことがほとんどです。考えられるパターンで、網羅すれば大丈夫だと思います。

くけーくけー 2013/02/28 12:19 型を意識していないコードが感じられるコードはレビューで拒否されると思います.

たとえば
> 関数のオーバーロードが不要になる
のコードは, Strategy/Stateパターンにするか, 分割して1つの手続きでは1つの型しか受けいれないようにするインタフェイスの変更(その上で共通部分があればそこを1つの関数にするのはよい)が求められるでしょう.

わた春香わた春香 2013/02/28 12:29 > シミュレーターなどで、試験せずに、ロケットに投入ということを意味しておられますか。試験で、一度実行すれば、エラーがわかるということを僕はいっているのであって、本番でいきなり実行するということは言っていないです。

それは昔本当にそういうケースがあったということです。どんなに優秀な人材を集めて慎重に慎重を期しても人の手ですべてのテストを網羅するのは難しい。数学的に証明された検査は、それがカバーできるエラーは 100% 取り除けるので機械的なメソッドは信頼性の向上に大変有用である、ということです。

> 型チェックの分岐なんてソースコード全体の5%にみたないはずです。5%の信頼性をあげても、残りの95%の信頼性は上がらないです。

それがそうでもないのでモヒカンの皆さんが怒りかけているのです。型付きラムダ計算という理論から始まる、おそらく貴方がこの投稿をされた時に想定しておられなかった型理論というものが存在しており、それを元にした言語がここ10年やっと日の目を見るようになり、それが今ニッチな業界でトレンドを起こしているのです。貴方が想定している型というものと、世間で知られている型というものは大きく違う可能性があるので、少しお調べになってから結論を出されても遅くはないのではないかと思います。

anonymousanonymous 2013/02/28 12:31 > どうして入り口から到達できない条件分岐があるのかを知りたいです。その処理は、どこからアクセスされるのでしょうか?

上の方で入力と出力だけテストすれば良いとおっしゃっていたので、全分岐をテストするのは入出力の確認だけではないですよね、と申し上げました。それに、全分岐テストしていれば関数単体のテストもそこに含まれるのではないかと。
到達できない条件分岐があるなどとは一言も書いておりません。

> そのシステムは、ソースコードの変更をした後に、確認をしないで、本番に投入されるのでしょうか。複雑なロジックを有していることは、静的な型の議論とは何の関係もないと思います。

確かに複雑なロジックは関係ないですね。撤回します。
改めて"止まってはいけない"という一点のみで言及すると、動的型付き言語はどんなに慎重にテストを頑張っても型エラーが起きる*可能性を排除できない*ため、
例示したようなシステムには向いていない = *このケースでは*動的型けがデメリットになる という事です。
(perlcodesampleさんは、このエラーが起きる可能性というものを甘く見ているように思います。可能性が限りなく0に近づこうとも、0ではありません。万が一が本番運用時に起きてはまずいのです。誰かの首が飛ぶ可能性がある程度には。)

> そんなことを議論しているのではないです。「変数に型がないということの利点」についての議論です。他の言語の用途を否定したことは、一度もないです。

あなたの文章からは、動的型付けであることのデメリットがパフォーマンス面しかないように読み取れます。
利点を議論するためには欠点の議論も必要ですよね。
私がお伝えしたいのは、あなたが「利点」として挙げている項目は対象の性質によっては「欠点」にもなり得るので、その点についてもちゃんと考えましょうよ、という事です。
動的型付けが悪いとは全く思っていませんし、他の言語の用途を否定されたとも思っていません。

(ただ、動的型付けであろうとなかろうと裏にある「型」は意識しないとまずいとは思いますが…。)

perlcodesampleperlcodesample 2013/02/28 12:37 くけーさん

>関数のオーバーロードが不要になるのコードは, Strategy/Stateパターンにするか, 分割して1つの手続きでは1つの型しか受けいれないようにするインタフェイスの変更(その上で共通部分があればそこを1つの関数にするのはよい)が求められるでしょう.


 方針としては、よいと思いますが、異なる型の間で類似があった場合は、許容される場合もあります。

 たとえば文字列あるいは、オブジェクトを受け取ることができる関数があったとします。URLを文字列で受け取ることもできるし、URLオブジェクトを受け取ることができるような場合です。

my $url_str = 'http://some.host.com';
my $url_obj = URL->new('http://some.host.com');

このような場合は「Strategy/Stateパターンにするか, 分割して1つの手続きでは1つの型しか受けいれないようにする」という原則を、貫く必要がないと思います。

some_func($url_str);
some_func($url_obj);

# こちらは、くけーさんの方法
some_func_str($url_str);
some_func_obj($url_obj);

どちらを選択するかは、実装者が利用者にどう使ってほしいかと思うかによると思います。最初のパターンであれば、関数がひとつですむので、重複が少なく、保守性が上がりますね。

ふえぇふえぇ 2013/02/28 12:37 あの…あきらかにブログ主様の勉強不足ってだけの話ではあるんだけど。
米欄でボコボコ叩いたところで、型理論に関する下地かできてないのでスッと受け入れられるもんでは無いかと。

ちゃんと理論を勉強できれば良いけど、型付きラムダ計算はいきなり敷居が高すぎるし…
とにかく、もっと色んな言語を触ってみましょう。できればOCamlやHaskellなどで関数プログラミングの考え方を身に付けると良いかな。
2年も勉強すればこの記事は消したくなりますぜ(ニヤッ

perlcodesampleperlcodesample 2013/02/28 12:51 わた春香さん

>数学的に証明された検査は、それがカバーできるエラーは 100% 取り除けるので機械的なメソッドは信頼性の向上に大変有用である、ということです。

 でも計算間違い、分岐間違い、ロジックの間違い、画面の表示のエラーとか、プログラムで書く大半の部分のバグは、取り除けないですよね。カバーできる範囲が多いという論拠が、どこにあるのかが僕にはよく理解できないです。

>それが今ニッチな業界でトレンドを起こしているのです。貴方が想定している型というものと、世間で知られている型というものは大きく違う可能性があるので、少しお調べになってから結論を出されても遅くはないのではないかと思います。

 どの業界で、どんな分野で、信頼性を高めるのに役立っているのかを教えてください。それを教えてくれれば、あぁこの分野ではこうなのかぁということが理解できますが、すべての議論は漠然としていて、たんなる過剰不安なんじゃないかなぁと言う気持ちを僕に起こさせます。

perlcodesampleperlcodesample 2013/02/28 12:55 ふえぇさん

>あの…あきらかにブログ主様の勉強不足ってだけの話ではあるんだけど。

 そういうふうにいったら、何かに疑問をもっている人とかが、何も書けなくなるでしょう。この記事は「静的な型を持たないことの利点」について書いているのであって、関数型言語との比較について書いているのではないです。

ukayareukayare 2013/02/28 12:56 > でも計算間違い、分岐間違い、ロジックの間違い、画面の表示のエラーとか、プログラムで書く大半の部分のバグは、取り除けないですよね。カバーできる範囲が多いという論拠が、どこにあるのかが僕にはよく理解できないです。

あなたがコンピューターよりも性格に網羅的にカバーできるという根拠を教えてください

DryadDryad 2013/02/28 12:57 > どの業界で、どんな分野で、信頼性を高めるのに役立っているのか
こちらの記事とか良いのではないでしょうか。ちと長いですが(´・ω・`) http://ymotongpoo.hatenablog.com/entry/20111105/1320506449

sumiisumii 2013/02/28 13:05 > ある入力に対して、正しい出力が得られることを試験すれば、十分なことがほとんどです。考えられるパターンで、網羅すれば大丈夫だと思います。

それを人間がやるのは困難なので現に多くの人が苦労していて、実際に漏れが生じてバグやセキュリティホールになっているから、場合分けなどの漏れをコンパイル時に防ぐ静的検査が有用なのだと思いますが、まあそう思わないというのであれば仕方がないです。

ふえぇふえぇ 2013/02/28 13:14 学ぶべきは道具(関数型言語)の使い方、ではなく、プログラミングそのものに対する考え方(思想)のほうです。
変数に値を代入するというのはどういう事か、その値を計算/演算するというのはどういうことか、関数やメソッドを呼び出すというのはどういうことか、そこに型がどのように関わってくるのか…プログラミングは単なる手続きの記述では無いのです。
静的型付の関数型言語を身に付けることはそのための近道だと言っています。

主様が「型」という難しい題材について議論するのは、それからでも遅くないでしょう。

perlcodesampleperlcodesample 2013/02/28 13:15 anonymousさん

普通単体試験というのは、小さくわけた部品自体の試験をいうのだと思っています。

入力 -> A -> B -> C -> D -> E -> 出力

と続くとすれば、B,C,Dなどの細かな部分のチェックをしなくても、入力と出力をチェックできればよいという意味で書きました。

>改めて"止まってはいけない"という一点のみで言及すると、動的型付き言語はどんなに慎重に>テストを頑張っても型エラーが起きる*可能性を排除できない*ため、例示したようなシステムには向いていない = *このケースでは*動的型けがデメリットになる という事です。
(perlcodesampleさんは、このエラーが起きる可能性というものを甘く見ているように思います。可能性が限りなく0に近づこうとも、0ではありません。万が一が本番運用時に起きてはまずいのです。誰かの首が飛ぶ可能性がある程度には。)

 はい。このエラーが起きる可能性を甘く見ています。プログラムのロジックのバグのほうが圧倒的に量が多いと思いますし、それを排除できないのは、どのプログラミング言語も同じだからです。みなさんの反応を見ると、過剰不安ではないかと思っています。

わた春香わた春香 2013/02/28 13:19 > でも計算間違い、分岐間違い、ロジックの間違い、画面の表示のエラーとか、プログラムで書く大半の部分のバグは、取り除けないですよね。カバーできる範囲が多いという論拠が、どこにあるのかが僕にはよく理解できないです。 

その理解できない理由が型理論に対する不理解にあるということです。

> どの業界で、どんな分野で、信頼性を高めるのに役立っているのかを教えてください。

ニッチな業界ってのはある程度の狭い範囲の人たちの間でというくらいの意味にとってくださいな。

> たんなる過剰不安なんじゃないかなぁと言う気持ちを僕に起こさせます。 

それ以上は怒られるから言わん方がいい。


結局つまりみなさんが言っているのは、貴方がこの投稿で挙げた「利点」というのは、(習得のしやすさを除けば)型が強い言語でも等価なものが実現されているということです。この記事は単に perl が java や c++ より優れている点を述べているのみであって、その利点は perl の型が「弱い」ために生じているのではありません。

perlcodesampleperlcodesample 2013/02/28 13:30 Dryadさん

> どの業界で、どんな分野で、信頼性を高めるのに役立っているのか
> こちらの記事とか良いのではないでしょうか。ちと長いですが(´・ω・`)

 読みました。以下のように書いてありました。

>もちろん実際はそうは行きません。OCamlの型システムは多くのバグに対して役に立ちません。しかしながら、テストではかなり見つけにくいようなバグも含め、型システムが効果的なバグというのは驚くほどたくさんあります。

 でも実際の例が少ないので、もう少し、関数型言語の関連記事を読もうと思います。

わた春香わた春香 2013/02/28 13:30 うーんちょっと違うか。
perl は型を弱くすることによってその利点を身につけたけど、ある言語は型をより強くすることによってその利点を身につけた、くらいですか。C++ はしょうがないけど Java の型の強さはホント中途半端。

くけーくけー 2013/02/28 13:32 程度問題ではあるので許容されることもあるのは否定しません.

ただし, コメントの例では

1.

some_func_str($url_str)
some_func_obj($url_obj)
の両方を作って

some_func_obj($url_obj) の実装は
{
some_func_str($url_obj->as_string);
}

とする($url_obj は 標準の URI のようなものとする)か

2.

some_func_str($url_str) だけにして
呼び出し側で $url_obj->as_string を呼ぶ

のどちらかへの変更で, ソースの可読性
(この手続きだけでなく, 利用する側も含めて)
が上がり保守性が向上すると考えます.

perlcodesampleperlcodesample 2013/02/28 13:36 くけーさん

 一般的には、ケースバイケースだと思いますよ。規約がある程度社内に存在するなら、それを守るのがよいと思います。

anonymousanonymous 2013/02/28 13:38 > 入力 -> A -> B -> C -> D -> E -> 出力
> と続くとすれば、B,C,Dなどの細かな部分のチェックをしなくても、入力と出力をチェックできればよいという意味で書きました。

perlcodesampleさんを除く、コメントされた(少なくともカバレッジという言葉を持ち出された)全ての方は、単体テストとはA,B,C,D,E全てテストすることだという前提で考えられていると思います。
私もそうです。
そうしないと出力以外の副作用を確認できませんし、もしかしたらその出力はたまたまあっていただけかもしれません。
B、C共にバグっていたため結果が正しく見えた、ということが有り得るからです。実際よくあります。

> はい。このエラーが起きる可能性を甘く見ています。プログラムのロジックのバグのほうが圧倒的に量が多いと思いますし、それを排除できないのは、どのプログラミング言語も同じだからです。みなさんの反応を見ると、過剰不安ではないかと思っています。

上記の通り、少なくとも私が言及したようなミッションクリティカルなシステムにおいては(他も程度の差こそあれそうだと思いますが)厳密なテストが求められます。
確かにバグを全て排除できるとは言いませんが、*上記のようなテストを行った上で*更に信頼性を高めるためには、型は非常に有用なのです。コンパイラによって保障されているのですから。
甘いテストによる抜け漏れを後からフォローするよりも、過剰不安であっても極限まで信頼性を高める必要があるシステムも存在するという事をご理解ください。

最後に一点補足しますが、どなたも静的型付けだからテストしなくていいとは言っていないですが、そこは伝わっているのでしょうか。
そこが少し気になりました。

...... 2013/02/28 13:42 > この記事は「静的な型を持たないことの利点」について書いているのであって、関数型言語との比較について書いているのではないです。
「型」に関する記事で避けて通れない「型理論」の話がしたくて出てきている関数型言語の話なのに、
どうして「関数型言語との比較について書いているのではない」と逃げてしまうのだろう?
自分が型理論について疎いのなら少し調べてみればよいだけなのに。

perlcodesampleperlcodesample 2013/02/28 13:45 ふふぇさん

>学ぶべきは道具(関数型言語)の使い方、ではなく、プログラミングそのものに対する考え方(思想)のほうです。変数に値を代入するというのはどういう事か、その値を計算/演算するというのはどういうことか、関数やメソッドを呼び出すというのはどういうことか、そこに型がどのように関わってくるのか…プログラミングは単なる手続きの記述では無いのです。静的型付の関数型言語を身に付けることはそのための近道だと言っています。主様が「型」という難しい題材について議論するのは、それからでも遅くないでしょう。

 僕はこの記事で型理論について書いているわけではないですし、型理論の専門家でもないです。僕はこの記事で、変数にどのような型の値でも代入できることの利点を書いているだけです。

perlcodesampleperlcodesample 2013/02/28 14:09 anonymousさん

>そうしないと出力以外の副作用を確認できませんし、もしかしたらその出力はたまたまあっていただけかもしれません。B、C共にバグっていたため結果が正しく見えた、ということが有り得るからです。実際よくあります。

 でも粒度を小さくするかどうかは、信頼性がどれだけ求められるかに依存すると思います。試験を増やすと、ソースコードを書き換えたときに、関連する試験すべてを書き直さないといけないので、内部の変更が行いにくくなるので、ケースバイケースだと思います。

 テストケースをうまく選択すれば、入力と出力の結果確認でよい場合も多いと思います。

>確かにバグを全て排除できるとは言いませんが、*上記のようなテストを行った上で*更に信頼性を高めるためには、型は非常に有用なのです。コンパイラによって保障されているのですから。

 ミッションクリティカルなシステムには静的な型を持つ言語が必要と主張されますか。それは言いすぎだと思います。たとえば、Webから取引するような証券システムをPerlやRubyやPythonで組んでもよいと僕は思います。

わた春香わた春香 2013/02/28 15:21 よしモヒカン視点からまとめましょう

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

型推論があればほとんど同じ構文を実現出来ます。(多くの関数型言語は束縛なので代入ではありませんが)実際強力な型付けの言語は型の宣言をつけようとすると長く複雑になることが多いですが、型推論のお陰でそれを意識する必要は殆どありません。LL でも結局はこの変数にどんな型の値が入っているかはある程度意識しなければいけませんよね。
まさか変数の再利用を推奨しているわけではないでしょう。

- 記述量がとても短くなる

型推論とインデントのお陰で haskell はかなり簡潔にわかりやすく書けます。型推論についての当節の意見は間違いです。右辺には必ずコンストラクタか関数が来ますので推論が出来ないのは特殊なケースに過ぎません。コンパイル速度については、実行時にその都度ハッシュを参照するよりは早いかと。メソッド補完は変数の型宣言のある言語の特権ですね。

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

これは抽象化の問題であって型の強弱の問題ではありません。Java だって設計がうまくいってればその変更は必要ないことも大いにありますね。場合によっては perl でも書き換える必要があるでしょう。

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

結局型の判断を if 文でしていますから、どこで分岐をしているかの違いでしかありません。確かに C++ や Java で書くと冗長になりますが、それは型のせいではなく構文のせいです(あと型推論がないためか)。場合によっては代数的データ構造でより簡潔かつ安全にかけますね。

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

それは java 特有の現象ですよね。それに処理が重複するなら基本的には基底クラスに書けば良いだけかと。

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

型多相によってタイプ量はLLと大差なく、しかし型安全な関数がかけます。

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

 複雑なものになると、メソッドがどんなオブジェクトを返しているかひと目でわからない場合がありますね。オブジェクトが動的に変更されていたりするからです。rails のソースなんかまさにそうです。そのため、整備されたドキュメントに頼る必要があります。まあこの場合問題になるのは「本当にその型の値が帰ってくるのか」ということでしょう。

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

haskeller 怒りの猛抗議。どう考えても設計に左右される要素。

以上

AnonymousAnonymous 2013/02/28 17:14 ※批判をしたいわけではありません
 コメント欄などからこのように多くの批判を受けて困惑されているのでは、と思い、書きます。

 多くの読者がタイトルの「変数に型がないということの利点について考える」から、筆者が型の強弱と動静を混同しているようだ、と考えたのではないかと思います。この点についてですが、RubyにもPythonにも型はあります。もう一度言いますが、型はあります。ただ、それが動的に変更出来るだけです。
 また、動的型付け言語における重要なキーワードである、「Duck Typing」が本文中に登場しないことにも違和感を覚えたことかと思います。

 私がまず目についたのは上記二点です。これらのことから、失礼ながらおそらく筆者はまだ言語に関する知識がそれほどない、と多くの人が判断したのではと推測しています。また、そのとおりであろうかと考えます。

 ですが、「型は補助的な情報でありプログラミングの本質ではない」という種の主張や、「型の整合性はコンパイラではなくテストに担保すればよい」といったような主張は正当です。(実行時テストはダメです。逆にコスト増になります。ユニットテストしましょう。)観点は正当で、もっともなことを述べられているので、Google検索しつつめげずに反論を行ない、知識を強化なさって下さい。

 “自ら信じるもののために戦え。ただし、負けは潔く受け入れよ。”

perlcodesampleperlcodesample 2013/02/28 18:45 ちょっとみなさん、関数型言語に熱狂しすぎではないかなぁと思いました。最終結論を,
勝手に僕の記事が間違っているという方向に持っていこうとしようとしていると思いました。申し訳ありませんが、そういうコメントは削除させていただきました。もう少し冷静になってみてください。

...... 2013/02/28 18:50 だから関数型言語じゃなくて型理論が大事なんですっての。
そこを履き違えちゃいかん。
関数型言語だって LISP 系は動的型付けですよ。

perlcodesampleperlcodesample 2013/02/28 19:02 わた春香

ちょっとhaskell読んでみましたが、難しいです。
http://itpro.nikkeibp.co.jp/article/COLUMN/20060915/248215/

...... 2013/02/28 19:05 軽く読んでみるなら、HaskellよりOCamlを勧めますよ。
(Haskellは型クラスの概念がなかなかわかり難いので)
let文と幾つかの構文だけ覚えて、あとはインタプリタで2〜3時間遊んでみるとよいでしょう。

perlcodesampleperlcodesample 2013/02/28 19:09  型理論はあまりに抽象的で専門的すぎて、今のところなんともいえないです。難しいという印象です。変数に、どんな型の値でも代入できれば、いろいろ難しいことかんがえなくてもよいのになぁと思いました。

ふえぇえふえぇえ 2013/02/28 20:06 どっちが冷静じゃないんだか…

んー。

僕は「本物のプログラマは…」は難しいサイトだと思ってるので、そこで挫折したからと言って投げ出してしまうのは早計だなぁと。
もし、一連の流れが悔しいと思うなら、ゆっくりでも良いから、ちゃんとした知識を身に付けちゃいましょっ

OcamlもHaskellも、Web資料だけで学ぶのは敷居が高いかもしれません。
もし、主様自信、少しでも前に進みたいと思うなら、本を一冊読んでみては如何でしょう。

http://www.amazon.co.jp/gp/aw/d/4274068854/ref=redir_mdp_mobile

他の記事をざっと読ませて頂きましたが、これだけのスキルをお持ちなら、ゆっくり読めば理解できる内容と思います。
その上で、動的型付け言語の魅力を存分に語れば良いのです。

そうですね、Functorあたりまで読んでから、anonymousさんのいう「Duck Typing」を検索してみたら、何か閃くかもしれません…?

ふえっふえっ 2013/02/28 20:20 あらごめんなさい。
リンクがモバイルさいとになっちゃってますね…

型チェックは簡単なバグを減らす型チェックは簡単なバグを減らす 2013/02/28 21:12 プログラミングで次のようなミスはありがちなのではないでしょうか。

- 変数名、メソッド名のタイポ
- メソッドに与える引数の数を間違える

静的型付き言語では、コンパイルが通りさえすれば、これらの間違いが存在しないことが保証されます。

perlで書かれた、ある一定以上大きいプロジェクトで長年運用をしていると、「どこでも使っていないと思われるメソッドだけど、怖いから残したままにしておく」、とありませんか?
その点に関して言えば静的型付き言語の方が保守しやすいシステムになるのではないでしょうか。

bleis-tiftbleis-tift 2013/02/28 21:38 色々と気になる部分があったので、書いてみました。

http://bleis-tift.hatenablog.com/entry/2013/02/28/%E3%80%8C%E5%A4%89%E6%95%B0%E3%81%AB%E5%9E%8B%E3%81%8C%E3%81%AA%E3%81%84%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8%E3%81%AE%E5%88%A9%E7%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%80%83%E3%81%88

perlcodesampleperlcodesample 2013/02/28 22:43 > プログラミングで次のようなミスはありがちなのではないでしょうか。
> 変数名、メソッド名のタイポ
> メソッドに与える引数の数を間違える

 これはありがちなミスのですが、どうしてそこまで、コンパイル時に発見できるということが大きなメリットなのかがよくわかりません。少しのメリットじゃないでしょうか。

>perlで書かれた、ある一定以上大きいプロジェクトで長年運用をしていると、「どこでも使っていないと思われるメソッドだけど、怖いから残したままにしておく」、とありませんか?その点に関して言えば静的型付き言語の方が保守しやすいシステムになるのではないでしょうか。

 うーん、少し例外的な状況ではないでしょうか。僕は、静的な型を持つ言語だから、信頼性が高く、保守しやすいシステムになるという結論にはやっぱり同意できないです。パフォーマンスが問題にならないのであれば、動的な型を持つ言語のほうが開発効率は高いかなぁと思います。

perlcodesampleperlcodesample 2013/02/28 22:46 ふえぇえさん

 ありがとうございます。関数型言語についても、さらによい記事を書けるように、学んでみたいと思います。

perlcodesampleperlcodesample 2013/02/28 22:47 bleis-tiftさん

 ありがとうございます。見てみます。

...... 2013/02/28 22:51 > これはありがちなミスのですが、どうしてそこまで、コンパイル時に発見できるということが大きなメリットなのかがよくわかりません。少しのメリットじゃないでしょうか。
例えば貴方が variable0 という変数を使っていたとしましょう。
で、1箇所だけ variableO と誤記してしまって、それによってテスト工程でエラーが起きたとする。
このとき、貴方はこの1箇所の variableO を見つけることができるでしょうか?
コンパイラは、何も言わなくても一瞬で見つけてくれます。

KleisliTripleKleisliTriple 2013/02/28 23:29 Haskellはドヤ顔するための言語、レガシーJavaは確かにめんどくさい、どちらも静的型付けをDISするのに持ち出すのはフェアじゃない。Haskellは素晴らしい言語だし使いこなせる人は誇りに思えばいいけど、Kleisli morphismは扱いが厄介で、静的型付けがいいか悪いか議論する時に持ち出しても主張を聞いてもらえなくなるだけ。静的型付けの良さを語るならOCamlやScalaの方が実用的でよい。

gnetygnety 2013/03/01 00:01 実際にテストすればわかるって言うけど、静的型の場合はテストしなくてもわかるというところがメリットになるのだと思う。
先にわかるか後でわかるかの違いと言うのも少し違って、後で発見した場合にはどこで誤っているか探す範囲が広くなって大変になるからね。
型を書かないほうが楽だって言うのはわかるけど、型があったほうが読みやすいので保守性があがるっていうのと複数人で作業する場合に情報伝達がしやすいという点でもメリットがあるね。

...... 2013/03/01 01:01 http://anond.hatelabo.jp/20130301010020

おむおむ 2013/03/01 01:47 不正な使い方をすることで実行時にエラーなく一見動いているように見えるものの、実は重大なバグを内包している、というのが
あらゆる開発者を永年悩ませ続けている最悪のケースであり、
あらゆるC++の教本だのコラムだのがこぞって「コンパイル時にエラーを出す」ことを目標に黒魔術の呪文のような構文を書かせる理由です。
不正な使い方をされると困る関数は、そうされようとする前に(最低でもassert、出来ればコンパイル時)エラーを出すのが望ましいです。
記事を見る限り、そのような最悪のケースを防ぐ手立てがされているようには思えません。残念ながら、プロジェクト終盤に頭を抱えることになるでしょう。

型チェックは簡単なバグを減らす型チェックは簡単なバグを減らす 2013/03/01 11:32 > これはありがちなミスのですが、どうしてそこまで、コンパイル時に発見できるということが大きなメリットなのかがよくわかりません。少しのメリットじゃないでしょうか。

あなたは他人の書いた数千、数万行のコードを保守したことがありますか?
その中で、あるメソッドfooの引数の型を変えたいときに、影響がどこまであるかすぐに判断できますか?分からなくて怖いからfooはそのまま残しておいてfoo2みたいなのを新しく追加して使うみたいなことはないですか?

静的型付き言語ではコンパイルが通れば、誰の書いたコードであっても、ある一定の整合性が保たれていることがソースコード全体で保証るため、このような問題は起きません。

客観的に考えてどちらが保守性が高いかは明らかなように思います。

kinokino 2013/03/01 14:45 人間が扱うのは文書にできることだけ、アトムの型は十誌に足りるので、値に型があれば十分。問題は集まったものをどうするか。これを型とすると、無限の広がりがある。これの述語を生成する機能が必要だ。。

tt 2013/03/01 16:12 perlcodesampleさんは型理論について詳しい知識を持っておられないようで、動的型付けの言語をさも万能かのように書いていらっしゃるけど、バグの発見に関する基本的な考え方には私も賛成です。
強い静的型付けの言語であれば、型に関する不整合をコンパイル時に即座に発見することはたしかに可能になりますが、現実の開発やプロジェクトで、CやJavaのように静的型を手動で明記する言語を使ったからといって、動的型付けの言語に比べて生産性や品質が向上したという客観的な分析は聞いたことがありません。
一方で、保守性について、動的型付け言語のほうが静的型つけの言語に比べて保守性が向上したという研究や客観的な分析についても聞いたことがありません。

perlcodesampleperlcodesample 2013/03/01 21:11 tさん

 ありがとうございます。保守性の定義があいまいすぎて、誤解を生む表現になっていますが、この文章で保守性とは、ソースコードの重複を少なく、素直に、シンプルに書くことができるという程度の意味でした。

 結論としては、型を意識しないでプログラムを書けたほうがプログラムの内容に集中できて楽です。ミッションクリティカルな分野でも信頼性が足りないということはなくって、自動試験によって、信頼性を担保できると思います。

コンパイルエラー?コンパイルエラー? 2013/03/01 21:13 最初の議論は型宣言しなくても良い言語の話だと思ったけど
いつの間にコンパイラ言語の話になったんだろう、
コンパイルエラーがどうのこうのって。
変数名、メソッド名のタイポと「型宣言不要の利点」はまた別の話じゃないか?
「品質を試験で担保する」ってころからこの流れになった気が……

とりあえずそれはおいておいて、
網羅的なテストをすればいいとは言うけど
修正の度にシステムテストするのはとても嫌過ぎる
もうテストは嫌だーーーーーーー(泣

perlcodesampleperlcodesample 2013/03/01 21:17 >あなたは他人の書いた数千、数万行のコードを保守したことがありますか?
>その中で、あるメソッドfooの引数の型を変えたいときに、影響がどこまであるかすぐに判断できますか?

 でも、たとえば、forループの構造を変えたときに、どこまで影響があるかわからないじゃないですか。なぜそこまで、品質や信頼性を、静的な型をコンパイラがチェックしてくれることに、そこまで大きく期待しているかがわからないです。

 本当にプログラムに、高い品質や信頼性を得たいのならば、本当に大事なロジックに関しては、自動試験を書いて、ソースコードにバグが含まれたときに検知したほうが、ずっとよいと思います。

perlcodesampleperlcodesample 2013/03/01 21:19  それとGUIなどの分野はスクリプト言語が向いているとは思っていませんよ。万能ということはいっていないですよ。けれども、大規模でミッションクリティカルなWebシステムを作れる能力を、スクリプト言語は持っていますよ。

perlcodesampleperlcodesample 2013/03/01 21:26 おむさん

 僕がこのサイトで、スクリプト言語を語るときに念頭においているのは、テキスト処理、システム管理、Webシステムです。万能とかは言わないけれど、この分野では、動的な型を持つ言語(つまりスクリプト言語ですけれど)で開発したほうが楽です。

 Webも含めてテキスト処理周辺ならば、自動試験も書きやすいので、信頼性も落ちないです。自動試験を実行して、信頼性を担保するので、プロジェクトはうまくいきます。

perlcodesampleperlcodesample 2013/03/01 21:28 ...さん

>例えば貴方が variable0 という変数を使っていたとしましょう。で、1箇所だけ variableO と誤記してしまって、それによってテスト工程でエラーが起きたとする。

 はい自動試験を書いておけば、実行したときにエラーで試験が落ちるので検知することができます。だから、何の問題もないです。

perlcodesampleperlcodesample 2013/03/01 21:30  基本的に、Webシステムやテキスト処理においては、入り口がテキストなので、型の重要性は、低いんです。それよりも、型を意識しないで書けたほうが楽なんです。動的な型を持つ言語で書けば楽です。

PocoPoco 2013/03/01 21:47 >なぜそこまで、品質や信頼性を、静的な型をコンパイラがチェックしてくれることに、そこまで大きく期待しているかがわからないです。
誰もそこまで期待していないです。
perlcodesampleさんが大げさに解釈しているだけです。
コメントした人の中で具体的に誰がそんな大きなこと言ってました?

>けれども、大規模でミッションクリティカルなWebシステムを作れる能力を、スクリプト言語は持っていますよ。
誰も能力がないと言ってないですよ。
向かない、と言っているんです。

>はい自動試験を書いておけば、実行したときにエラーで試験が落ちるので検知することができます。
この自動試験のテストセットって人間が用意するんですよね?
コンパイラ出すエラー報告と同様に「漏れ無く」用意できるものなのですか?
私の認識では、人間は「間違いやすい」し「よく見落とす」もので、コンパイラがチェック可能なレベルのテストセットの作成は不可能に近いと思いますが。。

perlcodesampleperlcodesample 2013/03/01 21:58  重複が少なく書けるというのが、なんだかうさんくさいなーと思っている方はPerlのソースコードも呼んでみてくださいね。以下はとてもきれいに書かれたPerlのWebフレームワークMojoliciousのソースコードになります。

 https://github.com/kraih/mojo

perlcodesampleperlcodesample 2013/03/01 22:15 Pocoさん

>向かない、と言っているんです。

 それは強い偏見だと思います。そんなことはないです。それを流布するほうが、間違った観点を持っていると思います。

>この自動試験のテストセットって人間が用意するんですよね?

 そうです。試験は人が準備して作成するものです。試験にもミスがつきものですが、それは当然のことだと思います。

 品質は試験によって担保されます。自動試験というのは、自動で行う試験で、一度書いておけば、プログラムが自動で試験してくれます。テストパターンを記述して、プログラムが正しく動くかどうかを試験します。もし間違っていれば試験が落ちます。

 コンパイラは型チェックしかしてくれないので、入力と出力が正しく合致しているかの試験は、行わないといけないです。

 どうして型チェックが正しいからといって、バグが少ないなんて保証できるんでしょうか。品質が最重要のプロジェクトであれば、いくら型エラーをコンパイラが検知してくれても、「入力 -> 出力」のチェックに関しては該当箇所をすべて試験しないといけないはずです。

 とすれば、エラーの発見のタイミングが、コンパイル時か実行時かの違いにしかならないと思います。だから100分の5くらいは、静的型を持つ言語のほうが、早く発見できるという点で、優れていると思いますが、向かないとか、決定的に信頼性や品質を落とすという考え方には同意できないです。

PocoPoco 2013/03/01 22:37 >それは強い偏見だと思います。そんなことはないです。それを流布するほうが、間違った観点を持っていると思います。
言葉足らずですみません。
静的言語に比べて、と言う意味です。
理由は後述の品質の担保にあります。

>もし間違っていれば試験が落ちます。
テストケースが漏れていたら落ちませんよね?
先程も「漏れ無く」を強調させて書かせていただきましたが、
人間は【漏れ無く】テストケースを用意できるものなのですか?
【漏れ無く】というのが重要なのです。
perlcodesampleさんはテストケースを後で追加する羽目になったことはないのですか?

>品質は試験によって担保されます。
当然です。
コメントをされた方々はこれに関して何も異議と唱えていません。
誰が異議を唱えていました?

>どうして型チェックが正しいからといって、バグが少ないなんて保証できるんでしょうか
型の不整合が起こり得ないことがコンパイラによって保証されるからです。
人間は「間違いやすい」し「よく見落とす」もので、型関連のテストを【漏らす】可能性があります。
【漏らす】可能性が0になったなんて誰も証明出来ません。
ですが、コンパイラはそれを保証します。
この時点で、「人間だけで作ったテストケースで担保する品質」vs「人間が作ったテストケース+コンパイラの保証付で担保する品質」は
後者の方が高いと思いませんか?

ぽんぽこ太郎ぽんぽこ太郎 2013/03/02 00:28 このトピックの中心は型宣言をしないことがバグを生む要因になりうるか
だったと思うのだけれど
なにゆえコンパイラ言語とスクリプト言語の話になっているのでしょう。
型宣言が必須な事とコンパイルが通ることは必ずしもイコールではないでしょう?

まぁ型宣言しないけどコンパイルする言語なんて聞いたことありませんが……
そういえばVBAマクロなら型宣言をしないで書けるし
デバッグメニューの中にコンパイルもありますよ!!
触ったことないけどVBも暗黙の型宣言ができるかも
そうか!みんなVBを使えばいいんだ(違

すいません暴走しました。
型宣言とバグの関係でしたね
といってもここでよく話題に上がっているRubyやPerl、
触ったことないんですよね
PHPなら改修でちょっと触りましたけどその少ない経験で何か型のバグあったかな?

うろ覚えですが、
真偽値の「True」が返ってくるはずが実際は数字の「1」が返ってきていて、
実際は通るはずだった(通ってると思ってた)分岐を通っていなくて
画面に想定された結果が出てこない、
理由が分からなくて困ったような記憶が……
あちこちにvar_dumpを追加しまくって後から消すのが大変でしたね(笑)

PHP 型の比較表
http://php.net/manual/ja/types.comparisons.php

...... 2013/03/02 01:34 > そうか!みんなVBを使えばいいんだ(違
確かに VB のバリアント型は動的型付けと言ってよいかもしれませんね。

> どうして型チェックが正しいからといって、バグが少ないなんて保証できるんでしょうか
型があっていれば「入ってくる値は整数に限られる」などの仮定が置けるので検査範囲が狭まる。
文字列かもしれないし真偽値かもしれないし新たに定義したクラスかもしれないし…… となったら、
本気で検査しようとしたら幾ら検査項目があっても足りませんよね。
(特に弱い型付けの言語だと型がおかしくても変な値を返しつつ平気で実行できてしまう)

SatooooooooooooSatoooooooooooo 2013/03/02 02:32 性的言語ならコンパイル時に検出できるエラーが、二分岐に埋め込まれて居る場合、二回実行しないと検出できない。だからテストケースで本当に検出したいバグに辿り着くまでに余計な手間がかかる。
あと、静的型言語はIDEが強力なのでリソースの質によらず一定の生産性を担保できる。
リソースの質に自信ないと、動的型付言語を大規模案件に採用するのは無理。

teatea 2013/03/02 03:27 よくわかりませんが、本エントリの主眼は
・動的型付け言語は開発効率に優れる
・静的型付け言語はパフォーマンスに優れる
だと解釈しています。正しいでしょうかね?これはそんなに奇抜な意見でないと思いますし、同意です。変更に強いという主張は開発効率の高さを示すためのものなのでそこに過度に噛み付くのは本論からはずれるようにも思います。
保守性というソフトウェアの性質も「容易に変更可能か」という資質と「変更時の品質確保がしやすいか」という資質に分かれていて、動的型付けの言語は前者に優れ、静的方付けの言語は後者に優れるくらいの評価ではないでしょうか。

結局のところそれぞれの言語の資質にあった設計を行うのが重要であって、特定の種類の言語だけ持ち上げるのは視野狭窄に陥る危険を招きかねず、程々にしたほうが良いのでは?というのがエントリを読んで思った素直な感想です。

以下蛇足。
少なくとも自分の周りでは保守性に関して静的型付け>動的型付けって話を聞いた事ないです。その逆もないですが。経験則ながら保守性って結局開発者の能力依存であって言語依存しないってのが実感です。
一方で動的型付けな言語は気軽にさくっと書けるとか覚える事少なくて学習コストが安いとかで開発効率の良さは実感として持っています。もし保守性が悪いという主張がこういった動的型付けな言語の敷居の低さが質の悪いプログラマを量産している事に起因するとしたら払拭すべき悪名かもしれませんね。

で、動的型付けな言語の最大の問題はエントリの最後に言及されている通りパフォーマンス問題に収斂されるかと。大規模開発で動的型付けな言語が選ばれないのは保守性が原因ではなくて、パフォーマンス問題が原因のはずです。プログラムの総量が増えれば塵も積もれば何とやらでパフォーマンスが維持できなくなる危険性が上がりますから。
有名な大規模サイトが動的型付け言語で成功しているのは、パフォーマンス問題をサーバ分散化技術でカバーしつつ動的型付け言語の生産性メリットも享受しているところだと思ってます。もしそういったサイトを模範にするなら動的型付け言語の良さを語るだけでなく、静的型付け言語の良さも同じくらいの熱心さで語れるようにしつつ、適材適所なソフトウェア設計ができるよう訓練するべきかなーと。最近は細かな変更要件が多く比較的品質部分で致命傷にならないフロントエンドサーバを動的型付け言語で書いて、逆な性質のバックエンドサーバを静的型付け言語で書くとかそういった構成も目に付きますし、エントリ冒頭で心配されるほどスクリプト言語の信頼性が低いとは思えません。(こういうのに統計とかあるんですかね?)

以上、駄文失礼しました。何かの足しになれば幸いです。

celaeno_wcelaeno_w 2013/03/02 12:49 素敵なテスト環境を構築する人は、ここで書いてることをメリットだーとか言って、さくさく書けるぜヒャッハーなんて思わないと思うけれど・・・
(きちんとテストを前提とした設計と実装を行うと思うし、そうした場合、静的だろうがなんだろうが、開発効率にさしたる違いはないと思うけれども)

これも強い偏見ですから気にしないでください。

ふぇぇえふぇぇえ 2013/03/02 16:52 http://anond.hatelabo.jp/20130302164711

anonymouscowardanonymouscoward 2013/03/02 19:41 もし、この記事を書く時、投稿ボタンを押す前にコンパイラを通していれば、faccbookというtypoに気がつくことが出来たのに。追記もしているので、一度実行しただけでもバグに気付けないってことですね。

perlcodesampleperlcodesample 2013/03/02 20:36  みなさんおつきあいありがとうございました。いろんな誤解を与えてしまいましたので、動的な型を持つ言語は、型を意識しなくてよいので、それなりの信頼性を保って、開発効率がよいという結論にしたいと思います。

 本文では、C++とJavaを想定していたので、型推論を含む静的な型を持つ言語の一般論としては却下したいと思います。C++、Javaとの比較だと思って読んでみてください。

 ありがとうございました。

celaeno_wcelaeno_w 2013/03/03 12:05 閉じたので、完全に蛇足ですが、信頼性は担保されないですってば。
変数の値に対する判断は、完全にプログラマ任せです。
それなりのブログや本で、変数の中身がどういうものか、変数名で示せと書いてます。
数値なのか文字列なのか、入力値そのものなのか、クレンジング後の値なのか、何でも入ってしまう分、逆に神経質になる必要があります。

言語の特性はトレードオフで、手軽に扱える分のサポートをプログラマが考慮しないといけない。
ここに書いてあることが理由で開発効率が上がるのは、ものすごく小さいプロジェクトか、天才だけです。

asdfasdf 2013/03/03 15:03 開発効率というのはデバッグも含めてですよね?

コンパイラーによって指摘されて修正するのと、C0カバレッジから問題点を探して修正するのでは、前者の方が効率がいいと思うのですが。

takano32takano32 2014/07/02 17:28 「スクリプト言語というのは、コンパイルと一緒に実行してしまいます。すると、バグがその時に見つかるので、バグの発見しやすさは変わらないと思います。」

型がない、型がない、と言ってますが、あなたが言ってるのは動的型付けのことです。
動的型付けでは、静的型付けとは違い、実行時にはじめて型が異なるバグを発見できます。それは、引用に書かれている通りです。

で、何が言いたいかと言うと、動的な片付けでは型が異なるバグというのはバグの箇所を実行しなければわかりません。つまり、C0 の網羅率が 100% じゃないと同じ品質にはならないということですね。

わかりますか?

perlcodesampleperlcodesample 2014/07/05 18:37  試験というのは、出力の試験が大事だと思います。もし中間の型が間違っていたら、動的型付けにしても、静的型付けにしても、最終の出力の試験が通らないです。結局のところ、出力のチェックをする必要があるので、品質に影響があるとは、思いません。

anon.anon. 2014/09/22 12:35 「変更に強い」について:静的型付けでも直和型とパターンマッチで処理を型ごとに分岐するとか容易かつ余裕でできるんですけどね。OCamlやHaskellで動的型付けなSchemeのインタープリタとか書いてみればどういうことかはすぐにわかります。さらにコンパイラが分岐のexhaustiveness検査もしてくれるのでほんとうに楽。Perlが「変更に強い」というその意味の「変更に強い」でいいなら、代数データ型をきちんと使えば静的型付け言語も「変更には強い」のですよ。Lisp的なヘテロリストもできます。ただ、もちろんそういう、実質的に動的言語+αになってしまうような型の使い方は(やはり型検査の恩恵を損ないがちなので)あまりしないわけですけど。

> もし中間の型が間違っていたら、動的型付けにしても、静的型付けにしても、最終の出力の試験が通らないです。

意味がよくわかりません。「中間の型が間違っていたら」ってなんですか(まともな静的型付けなら型が間違ってたらそもそもコンパイルできませんが)? 出力のチェックをした時にエラーがあったとして、型に由来するエラー(動的言語の実行時エラーの多くはこれ)の頻度は減るし、出力のエラーの原因が型の問題ではなくロジックの誤りであることが保証されるならデバッグが遥かに容易です。そもそもダイクストラの「テストはバグの存在を示すには有効だが、バグが存在しないことは証明できない」という(当たり前の)教訓を踏まえていれば、テストの種類を、型の整合性チェックで本質的に事前に削減することの重要性がわかるはずなのですが。

# まあ私にとっての表現力の高い静的型付けのメリットは品質保証云々よりは、写像合成でデータを変換していくというモノの考え方を型システムが導いてくれるのと、トップレベルでの型をきちんと書ければ実装の半分は済んだも同然、という関数型言語特有の書きやすさですが。

YSRYSR 2015/10/11 22:40  Togetterまとめからこのページを拝見しておりましたが、コメント欄などが炎上されているのは、お言葉ですが「perlcodesampleさんにこちらの主張が伝わっていないのではないか?」と感じておられる方々が少なからず存在するからではないでしょうか?

 例えばperlcodesampleさんは何度も「テストを100%完璧に実施すればコンパイル時に型エラーを調べる必要はない」といったことをおっしゃられています。確かにそれは嘘ではありませんが、「コンパイル時に型をチェックできれば、テストによって型エラーを調べる必要はない」というのもまた事実です。そして、大規模なソフトウェア開発においては、テストを100%完璧に実施するということがそもそも不可能です。つまりこの時点で、「どちらの意見も正しいのだ」ということをperlcodesampleさんは受け入れるべきです。
 また、もし仮にテストを100%完璧に実施できたとしても、「実行して初めて型エラーが分かったので修正する」より、「コンパイル時に型エラーが分かったので修正する」方がバグを早く潰せるのは明らかです。

 他の例は省略しますが、このような矛盾が生じるのは、perlcodesampleさんが想定するソフトウェアの規模・要件と、他の方が想定するソフトウェアの規模・要件が大きく異なるからだと思われます。確かに小さなコードでしたら100%網羅するテストは不可能ではありませんし、「実行しつつ修正する」ぐらいの姿勢で問題ないと思われます。しかしながら、実力が異なるプログラマが多く集まって大規模なソフトウェアを開発しようとする場合などで、「品質を多少犠牲にしても手早く動的言語で書いてその分テストを増やす」のではなく
「バグをなるべく減らすために、コンパイル時に型エラーを検出できる静的言語で書く」選択をすることに異議を唱える理由はないでしょう。

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証