「プログラムずタむプ」を予玄する

画像こんにちは、䜏民倚くのプログラミング゚ラヌは、デヌタ型の䞍䞀臎が原因で発生したす。匷力な型システムは、クラス党䜓の゚ラヌを回避し、アプリケヌション党䜓でデヌタの敎合性を保蚌したす。開発者は、日垞の緎習で型をマスタヌするこずを孊ぶこずで、より良いコヌドを䜜成し、トリッキヌなデヌタ゚ラヌを芋぀けるのにかかる時間を節玄できたす。



この本は、タむピングを䜿甚しお、安党でスムヌズに動䜜するだけでなく、保守も簡単な゜フトりェアを䜜成する方法を瀺しおいたす。



TypeScriptで蚘述された問題解決の䟋は、単玔なデヌタ型からファンクタヌやモナドなどのより耇雑な抂念たで、型を操䜜するスキルを䌞ばすのに圹立ちたす。



この本の䞭で



  • 単玔な型、配列、および参照に基づくデヌタ構造の䜜成。
  • オブゞェクト指向プログラミングずタむプ。
  • ゞェネリックスず高次タむプの䜿甚。


この本には、TypeScript、Java、JavaScript、C、C ++などの䞻流のプログラミング蚀語の1぀に関する経隓が必芁です。



この本は誰のためのものですか



この本は、プログラマヌの緎習を目的ずしおいたす。読者は、Java、C、C ++、JavaScript / TypeScriptなどのプログラミング蚀語のいずれかでコヌドを曞くのが埗意である必芁がありたす。コヌド䟋はTypeScriptにありたすが、ほずんどの資料はすべおのプログラミング蚀語に適甚できたす。実際、䟋では必ずしも兞型的なTypeScriptを䜿甚しおいるわけではありたせん。可胜な限り、他のプログラミング蚀語のプログラマヌが理解できるように適応しおいたす。コヌド䟋の組み立おは付録Aで説明されおおり、短いTypeScriptチヌトシヌトは付録Bで説明されおいたす。



仕事のためのオブゞェクト指向コヌド開発に携わっおいる堎合は、代数的デヌタ型ADT、ラムダ匏、ゞェネリック、ファンクタヌ、モナドに぀いお聞いたこずがあるかもしれたせん。 。



この本では、プログラミング蚀語の型システムを䜿甚しお、゚ラヌが発生しにくく、モゞュヌル化された、理解しやすいコヌドを蚭蚈する方法を説明したす。システム党䜓をクラッシュさせる可胜性のあるランタむム゚ラヌをコンパむル゚ラヌに倉換し、問題が発生する前にそれらをキャッチする方法を説明したす。



型システムに関する文献の倧郚分は高床に圢匏化されおいたす。この本は、型システムの実甚的なアプリケヌションに焊点を圓おおいたす。したがっお、数孊はほずんどありたせん。ただし、関数や集合などの基本的な代数の抂念を理解しおいるこずをお勧めしたす。これは、必芁な抂念のいく぀かを明確にするために必芁です。



䞀般化されたアルゎリズムずむンタヌレヌタヌ



この章では



  • map、filter、reduce操䜜の䜿甚は、配列だけではありたせん。
  • 䞀連の䞀般的なアルゎリズムを䜿甚しお、さたざたな問題を解決したす。
  • 目的のコントラクトの汎甚デヌタ型サポヌトを提䟛したす。
  • さたざたなカテゎリのむテレヌタを䜿甚したさたざたなアルゎリズムの実装。
  • 適応アルゎリズムの実装。


この章では、さたざたなデヌタ型ず構造に適した、䞀般的で再利甚可胜なアルゎリズムに完党に焊点を圓おおいたす。



高階関数に぀いお説明したずき、第5章で、map、filter、reduceの各操䜜の1぀のバヌゞョンを確認したした。これらの関数は配列で機胜したすが、前の章で芋たように、むテレヌタヌは任意のデヌタ構造を操䜜するための優れた抜象化です。むテレヌタで動䜜する䞊蚘の3぀のアルゎリズムの汎甚バヌゞョンを実装するこずから始めたす。したがっお、バむナリツリヌ、リスト、配列、およびその他の反埩可胜なデヌタ構造の凊理に適甚できたす。



map、filter、reduceの操䜜は䞀意ではありたせん。最新のプログラミング蚀語で利甚できる他の䞀般的なアルゎリズムずアルゎリズムラむブラリに぀いお説明したす。ほずんどのルヌプをラむブラリアルゎリズムの呌び出しに眮き換える方がよい理由がわかりたす。たた、流動的なAPIずナヌザヌフレンドリヌなアルゎリズムむンタヌフェむスに぀いおも少し説明したす。



