このような発言は理解できませんでした。正直に言うと、関数の戻り値の型を宣言したとしても、コードの多くの行を記述した後はそれを忘れることができ、その関数の検索関数を使用して宣言されている行に戻る必要があります。それをチェックするあなたのテキストエディタ。
それはあなたが戻り値の型を忘れることについてではありません-これは常に起こりそうです。これは、戻り値の型を忘れたことをツールが通知できるようにするためのものです。
さらに、関数はtype funcname()...
で宣言されているので、タイプがわかっている場合は、関数が呼び出された各行を検索する必要があります。なぜならfuncname
、Pythonなどでは、ただ検索するdef funcname
かfunction funcname
、一度だけしか実行できないためです。、宣言時。
これは構文の問題であり、静的型付けとはまったく無関係です。
特別なツールを自由に使用せずに宣言を検索する場合、Cファミリーの構文は実際には使いにくいものです。他の言語にはこの問題はありません。Rustの宣言構文を参照してください。
fn funcname(a: i32) -> i32
さらに、REPLでは、関数の戻り値の型をさまざまな入力でテストするのは簡単ですが、静的に型付けされた言語では、コード行を追加し、宣言された型を知るためにすべてを再コンパイルする必要があります。
どの言語も解釈でき、どの言語もREPLを持つことができます。
では、静的型付け言語の長所ではない関数の戻り値の型を知る以外に、静的型付けは大規模なプロジェクトでどのように役立つのでしょうか。
抽象的に答えます。
プログラムはさまざまな操作で構成され、これらの操作は、開発者が行ういくつかの前提のために、それらがそうであるようにレイアウトされています。
一部の前提は暗黙的であり、一部は明示的です。いくつかの仮定はそれらの近くの操作に関係し、いくつかはそれらから離れた操作に関係しています。仮定は、それが明示的に表現され、真理値が重要である場所に可能な限り近くなると、特定が容易になります。
バグとは、プログラムに存在するが一部のケースには当てはまらない仮定の現れです。バグを追跡するには、誤った仮定を特定する必要があります。バグを削除するには、その仮定をプログラムから削除するか、仮定が実際に満たされるように何かを変更する必要があります。
仮定を2種類に分類したいと思います。
最初の種類は、プログラムの入力に応じて、保持される場合とされない場合がある前提です。この種の誤った仮定を特定するには、プログラムのすべての可能な入力のスペースを検索する必要があります。知識に基づいた推測と合理的な思考を使用して、問題を絞り込み、はるかに小さなスペースで検索できます。しかし、それでも、プログラムが少しでも大きくなると、その初期入力スペースは非常に大きな速度で増加し、あらゆる実用的な目的で無限と見なすことができるようになります。
2番目の種類は、すべての入力に確実に当てはまる、またはすべての入力に間違いなく誤った仮定です。この種の仮定を誤りであると識別した場合、プログラムを実行したり、入力をテストしたりする必要さえありません。この種の仮定が正しいと判断すると、バグ(すべてのバグ)を追跡しているときに気になる疑いが1つ少なくなります。したがって、できるだけ多くの仮定がこの種類に属することに価値があります。
2番目のカテゴリ(入力に関係なく常にtrueまたは常にfalse)に仮定を置くには、仮定が行われる場所で利用できる最小限の情報が必要です。プログラムのソースコード全体で、情報はすぐに古くなります(たとえば、多くのコンパイラーは手続き間分析を行わないため、ほとんどの情報で呼び出しがハード境界になります)。必要な情報を最新に保つ方法が必要です(有効で近くにあります)。
1つの方法は、この情報のソースを、それが消費される場所にできるだけ近づけることですが、ほとんどの場合、それは非現実的です。もう1つの方法は、情報を頻繁に繰り返し、ソースコード全体で関連性を更新することです。
すでにおわかりのように、静的型はまさにそれです-タイプ情報のビーコンがソースコード全体に散在しています。その情報を使用して、型の正しさに関するほとんどの仮定を2番目のカテゴリーに入れることができます。つまり、ほとんどすべての操作は、型の互換性に関して常に正しいか常に正しくないかとして分類できます。
私たちのタイプが正しくない場合、分析により、バグが遅くなるのではなく早期に注目されるようになり、時間を節約できます。タイプが正しい場合、分析により、バグが発生したときにすぐにタイプエラーを除外できるため、時間を節約できます。