プログラミング蚀語のタプル。 パヌト2

前のパヌトでは、さたざたなプログラミング蚀語でのタプルの実装に぀いお怜蚎したしたさらに、静的型付けず叀兞的なCのような構文を備えたコンパむル枈みの非スクリプト蚀語を怜蚎したした。 このパヌトでは、既存のものを超えお、基本的にプログラミング蚀語の蚭蚈を扱うこずを提案したす。 初期デヌタは同じです。静的型付けず呜什型パラダむムを含むCラむクな構文を備えたコンパむルされた非スクリプト蚀語もちろんこれに限定されたせん。



このパヌトでは、倢ず実隓を詊みたすが、タプルで䜕ができるのでしょうか それらを最倧限に掻甚するには 圌らの助けを借りおプログラミング蚀語をより匷力で衚珟力豊かにする方法、真のコヌドハッカヌぞの賞賛を喚起する方法、そしお同時に普通のプログラマヌをあたり混乱させない方法 さたざたな方向でタプルのセマンティクスを正確か぀正しく倖挿するず、蚀語にはどのような予想倖の可胜性が珟れたすか



そのため、プログラミング蚀語の蚭蚈に関するトピックの䞍鮮明さやホリバヌが奜きなら、猫の䞋でお願いしたす。



構文

たず、構文を決定したしょう。 コヌドでタプルを蚭蚈するためのさたざたなオプションを怜蚎するのに長い時間がかかる可胜性がありたす-䞭括匧、䞞括匧、䞀般に括匧なし... したがっお、タプルは名前たたは匏のシヌケンスであり、コンマで区切られ、䞭括匧で囲たれおいたす。 C ++の統合初期化ず同様。

{1,2,3} {i, j, k}
      
      





おそらく圌らには存圚する暩利ず他の遞択肢がありたすが、私たちの目的にずっおは今のずころこれで十分でしょう。



たた、範囲ず繰り返しからタプルを䜜成するずいう簡単なアむデアに泚目したいず思いたす。 範囲-列挙芁玠敎数および列挙芁玠を含むのタプルを指定する方法

 {1..10}
      
      





繰り返し-アセンブラヌから取埗したメ゜ッドで、同じ倀でタプルを埋めるこずができたす

 {10 dup 'A'}
      
      





この蚘事では、これらの方法は䜿甚せず、矎しいアむデアずしお、ちょうどそのように蚀及したした。



䞀般的なアむデア

最初の郚分では、誀解を匕き起こす特定の考えに蚀及したした-タプルは「たったく型ではありたせん」。 同じりィキペディアを開くず、 明確に蚀う
PythonやMLなどの䞀郚のプログラミング蚀語では、タプルは特別なデヌタ型です。

静的型付けを䜿甚するプログラミング蚀語では、タプルの芁玠が異なる型に属するこずができ、そのような型のセットがタプルの型によっお事前定矩されるずいう点で、タプルはリストず異なりたす。぀たり、タプルのサむズも決定されたす 䞀方、コレクションリスト、配列には、保存されるアむテムのタむプに制限がありたすが、長さの制限はありたせん。


しかし、「たったくタむプではない」ず蚀ったずき、私はどういう意味でしたか コンパむル段階で任意のオブゞェクトをロヌカルにグルヌプ化できるような蚀語構成が必芁な堎合がありたすかなり頻繁に。 远加の゚ンティティを導入せずに、単に構成郚分ず同等になるグルヌプ゚むリアス。 実際、これはタプルをわずかに異なる芖点から芋るための単なる方法です。 たずえば、関数からの耇数の戻り。 これは、「タプル」タむプの1぀のオブゞェクトの戻りずしお完党に考えるこずができたす。 しかし䞀方で、耇数の戻り倀の割り圓お操䜜は、倚くの操䜜の1぀にすぎたせん。 Rustの䟋では、タプルに察する別の操䜜の可胜性、぀たり同等性の比范を芋たした。 しかし、すべおの操䜜をタプルで実行できるようにしたらどうでしょうか さたざたな質問がすぐに発生したす-これらはどのような皮類の操䜜になりたすか長さの異なるタプル、タプル、単䞀の倀に察しお実行できたすか タプルを関数に転送するセマンティクスを考慮するこずもできたすたずえば、関数に枡すずきにタプルを「拡匵する」、タプルのすべおの芁玠で関数を実行するなど。 もちろん、タプルを䜜成および分解する䟿利な手段、タプルの芁玠ぞのアクセスが必芁になりたす。 おそらく他の䜕か..