次に、パラメヌタヌ型の制玄に぀いお説明したす。ゞェネリックデヌタ構造ずアルゎリズムは、パラメヌタヌタむプに存圚しなければならない機胜を指定できたす。この特殊化により、どこでも䜿甚できるわけではない、普遍性の䜎いデヌタ構造ずアルゎリズムが発生したす。



むテレヌタに぀いお詳しく説明し、むテレヌタのさたざたなカテゎリに぀いお説明したす。むテレヌタがより専門化されおいるほど、その参加により効率的なアルゎリズムが可胜になりたす。ただし、すべおのデヌタ構造が特殊なむテレヌタをサポヌトできるわけではありたせん。



最埌に、適応アルゎリズムに぀いお簡単に説明したす。それらは、より少ない機胜を備えたむテレヌタのためのより甚途が広いが効率の䜎い実装、およびより倚くの機胜を備えたむテレヌタのためのより効率的であるがより甚途の狭い実装を可胜にする。



10.1。map、filter、reduce操䜜の改善



第5章では、map、filter、reduceの各操䜜に぀いお説明し、それぞれの可胜な実装の1぀を確認したした。これらのアルゎリズムは、別の関数を匕数ずしお取り、それを䞀連のデヌタに適甚するため、高階関数です。



map操䜜は、シヌケンス内の各芁玠に関数を適甚し、結果を返したす。 filter操䜜は、各芁玠にフィルタヌ関数を適甚し、この関数がtrueを返す芁玠のみを返したす。 reduce操䜜は、関数を䜿甚しおシヌケンス内のすべおの倀をグルヌプ化し、結果ずしお単䞀の倀を返したす。



第5章の実装では、汎甚パラメヌタヌタむプTを䜿甚し、シヌケンスをTタむプ芁玠の配列ずしお衚したした。



10.1.1。マップ操䜜



map操䜜をどのように実装したかを思い出しおください。TずUの2぀のタむプパラメヌタがありたした。この関数は、匕数ずしおタむプTの倀の配列を取り、2番目の匕数ずしおTからUに倉換する関数を取りたす。リスト10.1に瀺すように、U倀の配列を返したす。



画像


ここで、むテレヌタヌずゞェネレヌタヌの知識があれば、リスト10.2で、配列だけでなく任意のIterable <T>で機胜するようにmapを実装する方法を芋おみたしょう。



画像


元の実装は配列に限定されおいたしたが、これはむテレヌタヌを提䟛する任意のデヌタ構造で機胜したす。さらに、コヌドははるかにコンパクトになりたした。



10.1.2。フィルタ操䜜



filterでも同じこずをしたしょうリスト10.3。元の実装では、入力ずしおタむプTの芁玠の配列ず述語が必芁でした。述語は、あるタむプの1぀の芁玠を受け取り、ブヌル倀を返す関数であるこずを思い出しおください 。指定された関数が枡された倀に察しおtrueを返す堎合、その倀は述語を満たすず蚀われたす。



画像


map操䜜ず同様に、配列の代わりにIterable <T>を䜿甚し、リスト10.4に瀺すように、述語を満たす倀を生成するゞェネレヌタヌずしおこのIterableを実装したす。



画像


繰り返しになりたすが、配列だけでなく機胜する、より簡朔な実装が刀明したした。最埌に、reduce関数を倉曎したす。



10.1.3。削枛操䜜



元のreduce実装では、タむプTの芁玠の配列、タむプTの初期倀配列が空の堎合、およびop操䜜が必芁でした。この操䜜は、タむプTの2぀の倀を匕数ずしお受け取り、タむプTの1぀の倀を返す関数です。reduce操䜜は、操䜜を初期倀に適甚し、配列の最初の芁玠は結果を栌玍し、結果ず配列の次の芁玠などに察する同じ操䜜リスト10.5



画像


リスト10.6に瀺すように、この関数を曞き盎しお、配列の代わりにIterable <T>を䜿甚し、任意のシヌケンスで䜜業するこずができたす。この堎合、ゞェネレヌタヌは必芁ありたせん。前の2぀の関数ずは異なり、reduceは芁玠のシヌケンスを返したせんが、単䞀の倀を返したす。



画像


残りの実装は倉曎されおいたせん。



10.1.4。Filter/ reduceパむプラむン



これらのアルゎリズムを組み合わせお、二分朚から偶数のみを遞択しお合蚈するパむプラむンにする方法を芋おみたしょう。第9章のBinaryTreeNode <T>クラスを䞭心ツリヌトラバヌサルで䜿甚し、偶数フィルタヌず、挔算ずしお加算を䜿甚するreduce関数で連結しおみたしょうリスト10.7。



画像


この䟋は、ゞェネリック型の有効性の生きた蚌拠です。二分朚をトラバヌスしお偶数を合蚈するための新しい関数を実装する代わりに、目的のシナリオ専甚の凊理パむプラむンを圢成するだけです。



10.1.5。挔習



  1. 文字列型の反埩可胜オブゞェクトを凊理するパむプラむンを䜜成したす。空でないすべおの文字列を連結したす。
  2. タむプ番号の反埩可胜オブゞェクトを凊理するパむプラむンを䜜成したす。すべおの奇数を遞択し、それらを2乗したす。


10.2。䞀般的なアルゎリズム



map、filter、reduceアルゎリズムに぀いお説明し、第9章でtakeに぀いおも説明したした。パむプラむンでは他の倚くのアルゎリズムがよく䜿甚されたす。それらのいく぀かをリストしたす。実装に぀いおは説明したせん。Iterable以倖のどの匕数を受け取り、どのようにデヌタを凊理するかに぀いお説明したす。さらに、これらのアルゎリズムが参照できるさたざたな名前をリストしたす。



  • mapは、タむプTの倀のシヌケンスず関数倀T=> Uを入力ずしお受け取り、この関数を入力のすべおの倀に適甚した埌、タむプUの倀のシヌケンスを返したす。シヌケンス。たた、fmap、select;ずいう名前で衚瀺されたす。
  • filter() T (value: T) => boolean, T, , true. where();
  • reduce() T T (x: T, y: T) => T. reduce() T. fold(), collect(), accumulate(), aggregate();
  • any() T (value: T) => boolean. true, ;
  • all() T (value: T) => boolean. true, ;
  • none() T (value: T) => boolean. true, ;
  • take() T n. , n . limit();
  • drop() T n. , , n. skip();
  • zip() T U, , T U, , .


シヌケンスの䞊べ替え、反転、分割、および連結には、他にも倚くのアルゎリズムがありたす。幞い、これらのアルゎリズムは非垞に䟿利で倚くの分野に適甚できるため、自分で実装する必芁はありたせん。ほずんどのプログラミング蚀語には、既成の実装を備えたラむブラリがありたす。JavaScriptにはunderscore.jsずlodashのパッケヌゞがあり、それぞれに倚くの同様のアルゎリズムがありたす。この蚘事の執筆時点では、これらのラむブラリはむテレヌタをサポヌトしおいたせん。組み蟌みのJavaScript配列ずオブゞェクトタむプのみをサポヌトしおいたす。Javaでは、これらはjava.util.streamパッケヌゞにありたす。Cでは、これらはSystem.Linq名前空間にありたす。C ++では、暙準ラむブラリ<algrithm>のヘッダヌファむル。



10.2.1。ルヌプの代わりにアルゎリズム



驚かれるかもしれたせんが、経隓則がありたす。アルゎリズムを䜜成するずきは垞に、タスクのラむブラリアルゎリズムたたはパむプラむンがあるかどうかを確認しおください。ルヌプは通垞、シヌケンスを凊理するために䜜成されたす—たさに䞊蚘のアルゎリズムが行うこずです。



゚ラヌの可胜性が少ないため、カスタムルヌプよりもラむブラリアルゎリズムが優先されたす。ラむブラリアルゎリズムは実蚌枈みで効率的に実装されおおり、操䜜を明瀺的に指定するこずでコヌドを読みやすくするために䜿甚できたす。



この本では、内郚をよりよく理解するためにいく぀かの実装を芋おきたしたが、アルゎリズムを自分で実装する必芁はめったにありたせん。既存のアルゎリズムの胜力を超えたタスクに遭遇した堎合は、1回限りの特殊な実装よりも、汎甚的で再利甚可胜な実装を䜜成するこずをお勧めしたす。



10.2.2。流䜓パむプラむンの実装



ほずんどのラむブラリは、パむプラむンアルゎリズム甚の流動的なAPIを提䟛したす。Fluid APIは、コヌドをはるかに読みやすくするチェヌンAPIです。䟋ずしおセクション10.1.4リスト10.8のフィルタヌ/畳み蟌みパむプラむンを䜿甚しお、流䜓APIず非流䜓APIの違いを芋おみたしょう。



画像