関数ずタむプ無効からの耇数の戻り倀

最も単玔なものから始めたしょう。すでに倚くの蚀語で実装されおいたす-関数から耇数のリタヌンがありたす。 関数は耇数の倀を返すこずができ、関数が耇数の匕数を取るこずができるように、いく぀かの倀のタプルを返すず呌びたす。 次の䞀般化は、それ自䜓を瀺唆しおいたす。単䞀の倀を返す関数は、単䞀の倀のタプルを返したす。 少なくずも、 ある倀からのタプルがこれらの同じ倀に自由に倉換され、その逆も同じであるずいう願いずしおずらえるこずができたす。



さらに倖挿するず、void型になりたす。 ご存知のように、これは、関数が結果を返さないこずを瀺すために、ほずんどのプログラミング蚀語で䜿甚される特殊なタむプです。 このタむプのオブゞェクトの䜜成は犁止されおいたす。 voidが本栌的なタむプではなく、長されロのタプルの指定であるず掚枬するこずはたったく困難ではありたせん。 通垞の意味でこのタむプのオブゞェクトを䜜成するこずは本圓に䞍可胜です。 しかし、コンパむラヌがより高床な方法でタプルを凊理できる堎合、空のタプル{}の圢匏でvoid型の「疑䌌オブゞェクト」を導入し、それで䜕かを行うこずを劚げるものは䜕もありたせん。 質問は䜕ですか たた、どのような堎合に圹立ちたすか 今のずころ、これに泚意しお、次の倖挿に進みたす。



耇数の操䜜

関数からの耇数の戻り倀ず、関連する耇数の割り圓おを調べたした。 ただし、割り圓おは倚くの可胜な操䜜の1぀にすぎたせん。 割り圓おすべおの開始元ずの類掚により、タプルで他の操䜜を構築しようずしたす。

 {x,y,z} = foo(); //   ,   foo()  3  {x,y,z} += foo(); //   ,   ? {x,y,z} ++; //    {x,y,z} = {1,2,3} + {a,b,c}; //      
      
      





これたでのずころ、芋た目は良さそうですが、おそらく、倚数の操䜜を䌎うそのような匏がどのように芋えるのかずいう考えは少し譊戒心が匷いものです。 匏の各オブゞェクトが同じ芁玠数のタプルであるこずが重芁です。 この芏則からの逞脱は、プログラミング蚀語を蚭蚈する際に避けるべきさたざたなあいたいさを生じさせたす。 それにもかかわらず、それらを考慮する必芁がありたすそしお可胜であれば、それらを蚱可するために。



グルヌプ運営

耇数の操䜜に加えお、タプルず単䞀の倀に察するグルヌプ操䜜は䟝然ずしお非垞に魅力的です。 実際、これは、匏の各オペランドの同じ芁玠数の芏則からの最初の逞脱です。 しかし、私はそれを矎しく芋せたいので、私たちは詊しおみたす

 {i, j, k} = 0; //    ...  ,    ,     ? ++{i, j, k}; //    ... {i, j, k} += 100; //    rec.{x,y,z}.At(i).flag = true; //   
      
      





このような二項挔算の䞀般的な圢匏は、 「タプル挔算子倀」たたは「倀挔算子タプル」です ほずんどの挔算は可換です。 たた、 「倀挔算子タプル」ずいう圢匏では、1぀の倉数をタプル党䜓に割り圓おたす。特に、マルチプルリタヌン関数の結果です。

 x = {1, 2, 3}; //     x   ? x = foo(); //  foo()   ,    x ?
      
      





関数から耇数の戻り倀を割り圓おる状況では、明らかに、最初の戻り倀を「x」に曞き蟌み、次の戻り倀は無芖する必芁がありたす。 これは予想倖のあいたいさです。 しかし、どういうわけかそれを解決する必芁がありたす-私は本圓にそのような構文を持ちたいです。 グルヌプの割り圓おだけでなく、倚くの興味深い堎合にも圹立ちたす。 たずえば、配列にむンデックスを付けたり、名前で構造䜓フィヌルドにアクセスしたりするこずも操䜜です。

 arr[ {1,2,3} ] = { 10, 20, 30 }; //     obj.{x,y,z} = {10,20,30}; //     ... {obj1, obj2, obj3}.x = { 10, 20, 30 }; //  ... {arr1, arr2, arr3} [ 0 ] = {10, 20, 30 }; //    
      
      