そしお、最初にfilter操䜜を適甚し、次に結果をreduce操䜜に枡したすが、コヌドを巊から右に読み取るず、filterの前にreduceが衚瀺されたす。たた、どの匕数がパむプラむン内の特定の関数を参照しおいるかを把握するこずも非垞に困難です。流動的なAPIにより、コヌドがはるかに読みやすくなりたす。



珟圚、すべおのアルゎリズムは最初の匕数ずしお反埩可胜オブゞェクトを取り、反埩子を返したす。オブゞェクト指向プログラミングはAPIを改善したす。すべおのアルゎリズムを反埩可胜なラッパヌクラスに収集するこずができたす。そしお、最初の匕数ずしお明瀺的に指定せずに、任意のiterableを呌び出したす。これは、iterableがクラスのメンバヌであるためです。リスト10.9に瀺すように、map、filter、reduceに察しおこれを行い、Iterableオブゞェクトをラップする新しいFluentIterable <T>クラスにグルヌプ化したす。



画像


Iterable <T>に基づいお、FluentIterable <T>を䜜成できるため、フィルタヌを曞き盎したり、パむプラむンを枛らしお流動性を高めたりするこずができたす。リスト10.10に瀺すように、FluentIterable <T>オブゞェクトを䜜成し、そのオブゞェクトでfilterを呌び出し、その結果に基づいお新しいFluentIterable <T>オブゞェクトを䜜成し、reduceを呌び出したす。



画像


これで、filterがreduceの前に来るようになり、匕数がこの関数を参照しおいるこずは明らかです。唯䞀の問題は、各関数呌び出しの埌に新しいFluentIterable <T>を䜜成する必芁があるこずです。このAPIを改善するには、map関数ずfilter関数を曞き盎しお、IterableIterator <T>ではなくFluentIterable <T>を返したす。 reduceは反埩可胜ではなくタむプTの単䞀の倀を返すため、reduceメ゜ッドを倉曎する必芁がないこずに泚意しおください。



ただし、ゞェネレヌタヌを䜿甚しおいるため、リタヌンタむプを単玔に倉曎するこずはできたせん。ゞェネレヌタヌの存圚理由は、関数に䟿利な構文を提䟛するこずですが、垞にIterableIterator <T>を返したす。代わりに、リスト10.11に瀺すように、実装を2぀のプラむベヌトメ゜ッドmapImplずfilterImplに移動し、パブリックmapメ゜ッドずfilterメ゜ッドでIterableIterator <T>からFluentIterable <T>に倉換できたす。



画像


画像


リスト10.12に瀺すように、すべおのアルゎリズムがメ゜ッドずしお蚘述されおいるFluentIterableを返すようになったため、この改善された実装により、アルゎリズムのチェヌンが容易になりたす。



画像


珟圚、この真に流動的なバヌゞョンでは、コヌドは巊から右に読みやすく、パむプラむンを構成する任意の数のアルゎリズムを連結するための構文は非垞に自然に芋えたす。同様のアプロヌチがほずんどのアルゎリズムラむブラリで䜿甚されおおり、耇数のアルゎリズムを可胜な限り簡単に連鎖させるこずができたす。



プログラミング蚀語によっおは、Fluent APIの欠点の1぀は、FluentIterableクラスがすべおのアルゎリズムのメ゜ッドで乱雑になり、拡匵が困難になるこずです。ラむブラリに含たれおいる堎合、呌び出し元のコヌドには、クラスを倉曎せずに新しいアルゎリズムを远加する方法がありたせん。Cには、コヌドを倉曎せずにクラスたたはむンタヌフェむスにメ゜ッドを远加できる、いわゆる拡匵メ゜ッドがありたす。ただし、すべおの蚀語にそのような機胜があるわけではありたせん。それでも、ほずんどの堎合、新しいアルゎリズムを最初から実装するよりも、既存のアルゎリズムのラむブラリを䜿甚する方が適切です。



10.2.3。挔習



  1. FluentIterableクラスを拡匵しお、むテレヌタヌから最初のn個の芁玠を返すtakeアルゎリズムを含めたす。
  2. FluentIterableクラスを拡匵しお、むテレヌタヌから最初のn個の芁玠をスキップし、残りをすべお返すdropアルゎリズムを含めたす。


10.3。パラメヌタタむプの制限



ゞェネリックデヌタ構造が特定のタむプパラメヌタヌTに䟝存しないデヌタの圢匏をどのように定矩するかに぀いおはすでに芋おきたした。たた、どのタむプに関係なく、むテレヌタヌを䜿甚しおタむプTの倀のシヌケンスを凊理する䞀連のアルゎリズムに぀いおも調べたした。です。ここで、リスト10.13で、特定のデヌタ型が重芁であるシナリオを考えおみたしょう。Iterable<T>を匕数ずしお取り、むテレヌタヌによっお返される各芁玠でrenderを呌び出すゞェネリック関数renderAllです。



画像


この関数をコンパむルしようずするず、次の゚ラヌメッセヌゞが衚瀺されたす。プロパティ 'render'はタむプ 'T'に存圚したせんタむプ 'T'には 'render'プロパティがありたせん。



ゞェネリック型Tのrenderメ゜ッドを呌び出そうずしおいたすが、そのようなメ゜ッドがない可胜性がありたす。このようなシナリオでは、タむプTをrenderメ゜ッドを含む特定のむンカネヌションのみに制限する必芁がありたす 。



パラメヌタタむプの制限



制玄は、匕数タむプが持぀必芁のある機胜に぀いおコンパむラヌに通知したす。制限なしで、匕数の型は䜕でもかたいたせん。ゞェネリックデヌタ型に特定のクラスメンバヌが必芁な堎合は、制玄を利甚しお、蚱可される型のセットをこれらの必須メンバヌを持぀ものに枛らしたす。



この䟋では、リスト10.14に瀺すように、renderメ゜ッドを宣蚀するIRenderableむンタヌフェヌスを定矩できたす。次に、extendsキヌワヌドを䜿甚しお、Tの型に制玄を远加し、IRenderableを具䜓化する匕数型のみが蚱可されるこずをコンパむラヌに通知できたす。



画像


10.3.1。制限された䞀般的なデヌタ構造



ほずんどの䞀般的なデヌタ構造は、パラメヌタヌタむプの制玄を必芁ずしたせん。リンクリスト、ツリヌ、および配列には、任意のタむプの倀を栌玍できたす。ただし、いく぀かの䟋倖、特にハッシュセットがありたす。



セットのデヌタ構造は数孊的な意味でセットをモデル化するため、䞀意の倀がセットに保存され、重耇は砎棄されたす。セットデヌタ構造には通垞、他のセットを結合、亀差、および枛算するためのメ゜ッドが含たれ、特定の倀がセットに含たれおいるかどうかを確認するこずもできたす。このチェックを実行するには、この倀をセットの各芁玠ず比范できたすが、これはあたり効率的な方法ではありたせん。最悪の堎合、セットの各芁玠ず比范するには、セット党䜓をトラバヌスする必芁がありたす。このようなトラバヌサルは、線圢時間Onで実行されたす。以䞋のサむドバヌ「BigONotation」で、これらの衚蚘法をブラッシュアップできたす。



最も効率的な実装は、すべおの倀をハッシュし、ハッシュマップや蟞曞などのキヌ倀デヌタ構造に栌玍するこずです。これらのような構造はより効率的であり、䞀定時間で倀を取埗できたす 、O1。ハッシュセットはハッシュマップをラップし、芁玠が含たれおいるかどうかを効率的にチェックしたす。ただし、制限がありたす。タむプTは、タむプTの倀を取り、タむプ番号のハッシュ倀を返すハッシュ関数を提䟛する必芁がありたす。



䞀郚のプログラミング蚀語では、より高いタむプでハッシュメ゜ッドを蚘述するこずにより、すべおの倀のハッシュが可胜です。たずえば、䞊䜍のJavaオブゞェクトタむプにはhashCodeメ゜ッドが含たれ、䞊䜍のCオブゞェクトタむプにはGetHashCodeメ゜ッドが含たれたす。しかし、蚀語がそのような可胜性を提䟛しない堎合は、ハッシュ可胜な型のみをデヌタ構造に栌玍できるように、型制玄が必芁です。たずえば、IHashableむンタヌフェむスを定矩し、それを汎甚ハッシュマップたたはディクショナリのキヌタむプの型制玄ずしお䜿甚できたす。



著者に぀いお



Vlad Rishkutsiaは、Microsoftの゜フトりェア開発スペシャリストであり、10幎以䞊の経隓がありたす。この間、圌はいく぀かの䞻芁な゜フトりェアプロゞェクトを管理し、倚くの若い専門家を蚓緎したした。



この本に぀いおの詳现は、䞊で芋぀けるこずができる 出版瀟のりェブサむト

» 目次

» 抜粋



に぀いおは居䜏者クヌポンで25割匕- 掻字



本の玙のバヌゞョンの支払いの際、電子曞籍は、E-によっお送信されたす郵䟿物。



All Articles