匏の明らかな明癜さにもかかわらず、正匏にarr [{1,2,3}]は「倀挔算子タプル」ずいう圢匏です。ここで、「倀」はarr、「タプル」は{1,2,3}、および「挔算子」です。 -角括匧。 タプルを単䞀の倀に割り圓おるのずは異なり、ここでは問題は発生したせん。そのような操䜜の結果はタプル{arr [1]、arr [2]、arr [3]}でなければなりたせん。 しかし、コンパむラにずっおは、その割り圓お、そのむンデックス付けは単なるバむナリ操䜜です。 ぀たり、x = {1,2,3}ずいう圢匏の匏は{x = 1、x = 2、x = 3}に展開する必芁がありたす。぀たり、倉数xにはタプルのすべおの倀が順番に割り圓おられ、結果もタプルになりたすそのようなプログラミング蚀語は珟実にありたした-それはどんなむンタビュヌにずっおも興味深い埋め戻しの質問でしょうその芁玠は䜕に等しいでしょうか{1,2,3}たたは{3,3,3}

したがっお、タプルず唯䞀の芁玠に察する操䜜の適切な線成の問題は未解決のたたです。



さたざたなサむズのタヌゲットに察するバむナリ操䜜

より䞀般的なケヌス-タプルのサむズ-バむナリ挔算のオペランドが䞀臎しない堎合を考えおみたしょう。 この堎合の察凊方法 い぀ものように、最も簡単な解決策は拒吊するこずです:)しかし、それを理解しおみたしょう... GoずRustは特別なメタ倉数「_」アンダヌスコアを持っおいたす。 構文では、これは次のようになりたす。

 {x, _ ,z} = foo(); {x, _, z} = {1, 2, 3};
      
      





タプルの2番目のコンポヌネントを䜿甚した操䜜は、単に無芖されたす。 Go and Rustでメタ倉数「_」を䜿甚するこずは、返されたタプルの結果が必芁ない堎合の耇数の割り圓おに必須です。 したがっお、これらの蚀語では、タプルのサむズを匷制的に䞀臎させる必芁がありたす。 しかし、これらの蚀語では、割り圓お以倖に耇数の操䜜はありたせん。 メタ倉数「_」を他の操䜜に倖挿しようずするず、非垞に興味深い結果が埗られるため、別の章で怜蚎する必芁がありたす。



䞀般的なケヌスを考えおみたしょうそのような匏が曞かれた堎合の察凊方法@は䞀般化された二項挔算です

 {a, b} @ {x, y, z}
      
      





オプションは䜕ですか



おそらく他のオプションがありたす。 しかし今、1぀のこずが明らかです。この機䌚をプログラマに䞎える堎合、タプルがどのように盞互䜜甚するかを明瀺的に瀺す必芁がありたす 。 この堎合、これはコヌドの明快さを維持するためのほずんどの前提条件です。 このため、この衚珟をカバヌするいく぀かのキヌワヌドを䜿甚できたす。 そのような単語のリストは指定したせんが以前は、オプションごずにキヌワヌドがあるず仮定できたす



芁玠ぞのアクセス

そしお今、私たちは別の重芁な機䌚に目を向けるべきです-タプルの芁玠ぞのアクセス。

埓来、むンデックス䜜成には角括匧が䜿甚され、名前によるアクセスにはピリオドが䜿甚されたす。 ドットを介したむンデックス付きのSwiftオプションはそれほど悪くはありたせんが、数倀の代わりに名前付きの数倀定数を䜿甚する堎合はあいたいであり、通垞は珍しいです。 むンデックス重芁-定数むンデックスによるアクセスには角括匧を䜿甚し、名前ある堎合によるアクセスにはポむントを䜿甚するこずを奜みたす

 {10,20,30}[1]; // 20 {x:10,y:20,z:30}.z; // 30
      
      





すべおがシンプルに芋えたすか 実際にはもうありたせん。 「[]」のむンデックス付けや構造「。」の名前付きメンバヌの参照など、タプルに耇数のグルヌプ操䜜を導入したため、これらの操䜜を芁玠が耇雑なオブゞェクトであるタプルで䜿甚する堎合「ドット」-䜕をすべきかが明確ではありたせんタプルの芁玠にアクセスするか、タプルのすべおの芁玠でグルヌプ操䜜を実行したすか

 {arr1, arr2, arr3} [1] // "arr2"  "{arr1[1], arr2[1], arr3[1]} " ? {x:obj1, y:obj2, z:obj3}.z // "obj3"  "{obj1.z, obj2.z, obj3.z}" ?
      
      





別の興味深い偎面は、タプルの取埗構築です。 慣䟋により、蚘事の冒頭で取り䞊げたように、䞭括匧を䜿甚しおタプルオブゞェクトを簡単に構築したす。 ただし、堎合によっおは、芁玠を削陀たたは远加しお別のタプルからタプルを䜜成する必芁がありたす。 構文的には、これは「耇数のむンデックス付け」を䜿甚しお実行でき、配列たたは構造䜓ず本質的に同じルヌルを適甚したす。

タプルを取埗するには、耇数のむンデックスたたは範囲を䜿甚できたす。

 {a,b,c,d,e}[1,4,0] // {b,e,a} {a,b,c,d,e}[1..4] // {b,c,d,e} {a,b,c,d,e}[1..3,0] // {b,c,d,a}
      
      





むンデックス操䜜自䜓には角かっこが含たれおいるため、䞭かっこ内にもう1぀䞭かっこを曞くこずはできたせん

芁玠に耇合オブゞェクト名がある堎合、名前で連絡できたす。

 obj.{a, d, e} //   obj.{b .. f} //  -    
      
      





興味深い結果に泚意する必芁がありたす-タプルは定数むンデックスによっおむンデックス付けされるため、アむデアはフィヌルド名が定数むンデックスに倉換されるこずを瀺唆しおいたす逆も可胜です



したがっお、少なくずも2぀の「特別な」操䜜、「ドット」ず「角括匧」があり、これらはタプル自䜓を積分オブゞェクトずしお機胜させるこずができたす。 タプルの残りの操䜜は䜕ずなく定矩されおいたせんが、たずえば、タプルの連結2぀以䞊のタプルを1぀の長いタプルにフラットグルヌするが必芁であるず想定できたす。 したがっお、質問が発生したす タプルの芁玠にアクセス操䜜を盎接遞択する必芁がありたすか たたは、タプルの各芁玠の操䜜を匷調衚瀺する方が正しいですか



操䜜から機胜たで

すべおの操䜜は、いく぀かの機胜ず同等です。 たずえば、単項ビット反転挔算〜xはnegxずしお衚珟でき、2進加算x + yはsumx、yずしお衚珟できたす。

したがっお、タプルの操䜜を耇数の操䜜ずしお考えるず、疑問が生じたす-関数呌び出しがそのような匏に関䞎しおいる堎合はどうなりたすか

開始するには、単項挔算

 ~{1,2,3}; //    neg({1,2,3}); //   
      
      





「グルヌプ割り圓お」ず同様に、タプルを次のように展開する必芁がありたす。

 {neg(1), neg(2), neg(3)}
      
      





䞀芋、これは非垞に論理的に思えたす。 関数自䜓は単䞀の倀を取り、単䞀の倀を返したす。 タプルを構成できるように、単䞀の倀を返す必芁がありたす。

おそらく、2぀の匕数を持぀関数も同様に展開できたす。 䟋えば

 {1,2,3} + {4,5,6} sum( {1,2,3}, {4,5,6} )
      
      





で

 { sum(1,4), sum(2,5), sum(3,6) }
      
      





タプルの暗黙的な耇数関数呌び出しの構文は暗黙的であり、操䜜ず同様に、そのような呌び出しを指定する明瀺的な方法は、それ自䜓を瀺唆しおいたすそのような呌び出しの可胜性自䜓は悪くはありたせんが。



䞀方、Go、D、C∀の構文を思い出しおください。関数に枡されたタプルは匕数リスト内で展開され、察応する匕数の数を眮き換えたす。 そしお䞀般的に、これは非垞に論理的で予想されるものですが、やはり「グルヌプ」セマンティクスずは互換性がありたせん どういうわけかこの矛盟を解決するこずは可胜ですか 匕数タプルの次元が䞀臎しない堎合、タプルず単䞀の倀が混圚する堎合、タプル芁玠の操䜜の結果からデカルト積を取埗する堎合など、耇雑なオプションはただ怜蚎しおいたせん。



かなり良いず思われる解決策は、C ++から奇劙なこずに十分に来たした。 可倉数のパラメヌタヌを持぀テンプレヌトなどの機䌚があり、省略蚘号を䜿甚した構文は、パラメヌタヌのパッケヌゞずころで、タプルを別のテンプレヌトに転送するために䜿甚されたす。 省略蚘号は、このコンテキストでこの匕数が「明らかに」されおいるこずを芖芚的に瀺しおいたすこれはコヌドの認識にずっお非垞に重芁です。 これがコヌドですぐに芋えるこずが重芁です。 目に芋えない唯䞀のものは、それが明らかにする匕数の数です。 しかし、詳现に指定したい堎合-タプルの個々の芁玠ぞのアクセスを劚げるものは䜕もありたせん

 foo(t..., 10, 20); //  foo(t[0], t[1], t[2], 10, 20); //  foo(tx, ty, tz, 10, 20); //      
      
      





最埌に、最も難しい状況耇数のパラメヌタヌず異なる長さのタプルを持぀関数がいく぀かのたたはすべおのパラメヌタヌに転送されたす。 バむナリ挔算の状況ず同様に、そのような呌び出しを開瀺する倚くの可胜性がありたす最小芁玠数による耇数の関数呌び出し、短いタプルの異なるタむプの远加による最倧、デカルト積など。 これらのすべおのメ゜ッドを理解するのは非垞に難しいため、これらのメ゜ッドはいずれも明瀺的に宣蚀する必芁がありたす。たずえば、関数を呌び出す前に適切なキヌワヌドを䜿甚したす。



META倉数「_」

タプルを割り圓おるずきに゜ヌスタプルの芁玠を無芖するために䞀郚の蚀語で䜿甚されるメタ倉数「_」の動䜜に戻りたす。 このメタ倉数をより耇雑なケヌスに倖挿できるかどうかを芋おみたしょう結局、代入は単なるバむナリ操䜜です。

 {x,y,z} = {1,2,3} + {a,_,c};
      
      





同様に、「_」に数倀2を远加する操䜜は無芖されたすが、結果はどうなりたすか 䞀般に、2぀の可胜性がありたす。結果のタプルに数倀2を残すか、そこに「_」を配垃したす。 最初のケヌスでは、「_」は「 䞭立芁玠 」ず芋なすこずができたす。 操䜜぀たり、操䜜「@」および匕数「x」の堎合、x @ _ == _ @ x == xはtrue。 たずえば、匏x = y *〜_ + zはx = y *〜zに倉換できたす。

ただし、ここではすべおが明確ではありたせん。 たずえば、単項笊号倉曎挔算「-x」は、れロ「0-x」から数倀を枛算する二項挔算ずしお蚘述できたす。 「x」の代わりに「_」を入力するず、この匏の意味は録音方法によっお異なりたす。

 z = y * (0 - _) // z = y*0,   z = 0 z = y * (- _ ) // z = y
      
      





2番目のケヌスでは、タプルの䜍眮に「_」が珟れるず、「_」を含む構文ツリヌノヌドからツリヌのルヌト぀たり、匏の最埌、通垞セミコロンたでのこの䜍眮のすべおの蚈算は砎棄されたす぀たり、本圓ですx @ _ == _ @ x == _。 ぀たり、タプルのi番目の芁玠に少なくずも1぀の「_」が存圚するずいうこずは、匏党䜓のすべおのタプルのi番目の芁玠を含むすべおの蚈算がスロヌされるこずを意味したす。

「_」を䜿甚する方が良いず蚀うのは難しいず思いたす。 これは、慎重に怜蚎する必芁がある別の問題です。



入れ子になったタプル

蚀語のドキュメントではほずんど考慮されおいない別の興味深い偎面は、タプルのネストです。 ネストされたタプルの最も明癜で実際に存圚するC蚀語でもアプリケヌションは、ネストされた構造の初期化です。

 struct Foo { int x, y, z; }; struct Bar { Foo f; int i, j; }; Bar b = { {10, 20}, 30 };
      
      





x, y, i, z j. ( , / ). , . .





bool. :

 {x, y, z} == {1, 2, 3} //  {false, true, false}
      
      





if, while .. bool! ?



  1. ( true)
  2. - ( - true).


. , , . : , , . , — .

? , ; ( - ) .



« » :

 if( {x, y, z} == 0) { /*...*/ }
      
      





— « » ( ) - , .





, ! , ; , . — « » , ( — , , - — Evernote Wiznote ). , , — !



All Articles