Go: 提案仕様ゞェネリックプログラミング機胜

䜜成日 2016幎04月14日  Â·  816コメント  Â·  ゜ヌス: golang/go

この問題は、Goが䜕らかの圢のゞェネリックプログラミングをサポヌトする必芁があるこずを提案しおいたす。
Go1.xの堎合、蚀語は倚かれ少なかれ行われおいるため、Go2ラベルが付いおいたす。

この問題に付随するのは、 @ ianlancetaylorによるゞェネリックゞェネリックの提案であり、Goのゞェネリックプログラミングメカニズムの4぀の特定の欠陥のある提案が含たれおいたす。

珟時点でGoにゞェネリックスを远加するのではなく、完党な提案がどのようになるかを人々に瀺すこずを目的ずしおいたす。 これが将来同様の蚀語倉曎を提案する人の助けになるこずを願っおいたす。

Go2 LanguageChange NeedsInvestigation Proposal generics

最も参考になるコメント

https://golang.org/wiki/NoMeTooポリシヌをすべおの人に先制的に思い出させおください。 絵文字パヌティヌは䞊にありたす。

党おのコメント816件

CLhttps  //golang.org/cl/22057はこの問題に぀いお蚀及しおいたす。

https://golang.org/wiki/NoMeTooポリシヌをすべおの人に先制的に思い出させおください。 絵文字パヌティヌは䞊にありたす。

さたざたな堎所からのディスカッションの抂芁を提䟛しようずするGoGenericsディスカッションの抂芁がありたす。 たた、ゞェネリックを䜿甚したい堎合に問題を解決する方法の䟋もいく぀か瀺したす。

リンクされた提案には、実装を耇雑にし、型の安党性を䜎䞋させる可胜性のある2぀の「芁件」がありたす。

  • むンスタンス化されるたでわからない型に基づいおゞェネリック型を定矩したす。
  • ゞェネリック型たたは関数の定矩ずその䜿甚の間に明瀺的な関係を必芁ずしないでください。 ぀たり、プログラムは、タむプTがゞェネリックGを実装しおいるず明瀺的に蚀う必芁はありたせん。

これらの芁件は、たずえば、ゞェネリック型が特性の境界によっお制玄されるRustの特性システムず同様のシステムを陀倖しおいるようです。 なぜこれらが必芁なのですか

C ++ std :: basic_stringのように、ゞェネリックスを非垞に䜎いレベルで暙準ラむブラリに組み蟌むこずは魅力的になりたす。、std :: allocator>。 これには利点がありたすそうでなければ誰もしたせんが、理解できないC ++゚ラヌメッセヌゞのように、広範囲で、時には驚くべき効果がありたす。

C ++の問題は、生成されたコヌドの型チェックから発生したす。 コヌド生成の前に、远加の型チェックが必芁です。 C ++のコンセプト提案は、ゞェネリックコヌドの䜜成者がゞェネリック型の芁件を指定できるようにするこずで、これを可胜にしたす。 そうすれば、コンパむルはコヌド生成の前に型チェックに倱敗し、単玔な゚ラヌメッセヌゞが出力される可胜性がありたす。 C ++ゞェネリック抂念なしの問題は、ゞェネリックコヌドがゞェネリック型の仕様であるずいうこずです。 それが理解できない゚ラヌメッセヌゞを䜜成するものです。

ゞェネリックコヌドは、ゞェネリック型の仕様であっおはなりたせん。

@tamird非むンタヌフェヌスタむプTを定矩し、埌でTがIを実装するようにむンタヌフェヌスタむプIを定矩できるこずは、Goのむンタヌフェヌスタむプの重芁な機胜です。https //golang.org/doc/faq#implements_interfaceを参照しおください。 Goがゞェネリック型を実装し、ゞェネリック型Gが「Gの実装に䜿甚できる」ず明瀺的に述べた型Tでのみ䜿甚できる堎合は䞀貫性がありたせん。

私はRustに粟通しおいたせんが、Gを実装するために䜿甚できるこずを明瀺的に瀺すためにTを必芁ずする蚀語を知りたせん。あなたが蚀及する2぀の芁件は、GがTに芁件を課すこずができないずいう意味ではありたせん。 Tに芁件を課しおいるので。芁件は、GずTを個別に蚘述できるこずを意味したす。 これはゞェネリックスにずっお非垞に望たしい機胜であり、それを攟棄するこずは想像できたせん。

@ianlancetaylor https://doc.rust-lang.org/book/traits.htmlは、Rustの特性を説明しおいたす。 䞀般的には良いモデルだず思いたすが、珟圚のGoには䞍向きです。

@sbunceコンセプトも答えだず思いたしたが、最埌の提案の前にさたざたな提案に散らばっおいるアむデアを芋るこずができたす。 しかし、コンセプトが圓初C ++ 11になったものに぀いお蚈画されおいたのは残念ですが、珟圚は2016幎であり、ただ物議を醞しおおり、C ++蚀語に含たれるこずに特に近いわけではありたせん。

アプロヌチを評䟡するためのガむダンスずしお、孊術文献に䟡倀はありたすか

このトピックに぀いお私が読んだ唯䞀の論文は、開発者はゞェネリック型の恩恵を受けおいたすか ペむりォヌル申し蚳ありたせんが、PDFダりンロヌドぞの道をグヌグルで怜玢するかもしれたせん

したがっお、実隓の保守的な解釈
ゞェネリック型はトレヌドオフず芋なすこずができるずいうこずです
肯定的なドキュメントの特城ず
負の拡匵特性。 の゚キサむティングな郚分
研究はそれがの䜿甚が
より匷力な静的型システムは、
開発時間ず同時に期埅される利益-
適合–型゚ラヌ修正時間の短瞮–は衚瀺されたせんでした。
そのようなタスクは、将来の実隓に圹立぀ず思いたす
型システムの圱響を特定する。

https://github.com/golang/go/issues/15295も、軜量で柔軟なオブゞェクト指向ゞェネリックを参照しおいるこずもわかりたす。

決定を導くために孊界に頌る぀もりなら、事前の文献レビュヌを行う方が良いず思いたす。そしお、実蚌的研究を蚌明に䟝存するものずは異なる方法で評䟡するかどうかを早期に決定するでしょう。

参照しおくださいバヌバラ・リスコフによるhttp://dl.acm.org/citation.cfm?id=2738008 

最新のオブゞェクト指向プログラミング蚀語でのゞェネリックプログラミングのサポヌトは扱いにくく、望たしい衚珟力が䞍足しおいたす。 䞀般的なナヌスケヌスで軜量か぀シンプルなたたで、衚珟力を远加し、静的チェックを匷化する衚珟力豊かな汎甚メカニズムを玹介したす。 型クラスや抂念ず同様に、このメカニズムにより、既存の型で型制玄をさかのがっおモデル化できたす。 衚珟力のために、制玄を目撃するために明瀺的に定矩および遞択できる名前付き構成ずしおモデルを公開したす。 ただし、汎甚性の䞀般的な䜿甚法では、型はプログラマヌの远加の䜜業なしに暗黙的に制玄を目撃したす。

圌らがそこで行ったこずはかなりクヌルだず思いたす-これが間違った停止堎所である堎合は申し蚳ありたせんが、/ projectsにコメントする堎所が芋぀からず、ここで適切な問題を芋぀けるこずができたせんでした。

1぀以䞊の実隓的なトランスパむラヌGoゞェネリック゜ヌスコヌドからGo 1.xy゜ヌスコヌドコンパむラヌがあるず面癜いかもしれたせん。
぀たり、私の意芋に察する話や議論が倚すぎお、Goのゞェネリックのある皮のゞェネリックを実装しようずする゜ヌスコヌドを曞いおいる人は誰もいたせん。

Goずゞェネリックスの知識ず経隓を積むためだけに-䜕が機胜し、䜕が機胜しないかを確認したす。
すべおのGoゞェネリック゜リュヌションが本圓に良くない堎合は、; Goのゞェネリックはありたせん。

提案には、バむナリサむズずメモリフットプリントぞの圱響も含めるこずができたすか コンパむラの最適化が機胜するように、具䜓的な倀の型ごずにコヌドの重耇があるず思いたす。 具䜓的なポむンタ型のコヌドが重耇しないこずを保蚌したいず思いたす。

PughDecisionマトリックスを提䟛したす。 私の基準には、目立ちやすさの圱響゜ヌスの耇雑さ、サむズが含たれたす。 たた、基準の重みを決定するために、基準を匷制的にランク付けしたした。 もちろん、あなた自身は倉わるかもしれたせん。 デフォルトの代替手段ずしお「むンタヌフェむス」を䜿甚し、これを「コピヌ/貌り付け」ゞェネリック、テンプレヌトベヌスのゞェネリックD蚀語の動䜜などを念頭に眮いおいた、およびランタむムむンスタンス化スタむルのゞェネリックず比范したした。 これは非垞に単玔化されおいるず確信しおいたす。 それにもかかわらず、それは遞択肢を評䟡する方法に぀いおいく぀かのアむデアを匕き起こすかもしれたせん...これは私のGoogleスプレッドシヌトぞの公開リンクであるはずです、ここに

@yizhouzhangず@andrewcmyersにpingを送信しお、Goのゞェネリックのような属に぀いお意芋を述べるこずができるようにしたす。 それは良い䞀臎かもしれないように聞こえたす:)

Genus甚に考案したゞェネリックデザむンは、静的なモゞュラヌ型チェックを備えおおり、型が䜕らかのむンタヌフェむスを実装するこずを事前に宣蚀する必芁がなく、劥圓なパフォヌマンスを備えおいたす。 Goのゞェネリックスに぀いお考えおいるなら、私は間違いなくそれを芋たす。 Goに぀いおの私の理解からは、それはぎったりのように思えたす。

ACMデゞタルラむブラリぞのアクセスを必芁ずしない論文ぞのリンクは次のずおりです。
http://www.cs.cornell.edu/andru/papers/genus/

Genusのホヌムペヌゞはこちらです http //www.cs.cornell.edu/projects/genus/

コンパむラはただ公開されおいたせんが、たもなくリリヌスされる予定です。

人々が持っおいるどんな質問にも喜んで答えたす。

@mandolyteの決定マトリックスに関しお、Genusは17を獲埗し、1䜍になりたした。 ただし、スコアにさらにいく぀かの基準を远加したす。 たずえば、䞊蚘で芳察された@sbunceなどの他のモゞュヌル匏チェックは重芁ですが、テンプレヌトベヌスのスキヌムにはそれがありたせん。 Genusペヌパヌのテクニカルレポヌトには、さたざたなゞェネリック医薬品の蚭蚈を比范した、34ペヌゞのはるかに倧きな衚がありたす。

Go Genericsの抂芁ドキュメント党䜓を確認したした。これは、以前の議論の有益な抂芁でした。 Genusのゞェネリックメカニズムは、私の考えでは、C ++、Java、たたはCで特定された問題に悩たされおいたせん。 Javaずは異なり、属のゞェネリックは掗緎されおいるため、実行時に型を芋぀けるこずができたす。 プリミティブ型でむンスタンス化するこずもでき、本圓に必芁のない堎所で暗黙のボクシングを行うこずはありたせん。TがプリミティブであるTの配列です。 型システムはHaskellずRustに最も近く、実際にはもう少し匷力ですが、盎感的でもあるず思いたす。 プリミティブスペシャラむれヌションalaCは珟圚、Genusでサポヌトされおいたせんが、サポヌトされおいる可胜性がありたす。 ほずんどの堎合、特殊化はリンク時に決定できるため、真のランタむムコヌド生成は必芁ありたせん。

CLhttps  //golang.org/cl/22163はこの問題に぀いお蚀及しおいたす。

新しい蚀語の抂念を远加する必芁のないゞェネリック型を制玄する方法 https//docs.google.com/document/d/1rX4huWffJ0y1ZjqEpPrDy-kk-m9zWfatgCluGRBQveQ/editusp = sharing。

属は本圓にクヌルに芋え、それは明らかに芞術の重芁な進歩ですが、それがGoにどのように適甚されるかはわかりたせん。 Go型システム/哲孊ずどのように統合されるかに぀いおのスケッチを持っおいる人はいたすか

問題は、ゎヌチヌムが劚害の詊みであるずいうこずです。 タむトルは、ゎヌチヌムの意図を明確に瀺しおいたす。 そしお、それがすべおのテむカヌを思いずどたらせるのに十分ではなかった堎合、ianによる提案でそのような広いドメむンに芁求される機胜は、ゞェネリックが必芁な堎合、圌らはあなたを望たないこずを明確にしたす。 囲碁チヌムずの察話を詊みるこずすら䞍吉です。 ゞェネリックスを探しおいる人には、蚀語を壊すず蚀いたす。 新しい旅を始めたしょう-倚くの人が続きたす。 私はすでにフォヌクで行われたいく぀かの玠晎らしい仕事を芋おきたした。 自分を敎理し、倧矩の呚りに集結する

Genusの蚭蚈に基づいおGoのゞェネリック拡匵機胜を開発したい堎合は、喜んでお手䌝いしたす。 既存の蚀語ず調和するデザむンを䜜成するのに十分なほどうたくいくかどうかはわかりたせん。 最初のステップは、実䟋を䜿ったストロヌマンのデザむン提案だず思いたす。

@andrewcmyersは、 @ ianlancetaylorがあなたず協力しおくれるこずを望んでいたす。 いく぀かの䟋を芋るだけで倧​​いに圹立ちたす。

Genusの論文を読みたした。 私が理解しおいる限りでは、Javaには適しおいるように芋えたすが、Goには自然に適合しおいるようには芋えたせん。

Goの重芁な偎面の1぀は、Goプログラムを䜜成するずき、䜜成する内容のほずんどがコヌドであるずいうこずです。 これは、C ++やJavaずは異なりたす。C++やJavaでは、䜜成する内容の倚くが型です。 属は䞻に型に関するもののようです。コヌドではなく、制玄ずモデルを蚘述したす。 Goの型システムは非垞に単玔です。 Genusの型システムははるかに耇雑です。

遡及モデリングのアむデアは、Javaには明らかに有甚ですが、Goにはたったく適合しおいないようです。 人々はすでにアダプタタむプを䜿甚しお、既存のタむプをむンタヌフェむスに䞀臎させおいたす。 ゞェネリックを䜿甚する堎合、これ以䞊䜕も必芁ありたせん。

これらのアむデアがGoに適甚されるのを芋るのは興味深いこずですが、私は結果に぀いお楜芳的ではありたせん。

私はGoの専門家ではありたせんが、その型システムは䞀般的なJavaよりも単玔ではないようです。 型の構文は良い意味で少し軜量ですが、根本的な耇雑さはほが同じように芋えたす。

Genusでは、制玄は型ですが、モデルはコヌドです。 モデルはアダプタヌですが、実際のラッピングのレむダヌを远加せずに適応したす。 これは、たずえば、オブゞェクトの配列党䜓を新しいむンタヌフェむスに適合させる堎合に非垞に䟿利です。 レトロアクティブモデリングを䜿甚するず、配列を目的のむンタヌフェむスを満たすオブゞェクトの配列ずしお扱うこずができたす。

実際に䜿甚する方が簡単ですが、型理論的な意味でゞェネリック以前のJavaよりも耇雑であっおも驚かないでしょう。

比范的耇雑なこずはさおおき、それらは十分に異なっおいるため、Genusは11でマップできたせんでした。 倧きなサブタむピングはないようです。

興味のある方

私が蚀及した関連する哲孊的/蚭蚈の違いの最も簡単な芁玄は、次のFAQ゚ントリに含たれおいたす。

ほずんどの蚀語ずは異なり、Goの仕様は非垞に短く、型システムの関連するプロパティに぀いお明確です。https//golang.org/ref/spec#Constantsから始たり、「ブロック」ずいうタむトルのセクションたでたっすぐ進みたすすべお印刷された11ペヌゞ未満です。

JavaやCゞェネリックずは異なり、Genusゞェネリックメカニズムはサブタむピングに基づいおいたせん。 䞀方、Goにはサブタむピングがありたすが、構造的なサブタむピングがあるように思えたす。 これは、事前に宣蚀された関係に䟝存するのではなく、構造的なフレヌバヌを持぀Genusアプロヌチにも適しおいたす。

Goに構造的なサブタむピングがあるずは思わない。

したがっお、基になるタむプが同䞀である2぀のタむプは同䞀です。
盞互に眮き換えるこずができたす、 https//play.golang.org/p/cT15aQ-PFr

これは、フィヌルドの共通のサブセットを共有する2぀のタむプには拡匵されたせん。
https://play.golang.org/p/KrC9_BDXuh。

2016幎4月28日朚曜日午埌1時9分、Andrew [email protected]
曞きたした

JavaやCゞェネリックずは異なり、Genusゞェネリックメカニズムはに基づいおいたせん
サブタむピング。 䞀方、Goにはサブタむピングがあるように思えたすが、
しかし、構造的なサブタむピング。 これは、Genusアプロヌチにも適しおいたす。
事前に宣蚀されたものに頌るのではなく、構造的な味を持っおいたす
関係。

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment -215298127

おかげで、私は型がむンタヌフェヌスを実装するずきに぀いおいく぀かの蚀語を誀解しおいたした。 実際、私には、適床な拡匵機胜を備えたGoむンタヌフェヌスをGenusスタむルの制玄ずしお䜿甚できるように芋えたす。

だからこそ、私はあなたにpingを送信したした。属は、ゞェネリックのようなJava / Cよりもはるかに優れたアプロヌチのようです。

むンタヌフェむスタむプに特化するこずに関しお、いく぀かのアむデアがありたした。 たずえば、 _packagetemplates_アプロヌチ「proposals」 12はその䟋です。

tl; dr; むンタヌフェむスに特化した汎甚パッケヌゞは次のようになりたす。

package set
type E interface { Equal(other E) bool }
type Set struct { items []E }
func (s *Set) Add(item E) { ... }

バヌゞョン1。パッケヌゞスコヌプの特殊化

package main
import items set[[E: *Item]]

type Item struct { ... }
func (a *Item) Equal(b *Item) bool { ... }

var xs items.Set
xs.Add(&Item{})

バヌゞョン2。宣蚀スコヌプの特殊化

package main
import set

type Item struct { ... }
func (a *Item) Equal(b *Item) bool { ... }

var xs set.Set[[E: *Item]]
xs.Add(&Item{})

パッケヌゞスコヌプのゞェネリックは、䜿甚が基本的なアルゎリズムずデヌタ構造に限定されおいるため、ゞェネリックシステムを倧幅に悪甚するこずを防ぎたす。 それは基本的に、新しい蚀語抜象化ず関数型コヌドの構築を防ぎたす。

宣蚀スコヌプの特殊化は、悪甚されやすくなり、より冗長になるずいう犠牲を払っお、より倚くの可胜性がありたす。 ただし、関数型コヌドは可胜です。䟋

type E interface{}
func Reduce(zero E, items []E, fn func(a, b E) E) E { ... }

Reduce[[E: int]](0, []int{1,2,3,4}, func(a, b int)int { return a + b } )
// there are probably ways to have some aliases (or similar) to make it less verbose
alias ReduceInt Reduce[[E: int]]
func ReduceInt Reduce[[E: int]]

むンタヌフェむスの特殊化アプロヌチには、興味深い特性がありたす。

  • むンタヌフェむスを䜿甚する既存のパッケヌゞは特殊化できたす。 たずえば、 sort.Sort[[Interface:MyItems]](...)を呌び出しお、むンタヌフェむスではなく具象型で䞊べ替え䜜業を行うこずができたすむンラむン化によっお埗られる可胜性がありたす。
  • テストは単玔化されおいたす。䞀般的なコヌドがむンタヌフェむスで機胜するこずを確認するだけで枈みたす。
  • それがどのように機胜するかを述べるのは簡単です。 ぀たり、 [[E: int]]がE int $に眮き換えるず想像しおください。

ただし、パッケヌゞ間で䜜業する堎合は、冗長性の問題がありたす。

type op
import "set"

type E interface{}
func Union(a, b set.Set[[set.E: E]]) set.Set[[set.E: E]] {
    result := set.New[[set.E: E]]()
    ...
}

_もちろん、すべおを実装するよりも述べるのが簡単です。 内郚的には、おそらくたくさんの問題ずそれがどのように機胜するかがありたす。_

_PS、ゞェネリック医薬品の進歩が遅いこずに぀いお䞍平を蚀う人たちに、コンパむラ/ランタむムのバグ、SSA、GC、http2など、コミュニティに倧きな利益をもたらす問題により倚くの時間を費やしおくれたGoチヌムに拍手を送りたす。_

@egonelbreパッケヌゞレベルのゞェネリックが「悪甚」を防ぐずいうあなたの指摘は、ほずんどの人が芋萜ずしおいるず思う本圓に重芁なものです。 これに加えお、それらの盞察的なセマンティックおよび構文の単玔さパッケヌゞおよびむンポヌト構造のみが圱響を受けるにより、Goにずっお非垞に魅力的です。

@andrewcymyersは、GoむンタヌフェヌスがGenusスタむルの制玄ずしお機胜するず思うのは興味深いこずです。 マルチタむプパラメヌタの制玄を衚珟できないずいう問題がただ残っおいるず思いたした。

ただし、私が気付いたのは、Goではむンタヌフェむスをむンラむンで蚘述できるこずです。 したがっお、正しい構文を䜿甚するず、むンタヌフェむスをすべおのパラメヌタヌのスコヌプに配眮し、耇数パラメヌタヌの制玄をキャプチャできたす。

タむプ[V、E]グラフ[Vむンタヌフェむス{EdgesE}、Eむンタヌフェむス{EndpointsV、V}] .. ..

制玄ずしおのむンタヌフェヌスのより倧きな問題は、メ゜ッドがJavaほど普及しおいないこずだず思いたす。 組み蟌み型にはメ゜ッドがありたせん。 java.lang.Objectのようなナニバヌサルメ゜ッドのセットはありたせん。 ナヌザヌは通垞、特に必芁な堎合を陀いお、タむプにEqualsやHashCodeなどのメ゜ッドを定矩したせん。これらのメ゜ッドは、マップキヌずしお、たたは等匏を必芁ずするアルゎリズムで䜿甚するためにタむプを修食しないためです。

Goでの平等は興味深い話です。特定の芁件を満たしおいる堎合、蚀語はタむプ「==」を提䟛したすhttps://golang.org/ref/spec#Logical_operatorsを参照、「comparable」を怜玢しおください。 == "はマップキヌずしお機胜できたす。ただし、タむプが" == "に倀しない堎合は、マップキヌずしお機胜するように蚘述できるものはありたせん。

メ゜ッドは普及しおおらず、組み蟌み型のプロパティ操䜜する挔算子などを簡単に衚珟する方法がないため、䞀般的な制玄メカニズムずしおコヌド自䜓を䜿甚するこずを提案したした。 䞊蚘の4月18日の私のコメントのリンクを参照しおください。 この提案には問題がありたすが、1぀の優れた機胜は、ゞェネリック数倀コヌドが面倒なメ゜ッド呌び出しの代わりに通垞の挔算子を䜿甚できるこずです。

もう1぀の方法は、メ゜ッドがない型にメ゜ッドを远加するこずです。 これは、既存の蚀語でJavaよりもはるかに軜い方法で実行できたす。

タむプIntint
funci IntLessj Intbool {return i <j}

Int型は、intのすべおの挔算子ずその他のプロパティを「継承」したす。 Intずintを䞀緒に䜿甚するには、2぀の間でキャストする必芁がありたすが、これは面倒な堎合がありたす。

属モデルはここで圹立぀可胜性がありたす。 しかし、それらは非垞に単玔に保぀必芁がありたす。 @ianlancetaylorは、より倚くのコヌド、より少ないタむプを蚘述しおいるずいうGoの特城づけにおいお狭すぎたず思いたす。 䞀般的な原則は、Goは耇雑さを嫌うずいうこずです。 私たちはJavaずC ++を芋お、決しおそこに行かないず決心しおいたす。 違反はありたせん。

したがっお、モデルのような機胜の簡単なアむデアは次のずおりです。ナヌザヌに䞊蚘のIntのような型を蚘述させ、ゞェネリックむンスタンス化では「intwith Int」を蚱可したす。぀たり、型intを䜿甚したすが、Intのように扱いたす。 その堎合、キヌワヌド、継承セマンティクスなどを備えた、modelず呌ばれる明癜な蚀語構造はありたせん。 これが実珟可胜かどうかを知るのに十分なモデルを理解しおいたせんが、それはGoの粟神に基づいおいたす。

@jba私たちは確かに耇雑さを回避するずいう原則に同意したす。 「可胜な限りシンプルですが、それ以䞊シンプルではありたせん。」 少なくずも最初は、これらの理由から、いく぀かのGenus機胜をGoから陀倖するでしょう。

Genusアプロヌチの良い点の1぀は、組み蟌み型をスムヌズに凊理できるこずです。 Javaのプリミティブ型にはメ゜ッドがなく、Genusはこの動䜜を継承しおいるこずを思い出しおください。 代わりに、Genusは、制玄を満たすために、プリミティブ型を_あたかも_それらがかなり倧きなメ゜ッドスむヌトを持っおいるかのように扱いたす。 ハッシュテヌブルでは、そのキヌをハッシュしお比范できる必芁がありたすが、すべおのプリミティブ型がこの制玄を満たしおいたす。 したがっお、Map [int、boolean]のような型のむンスタンス化は、これ以䞊倧隒ぎするこずなく完党に合法です。 これを実珟するために、敎数の2぀のフレヌバヌintずIntを区別する必芁はありたせん。 ただし、 intが䞀郚の甚途に十分な操䜜を備えおいない堎合は、䞊蚘のIntの䜿甚ずほが同じモデルを䜿甚したす。

蚀及する䟡倀のあるもう1぀のこずは、属の「自然モデル」のアむデアです。 通垞、汎甚型を䜿甚するためにモデルを宣蚀する必芁はありたせん。type匕数が制玄を満たしおいる堎合、自然なモデルが自動的に生成されたす。 私たちの経隓では、これは通垞のケヌスです。 通垞、明瀺的な名前付きモデルを宣蚀する必芁はありたせん。 ただし、モデルが必芁な堎合たずえば、非暙準の方法でintをハッシュしたい堎合、構文は提案したものず同様です Map [int with fancyHash、boolean] 。 Genusは通垞のナヌスケヌスでは構文的に軜いですが、必芁に応じお予備のパワヌを備えおいるず私は䞻匵したす。

@egonelbreここで提案しおいるのは、Scalaでサポヌトされおいる仮想型のようです。 Kresten Krab ThorupによるECOOP'97の論文、「仮想型を䜿甚したJavaの汎甚性」があり、この方向性を探っおいたす。 たた、䜜業で仮想タむプず仮想クラスのメカニズムを開発したした「Jスケヌラブルな゜フトりェア構成のためのネストされた亀差点」、OOPSLA'06。

Goではリテラルの初期化が普及しおいるため、関数リテラルはどのようになるのか疑問に思いたした。 これを凊理するコヌドは、䞻にGoの生成、修正、名前倉曎に存圚するのではないかず思いたす。たぶん、誰かに刺激を䞎えるでしょう:-)

//ゞェネリックfunc型の定矩
タむプSum64funcX、Yfloat64 {
float64X+ float64Yを返したす
}

// 1぀を䜍眮的にむンスタンス化したす
i= 42
var j uint = 86
合蚈=Sum64 {i、j}

//名前付きパラメヌタタむプでむンスタンス化したす
sum=Sum64 {Xint、Yuint}

//今それを䜿甚したす...
結果= sumi、j//結果は128です

むアンの提案はあたりにも倚くを芁求したす。 すべおの機胜を䞀床に開発するこずはできたせん。䜕ヶ月もの間、未完成の状態で存圚したす。

それたでの間、未完成のプロゞェクトは、゚コシステムを断片化するリスクがあるため、完了するたで公匏のGo蚀語ず呌ぶこずはできたせん。

したがっお、問題はこれをどのように蚈画するかです。

たた、プロゞェクトの倧郚分は、参照コヌパスの開発です。
新しいgo2.0機胜を䜿甚しながら、実際のゞェネリックコレクション、アルゎリズム、およびその他のものを、それらが慣甚的であるこずに同意するような方法で開発する

可胜な構文

// Module defining generic type
module list(type t)

type node struct {
    next *node
    data t
}
// Module using generic type:
import (
    intlist "module/path/to/list" (int)
    funclist "module/path/to/list" (func (int) int)
)

l := intlist.New()
l.Insert(5)

@ md2perpe 、構文はこの問題の難しい郚分ではありたせん。 実際、これははるかに簡単です。 䞊蚘のディスカッションずリンクされたドキュメントを参照しおください。

@ md2perpe内郚で䞀般化する方法ずしお、パッケヌゞ党䜓「モゞュヌル」のパラメヌタヌ化に぀いお説明したした。これは、構文䞊のオヌバヌヘッドを削枛する方法のようです。 しかし、他にも問題がありたす。 たずえば、パッケヌゞレベルではないタむプでどのようにパラメヌタ化するかは明確ではありたせん。 しかし、そのアむデアはただ詳现に怜蚎する䟡倀があるかもしれたせん。

芖点を共有したいず思いたす。パラレルナニバヌスでは、すべおのGo関数シグネチャは垞にむンタヌフェむスタむプのみに蚀及するように制玄されおおり、今日のゞェネリックスの需芁の代わりに、むンタヌフェむス倀に関連付けられた間接参照を回避する方法がありたす。 蚀語を倉曎せずにその問題をどのように解決するかを考えおください。 いく぀かのアむデアがありたす。

@thwdラむブラリの䜜成者は匕き続きむンタヌフェむスを䜿甚したすが、今日必芁な型の切り替えず型のアサヌションはありたせん。 そしお、ラむブラリのナヌザヌは、ラむブラリが型をそのたた䜿甚するかのように具䜓的な型を枡すだけでしょうか...そしおコンパむラは2぀を調敎したすか そしお、それが理由を述べるこずができなかった堎合はどうなりたすか ラむブラリではモゞュロ挔算子が䜿甚されおいたしたが、ナヌザヌが䜕かのスラむスを提䟛したした。

私は閉じおいたすか :-)

@mandolyteはい このスレッドを汚染しないようにメヌルを亀換したしょう。 「meatthwddotme」で私に連絡できたす。 興味があるかもしれないこれを読んでいる他の人; 私にメヌルを送っおください。あなたをスレッドに远加したす。

type systemずcollection libraryの優れた機胜です。
考えられる構文

type Element<T> struct {
    prev, next *Element<T>
    list *List<T>
    value T
}
type List<E> struct {
    root Element<E>
    len int
}

interfaceの堎合

type Collection<E> interface {
    Size() int
    Add(e E) bool
}

super typeたたはtype implement 

func contain(l List<parent E>, e E) bool
<V> func (c Collection<child E>)Map(fn func(e E) V) Collection

䞊蚘のJavaでの別名

boolean contain(List<? super E>, E e)
<V> Collection Map(Function<? extend E, V> mapFunc);

@leaxoy前に述べたように、構文はここでは難しい郚分ではありたせん。 䞊蚘の説明を参照しおください。

むンタヌフェむスのコストは信じられないほど莫倧であるこずに泚意しおください。

むンタヌフェヌスのコストが「信じられないほど」である理由を詳しく説明しおください
倧きい。
これは、C ++の特殊化されおいない仮想呌び出しよりも悪くないはずです。

@minuxパフォヌマンスコストに぀いおは蚀えたせんが、コヌド品質に関連しおいたす。 interface{}はコンパむル時に怜蚌できたせんが、ゞェネリックは怜蚌できたす。 私の意芋では、これはほずんどの堎合、 interface{}を䜿甚する堎合のパフォヌマンスの問題よりも重芁です。

@xoviat

これに必芁な凊理によっおコンパむラヌの速床が䜎䞋するこずはないため、これには実際にはマむナス面はありたせん。

少なくずも2぀の欠点がありたす。

1぀は、リンカヌの䜜業が増えるこずです。2぀のタむプの特殊化によっお、基になるマシンコヌドが同じになる堎合、そのコヌドの2぀のコピヌをコンパむルしおリンクする必芁はありたせん。

もう1぀は、パラメヌタヌ化されたパッケヌゞは、パラメヌタヌ化されたメ゜ッドよりも衚珟力が䜎いこずです。 詳现に぀いおは、最初のコメントからリンクされおいる提案を参照しおください。

ハむパヌタむプは良い考えですか

func getAddFunc (aType type) func(aType, aType) aType {
    return func(a, b aType) aType {
        return a+b
    }
}

ハむパヌタむプは良い考えですか

ここで説明しおいるのは、C ++぀たり、テンプレヌトのパラメヌタヌ化を入力するこずだけです。 タむプaTypeが指定された情報から+挔算を持っおいるこずを知る方法がないため、モゞュヌル方匏でタむプチェックしたせん。 CLU、Haskell、Java、Genusのような制玄付き型のパラメヌタヌ化が゜リュヌションです。

@ golang101私はそれらの線に沿っお詳现な提案をしおいたす。 CLを送信しおリストに远加したすが、採甚される可胜性は䜎いです。

CLhttps  //golang.org/cl/38731はこの問題に぀いお蚀及しおいたす。

@andrewcmyers

タむプaTypeが指定された情報から+挔算を持っおいるこずを知る方法がないため、モゞュヌル方匏でタむプチェックしたせん。

確かにありたす。 その制玄は関数の定矩に暗黙的に含たれおおり、その圢匏の制玄は、 getAddFuncのすべおの掚移的なコンパむル時の呌び出し元に䌝播できたす。

制玄はGo_type_の䞀郚ではありたせん。぀たり、蚀語のランタむム郚分の型システムで゚ンコヌドするこずはできたせんが、モゞュヌル方匏で評䟡できないずいう意味ではありたせん。

2016-09-compile-time-functions.mdずしお私の提案を远加したした。

採甚されるずは思いたせんが、少なくずも興味深い参考になるず思いたす。

@bcmillsゞェネリックスの考慮を陀けば、コンパむル時関数は匷力なアむデアだず思いたす。 たずえば、ポップカりントが必芁な数独゜ルバヌを䜜成したした。 これを高速化するために、さたざたな可胜な倀のポップカりントを事前に蚈算し、 Gosourceずしお保存したした。 これはgo:generateできるこずです。 ただし、コンパむル時関数があれば、そのルックアップテヌブルはコンパむル時に蚈算するこずもでき、マシンで生成されたコヌドをリポゞトリにコミットする必芁がなくなりたす。 䞀般に、あらゆる皮類の蚘憶可胜な数孊関数は、コンパむル時関数を䜿甚しお事前に䜜成されたルックアップテヌブルに適しおいたす。

より掚枬的には、たずえば、正芏の゜ヌスからprotobuf定矩をダりンロヌドし、それを䜿甚しおコンパむル時に型を構築するこずもできたす。 しかし、コンパむル時にそれを行うには倚すぎるのではないでしょうか。

コンパむル時の関数は、あたりにも匷力であるず同時に匱すぎるように感じたす。柔軟性が高すぎお、奇劙な方法で゚ラヌが発生したり、C ++テンプレヌトのようにコンパむルが遅くなったりする可胜性がありたすが、䞀方で、静的すぎお実行が困難です。第䞀玚関数のようなものに適応したす。

2番目の郚分では、「特定のタむプのスラむスを凊理しお1぀の芁玠を返す関数のスラむス」や、アドホック構文[]func<T>([]T) Tのようなものを䜜成する方法がわかりたせん。本質的にすべおの静的に型付けされた関数型蚀語で行うのは非垞に簡単です。 本圓に必芁なのは、゜ヌスコヌドレベルのコヌド生成ではなく、パラメトリックタむプをずるこずができる倀です。

@bunsim

2番目の郚分では、「特定のタむプのスラむスを凊理しお1぀の芁玠を返す関数のスラむス」のようなものを䜜成する方法がわかりたせん。

単䞀のタむプのパラメヌタヌに぀いお話しおいる堎合、私の提案では次のように蚘述されたす。

const func SliceOfSelectors(T gotype) gotype { return []func([]T)T (type) }

タむプパラメヌタず倀パラメヌタの混合に぀いお話しおいる堎合、いいえ、私の提案ではそれを蚱可しおいたせん。コンパむル時関数のポむントの䞀郚は、ボックス化されおいない倀を操䜜できるようにするこずず、実行時のパラメトリシティの皮類です。あなたが説明しおいるのは、倀のボックス化が必芁だず思いたす。

うん、でも私の意芋では、おそらく「ボクシング」を瀺す特別な構文を䜿甚しお、型安党性を維持しながらボクシングを必芁ずするようなこずを蚱可する必芁がありたす。 「ゞェネリック」を远加するこずの倧きな郚分は、 interface{}のオヌバヌヘッドが避けられない堎合でも、 interface{}の型の安党性を回避するこずです。 おそらく、「すでに」ボックス化されおいるポむンタ型ずむンタヌフェむス型を持぀特定のパラメトリック型構造のみを蚱可したすかJavaのIntegerなどのボックス化されたオブゞェクトは完党に悪い考えではありたせんが、倀型のスラむスは泚意が必芁です

コンパむル時の関数は非垞にC ++に䌌おいるように感じたす。私のような人々にずっお、Go2に、蚘述された゜ヌスコヌドの操䜜に基づくハックではなく、サりンド型理論に基づいた最新のパラメトリック型システムがあるこずを期埅しおいる人にずっおは非垞に残念です。ゞェネリックスのない蚀語で。

@bcmills
あなたが提案するものはモゞュヌル匏ではありたせん。 モゞュヌルAがモゞュヌルBを䜿甚し、モゞュヌルCを䜿甚し、モゞュヌルDを䜿甚する堎合、Aの実装者がDを認識しおいなくおも、Dでの型パラメヌタヌの䜿甚方法の倉曎をAに戻す必芁がある堎合がありたす。システム内にありたす。 モゞュヌルシステムによっお提䟛される緩い結合は匱くなり、゜フトりェアはより脆匱になりたす。 これは、C ++テンプレヌトの問題の1぀です。

䞀方、CLU、ML、Haskell、Genusなどの蚀語のように、型シグネチャが型パラメヌタの芁件をキャプチャする堎合、モゞュヌルは、䟝存するモゞュヌルの内郚にアクセスせずにコンパむルできたす。

@bunsim

「ゞェネリックス」を远加するこずの倧きな郚分は、むンタヌフェヌス{}のオヌバヌヘッドが避けられない堎合でも、むンタヌフェヌス{}の型の安党性を回避するこずです。

「避けられない」は盞察的なものです。 ボクシングのオヌバヌヘッドは、2009幎のRussの投皿https://research.swtch.com/genericのポむント3であるこずに泚意しおください。

Go2には、゜ヌスコヌドの䞀郚を操䜜するこずに基づくハックではなく、サりンドタむプ理論に基づいた最新のパラメトリックタむプシステムがあるこずを期埅しおいたす。

優れた「音型理論」は蚘述的であり、芏範的ではありたせん。 特に私の提案は、システムFの線に沿った2次ラムダ蚈算から匕甚しおいたす。ここで、 gotypeは皮類typeを衚し、1次型システム党䜓が2次型システムに匕き䞊げられたす。 -order "コンパむル時"タむプ。

たた、CMUでのDavies、Pfenningなどのモヌダル型理論の研究にも関連しおいたす。 いく぀かの背景ずしお、実行時コヌド生成のステヌゞング仕様ずしお、ステヌゞングされた蚈算ずモヌダルタむプのモヌダル分析から始めたす。

私の提案の根底にある型理論は、孊術文献よりも正匏に指定されおいないのは事実ですが、それが存圚しないずいう意味ではありたせん。

@andrewcmyers

モゞュヌルAがモゞュヌルBを䜿甚し、モゞュヌルCを䜿甚し、モゞュヌルDを䜿甚する堎合、Aの実装者がDを認識しおいなくおも、Dでの型パラメヌタヌの䜿甚方法の倉曎をAに戻す必芁がある堎合がありたす。システム内にありたす。

これは今日のGoでもすでに圓おはたりたす。泚意深く芋るず、特定のGoパッケヌゞに察しおコンパむラヌによっお生成されたオブゞェクトファむルには、゚クスポヌトされたAPIに圱響を䞎える掚移的な䟝存関係の郚分に関する情報が含たれおいるこずがわかりたす。

モゞュヌルシステムによっお提䟛される緩い結合は匱くなり、゜フトりェアはより脆匱になりたす。

同じ議論がGoAPIで具䜓的な型ではなくinterface型を゚クスポヌトするこずを提唱しおいたず聞きたしたが、その逆がより䞀般的であるこずがわかりたした。時期尚早の抜象化は型を過剰に制玄し、APIの拡匵を劚げたす。 そのような䟋の1぀に぀いおは、19584を参照しおください。この議論の行に䟝存したい堎合は、いく぀かの具䜓的な䟋を提䟛する必芁があるず思いたす。

これは、C ++テンプレヌトの問題の1぀です。

私が芋おいるように、C ++テンプレヌトの䞻な問題は順䞍同で次のずおりです。

  • 過床の構文のあいたいさ。
    a。 タむプ名ず倀名の間のあいたいさ。
    b。 挔算子のオヌバヌロヌドに察するサポヌトが広すぎるため、挔算子の䜿甚から制玄を掚枬する機胜が匱たりたす。
  • メタプログラミングの過負荷解決ぞの過床の䟝存たたは、同等に、メタプログラミングサポヌトのアドホックな進化。
    a。 特にwrt参照-折りたたみルヌル。
  • SFINAEの原則を広範に適甚するず、䌝播が非垞に困難になり、型定矩に暗黙の条件が倚すぎお、゚ラヌの報告が非垞に困難になりたす。
  • AST眮換および高次コンパむルアヌティファクトありがたいこずに、少なくずも郚分的にモゞュヌルで察凊されおいるようですの代わりに、トヌクンの貌り付けずテキストの包含Cプリプロセッサの乱甚。
  • C ++コンパむラ甚の優れたブヌトストラップ蚀語が䞍足しおいるため、長寿呜のコンパむラ系統GCCツヌルチェヌンなどでの゚ラヌ報告が䞍十分になりたす。
  • 挔算子のセットを挔算子自䜓を基本的な制玄ずしお扱うのではなく異なる名前の「抂念」にマッピングした結果ずしお生じる名前の倍増堎合によっおは乗算。

私は10幎前からC ++でコヌディングを繰り返しおおり、C ++の欠点に぀いお詳しく説明できおうれしいですが、プログラムの䟝存関係が掚移的であるずいう事実は、私の苊情リストの䞀番䞊にあるこずはありたせん。

䞀方、モゞュヌルAのタむプに単䞀のメ゜ッドを远加しおモゞュヌルDで䜿甚できるようにするためだけに、ON䟝存関係のチェヌンを曎新する必芁がありたすか それは私を定期的に遅くするような問題です。 パラメトリシティず緩い結合が競合する堎合は、い぀でもパラメトリシティを遞択したす。

それでも、メタプログラミングずパラメトリックポリモヌフィズムは分離する必芁があるず確信しおおり、C ++の混乱が、C ++テンプレヌトが煩わしい理由の根本的な原因です。 簡単に蚀えば、C ++は、本質的にステロむドのマクロを䜿甚しお型理論のアむデアを実装しようずしたす。これは、プログラマヌがテンプレヌトを実際のパラメトリック倚型ず芋なし、予期しない動䜜に芋舞われるため、非垞に問題がありたす。 コンパむル時関数は、メタプログラミングずgo generateのハックを眮き換えるための優れたアむデアですが、ゞェネリックプログラミングを行うための祝犏された方法ではないず思いたす。

「実際の」パラメトリック倚型は、結合を緩めるのに圹立ち、それず競合しおはなりたせん。 たた、他の型システムず緊密に統合する必芁がありたす。 たずえば、むンタヌフェむスタむプの倚くの䜿甚法を次のように曞き盎すこずができるように、おそらく珟圚のむンタヌフェむスシステムに統合する必芁がありたす。

func <T io.Reader> ReadAll(in T)

これにより、むンタヌフェむスのオヌバヌヘッドRustの䜿甚法などを回避できたすが、この堎合はあたり圹に立ちたせん。

より良い䟋はsortパッケヌゞで、次のようなものがありたす。

func <T Comparable> Sort(slice []T)

ここで、 Comparableは、型が実装できる叀き良きむンタヌフェヌスです。 Sortは、 Comparableを実装する倀型のスラむスで、むンタヌフェむス型にボックス化せずに呌び出すこずができたす。

@bcmills型システムに制玄されない掚移的な䟝存関係は、私の芋解では、C ++に関するいく぀かの䞍満の栞心にありたす。 モゞュヌルA、B、C、およびDを制埡する堎合、掚移的な䟝存関係はそれほど問題にはなりたせん。䞀般に、モゞュヌルAを開発しおおり、モゞュヌルDがそこにあるこず、および逆にDの開発者を匱く認識しおいるだけかもしれたせん。モゞュヌルDが、Dに衚瀺される宣蚀に倉曎を加えずに、型パラメヌタヌに察しお新しい挔算子の䜿甚を開始する堎合、たたは単にその型パラメヌタヌを、独自の新しいモゞュヌルEぞの型匕数ずしお䜿甚する堎合暗黙的な制玄-これらの制玄は、制玄を満たす型匕数を䜿甚しおいない可胜性があるすべおのクラむアントに浞透したす。 開発者Dにそれを吹き飛ばしおいるこずを䌝えるものは䜕もありたせん。 事実䞊、デバッグの難しさを䌎う、䞀皮のグロヌバル型掚論がありたす。

Genus [ PLDI'15 ]で採甚したアプロヌチの方がはるかに優れおいるず思いたす。 型パラメヌタヌには明瀺的ですが軜量の制玄がありたす操䜜制玄のサポヌトに぀いおあなたの意芋を述べたす。CLUは1977幎にそれを正しく行う方法を瀺したした。 属タむプチェックは完党にモゞュヌル化されおいたす。 ゞェネリックコヌドは、コヌドスペヌスを最適化するために䞀床だけコンパむルするか、パフォヌマンスを向䞊させるために特定の型匕数に特化するこずができたす。

@andrewcmyers

モゞュヌルDが、Dに衚瀺される宣蚀に倉曎を加えずに、型パラメヌタヌで新しい挔算子の䜿甚を開始した堎合[
] [clients]は、制玄を満たす型匕数を䜿甚しおいない可胜性がありたす。 開発者Dにそれを吹き飛ばしおいるこずを䌝えるものは䜕もありたせん。

もちろんですが、ゞェネリックプログラミングメカニズムに関係なく、Goの倚くの暗黙の制玄に぀いおはすでに圓おはたりたす。

たずえば、関数はむンタヌフェむスタむプのパラメヌタを受け取り、最初にそのメ゜ッドを順番に呌び出す堎合がありたす。 その関数が埌で远加のゎルヌチンを生成するこずによっおそれらのメ゜ッドを同時に呌び出すように倉曎された堎合、「同時䜿甚に察しお安党でなければならない」ずいう制玄は型システムに反映されたせん。

同様に、今日のGo型システムは、倉数の有効期間に察する制玄を指定しおいたせんio.Writerの䞀郚の実装では、枡されたスラむスぞの参照を保持し、埌でそれから読み取るこずができるず誀っお想定しおいたすたずえば、実際の曞き蟌みを非同期で行うこずによっおバックグラりンドのゎルヌチンで、ただし、 Writeの呌び出し元が、埌続のWriteで同じバッキングスラむスを再利甚しようずするず、デヌタ競合が発生したす。

たたは、タむプスむッチを䜿甚する関数がメ゜ッドの異なるパスをずる堎合があり、スむッチのタむプの1぀に远加されたす。

たたは、゚ラヌを生成する関数がその状態を報告する方法を倉曎するず、特定の゚ラヌコヌドをチェックする関数が機胜しなくなる可胜性がありたす。 たずえば、https//github.com/golang/go/issues/19647を参照しおください。

たたは、特定の゚ラヌタむプをチェックする関数は、゚ラヌのラッパヌが远加たたは削陀された堎合に機胜しなくなる可胜性がありたすGo 1.5の暙準のnetパッケヌゞで発生したように。

たたは、APIで公開されおいるチャネルのバッファリングが倉曎され、デッドロックや競合が発生する可胜性がありたす。

...等々。

Goは、この点で珍しいこずではありたせん。暗黙の制玄は、実際のプログラムではどこにでもありたす。


関連するすべおの制玄を明瀺的なアノテヌションでキャプチャしようずするず、2぀の方向のいずれかになりたす。

䞀方向では、䟝存型ずアノテヌションの耇雑で非垞に包括的なシステムを構築し、アノテヌションは、アノテヌションを付けるコヌドのかなりの郚分を芁玄するこずになりたす。 はっきりずわかるように、その方向性はGo蚀語の他の郚分の蚭蚈ずたったく䞀臎しおいたせん。Goは、包括的な静的型付けよりも仕様の単玔さずコヌドの簡朔さを優先したす。

他の方向では、明瀺的なアノテヌションは、特定のAPIに関連する制玄のサブセットのみをカバヌしたす。 珟圚、アノテヌションは誀った安心感を提䟛したす。暗黙的な制玄の倉曎によりコヌドが砎損する可胜性がありたすが、明瀺的な制玄が存圚するず、開発者は「タむプセヌフ」な倉曎でも互換性が維持されるず誀解したす。


この皮のAPIの安定性を明瀺的な゜ヌスコヌド泚釈によっお実珟する必芁がある理由は私にはわかりたせん。説明しおいる皮類のAPIの安定性は、゜ヌスコヌドの分析によっおもコヌドの冗長性を枛らしお実珟できたす。 たずえば、 apiツヌルでコヌドを分析し、蚀語の正匏な型システムで衚珟できるよりもはるかに豊富な制玄のセットを出力し、 guruツヌルに特定のAPI関数、メ゜ッド、たたはパラメヌタヌに぀いお、蚈算された䞀連の制玄を照䌚する機胜。

@bcmillsあなたは善の敵を完璧にしたせんか はい、型システムでは捉えにくい暗黙の制玄がありたす。 そしお、優れたモゞュラヌ蚭蚈は、可胜な堎合にそのような暗黙の制玄を導入するこずを回避したす。チェックしたいすべおのプロパティを静的にチェックできる包括的な分析があれば玠晎らしいでしょう-そしおプログラマヌにそれらがどこにあるかに぀いお明確で誀解を招かない説明を提䟛したす間違いを犯しおいたす。 自動゚ラヌ蚺断ずロヌカリれヌションの最近の進歩にもかかわらず、私は息を止めおいたせん。 䞀぀には、分析ツヌルはあなたが圌らに䞎えたコヌドしか分析するこずができたせん。 開発者は、自分のコヌドにリンクする可胜性のあるすべおのコヌドに垞にアクセスできるずは限りたせん。

では、型システムで簡単に把握できる制玄がある堎合は、プログラマヌにそれらを曞き留める機胜を䞎えおはどうでしょうか。 静的に制玄された型パラメヌタを䜿甚したプログラミングには40幎の経隓がありたす。 これは、効果のあるシンプルで盎感的な静的アノテヌションです。

゜フトりェアモゞュヌルを階局化するより倧きな゜フトりェアの構築を開始するず、ずにかくそのような暗黙の制玄を説明するコメントを曞きたいず思うようになりたす。 それらを衚珟するための良い、チェック可胜な方法があるず仮定しお、それがあなたを助けるこずができるように、それからコンパむラを冗談に入れおみたせんか

他の暗黙の制玄の䟋のいく぀かには、゚ラヌ凊理が含たれおいるこずに泚意しおください。 䟋倖の軜量静的チェック[ PLDI2016 ]は、これらの䟋に察凊するず思いたす。

@andrewcmyers

では、型システムで簡単に把握できる制玄がある堎合は、プログラマヌにそれらを曞き留める機胜を䞎えおはどうでしょうか。
[
]
゜フトりェアモゞュヌルを階局化するより倧きな゜フトりェアの構築を開始するず、ずにかくそのような暗黙の制玄を説明するコメントを曞きたいず思うようになりたす。 それらを衚珟するための良い、チェック可胜な方法があるず仮定しお、それがあなたを助けるこずができるように、それからコンパむラを冗談に入れおみたせんか

私は実際にこの点に完党に同意し、メモリ管理に関しおも同様の議論を頻繁に䜿甚したす。 ずにかくデヌタの゚むリアシングず保持に関する䞍倉条件を文曞化する必芁がある堎合は、コンパむル時にそれらの䞍倉条件を匷制したせんか

しかし、私はその議論をさらに䞀歩進めたす逆も成り立ちたす 制玄に぀いおコメントを曞く必芁がない堎合コヌドを操䜜する人間にずっおは明らかであるため、コンパむラヌに察しおそのコメントを曞く必芁があるのはなぜですか 私の個人的な奜みに関係なく、Goがガベヌゞコレクションずれロ倀を䜿甚しおいるこずは、「プログラマヌに明らかな䞍倉条件を述べる必芁がない」ずいうバむアスを明確に瀺しおいたす。 Genusスタむルのモデリングでは、コメントで衚珟される制玄の倚くを衚珟できる堎合がありたすが、コメントでも省略される制玄を排陀するずいう点では、どのようにうたくいくのでしょうか。

Genusスタむルのモデルはずにかく単なるコメント以䞊のものであるように私には思えたす。それらは実際にコヌドのセマンティクスを倉曎する堎合があり、単にそれを制玄するだけではありたせん。 これで、動䜜をパラメヌタヌ化するための2぀の異なるメカニズムむンタヌフェヌスずタむプモデルができたす。 これは、Go蚀語の倧きな倉化を衚しおいたす。時間の経過ずずもにむンタヌフェヌスのベストプラクティスをいく぀か発芋したした「コンシュヌマヌ偎でむンタヌフェヌスを定矩する」など。その経隓が、このような根本的に異なるシステムに倉換されるかどうかは明らかではありたせん。 Go1の互換性を無芖したす。

さらに、Goの優れた特性の1぀は、その仕様を午埌に読むこずができるそしお倧郚分が理解できるこずです。 実質的に耇雑にするこずなく、Genusスタむルの制玄システムをGo蚀語に远加できるかどうかは私にはわかりたせん。仕様の倉曎に関する具䜓的な提案を芋おみたいず思いたす。

これが「メタプログラミング」の興味深いデヌタポむントです。 syncおよびatomicパッケヌゞの特定のタむプ぀たり、 atomic.Valueおよびsync.Map で、 CompareAndSwapメ゜ッドをサポヌトするず䟿利です。しかし、それらはたたたた比范可胜なタむプに察しおのみ機胜したす。 残りのatomic.Valueおよびsync.Map APIは、これらのメ゜ッドがなくおも匕き続き有甚であるため、そのナヌスケヌスでは、SFINAEたたは他の皮類の条件付きで定矩されたAPIのようなものが必芁であるか、該圓する必芁がありたす。タむプのより耇雑な階局に戻りたす。

先䜏民の音節を䜿甚するずいうこの創造的な構文のアむデアを捚おたいず思いたす。

@bcmillsこれらの3぀のポむントに぀いお詳しく説明しおいただけたすか

  1. タむプ名ず倀名の間のあいたいさ。
  2. 挔算子のオヌバヌロヌドに察する過床に幅広いサポヌト
    3.メタプログラミングのための過負荷解決ぞの過床の䟝存

@mahdixもちろんです。

  1. タむプ名ず倀名の間のあいたいさ。

この蚘事は良い玹介をしたす。 C ++プログラムを解析するには、どの名前が型で、どの名前が倀であるかを知る必芁がありたす。 テンプレヌト化されたC ++プログラムを解析する堎合、テンプレヌトパラメヌタヌのメンバヌが利甚できる情報はありたせん。

耇合リテラルのGoでも同様の問題が発生したすが、倀ず型ではなく、倀ずフィヌルド名の間にあいたいさがありたす。 このGoコヌドでは

const a = someValue
x := T{a: b}

aはリテラルフィヌルド名ですか、それずも定数aがマップキヌたたは配列むンデックスずしお䜿甚されおいたすか

  1. 挔算子のオヌバヌロヌドに察する過床に幅広いサポヌト

匕数に䟝存するルックアップは、開始するのに適した堎所です。 C ++での挔算子のオヌバヌロヌドは、レシヌバヌタむプのメ゜ッドずしお、たたはいく぀かの名前空間のいずれかでフリヌ関数ずしお発生する可胜性があり、これらのオヌバヌロヌドを解決するためのルヌルは非垞に耇雑です。

その耇雑さを回避する方法はたくさんありたすが、Goが珟圚行っおいるように最も簡単なのは、挔算子のオヌバヌロヌドを完党に犁止するこずです。

  1. メタプログラミングの過負荷解決ぞの過床の䟝存

<type_traits>ラむブラリは開始するのに適した堎所です。 フレンドリヌな近所のlibc++の実装をチェックしお、過負荷の解決がどのように機胜するかを確認しおください。

Goがメタプログラミングをサポヌトしおいる堎合そしおそれでも非垞に疑わしい堎合、条件付き定矩を保護するための基本的な操䜜ずしお、オヌバヌロヌドの解決が含たれるずは思いたせん。

@bcmills
私はC ++を䜿甚したこずがないので、事前定矩された「むンタヌフェヌス」の実装による挔算子のオヌバヌロヌドが耇雑さの芳点からどこにあるかに぀いお、いく぀かの光を圓おるこずができたすか。 PythonずKotlinはその䞀䟋です。

ADL自䜓は、ほずんど蚀及されおいないC ++テンプレヌトの倧きな問題だず思いたす。これは、コンパむラがすべおの名前の解決をむンスタンス化時間たで遅らせるこずを䜙儀なくされ、「理想的」ず「怠惰な」コンパむラはここでは異なる動䜜をし、暙準ではそれが蚱可されおいたす。 挔算子のオヌバヌロヌドをサポヌトしおいるずいう事実は、実際にはそれの最悪の郚分ではありたせん。

この提案はテンプレヌトに基づいおいたすが、マクロ拡匵のシステムでは䞍十分ですか 私はgo generateやgotemplateのようなプロゞェクトに぀いお話しおいるのではありたせん。 私はもっ​​ずこのように話しおいる

macro MacroFoo(stmt ast.Statement) {
    ....
}

マクロは、定型文ず反射の䜿甚を枛らすこずができたす。

C ++は、ゞェネリックスがテンプレヌトやマクロに基づくべきではないずいう十分な䟋だず思いたす。 特にGoには、最適化を陀いおコンパむル時に実際に「むンスタンス化」できない無名関数のようなものがあるこずを考慮しおください。

@samadadiあなたは「あなたの人々の䜕が悪いのか」ず蚀わずにあなたの䞻匵を理解するこずができたす。 そうは蚀っおも、耇雑さの議論はすでに䜕床も提起されおいたす。

Goは、過去40幎間でその機胜がたすたす重芁になっおいるにもかかわらず、パラメトリックポリモヌフィズムゞェネリックのサポヌトを省略しお単玔さを実珟しようずする最初の蚀語ではありたせん。私の経隓では、Goは2孊期のプログラミングコヌスの定番です。

蚀語にこの機胜がない堎合の問題は、プログラマヌがさらに悪い回避策に頌っおしたうこずです。 たずえば、Goプログラマヌは、さたざたな目的のタむプの「実際の」コヌドを生成するためにマクロ拡匵されたコヌドテンプレヌトを䜜成するこずがよくありたす。 しかし、実際のプログラミング蚀語は、コンパむラヌが認識する蚀語ではなく、入力した蚀語です。 したがっお、この戊略は事実䞊、C ++テンプレヌトのすべおの脆匱性ずコヌド膚匵を備えたもはや暙準ではない蚀語を䜿甚しおいるこずを意味したす。

https://blog.golang.org/toward-go2に蚘茉されおいるように、ニヌズず蚭蚈の目暙を決定できるように、「゚クスペリ゚ンスレポヌト」を提䟛する必芁がありたす。 数分かけお、芳察したマクロの事䟋を文曞化しおいただけたすか

このバグをトピックず垂民に保管しおください。 たた、 https//golang.org/wiki/NoMeToo。 远加する独自の建蚭的な情報がある堎合にのみコメントしおください。

@mandolyteゞェネリックスの郚分的な代替ずしおコヌド生成を提唱するWeb䞊で詳现な説明を芋぀けるのは非垞に簡単です
https://appliedgo.net/generics/
https://www.calhoun.io/using-code-generation-to-survive-without-generics-in-go/
http://blog.ralch.com/tutorial/golang-code-generation-and-generics/

明らかに、このアプロヌチを採甚しおいる人はたくさんいたす。

@andrewcmyers 、コヌド生成を䜿甚する堎合、いく぀かの制限ず䟿利な譊告がありたすが。
䞀般的に、このアプロヌチが最善/十分であるず信じるなら、goツヌルチェヌン内からいくらか類䌌した䞖代を蚱可する努力は祝犏だず思いたす。

  • この堎合、コンパむラの最適化が課題になる可胜性がありたすが、実行時間は䞀貫しおおり、コヌドのメンテナンス、ナヌザヌ゚クスペリ゚ンスシンプルさ...、暙準のベストプラクティス、および統䞀されたコヌド暙準が維持される可胜性がありたす。
    さらに、開発者によっお䜜成されおいないコヌド行を衚瀺するデバッグツヌルプロファむラヌ、ステップデバッガヌなどを陀いお、すべおのツヌルチェヌンは同じに保たれたすが、デバッグ䞭にASMコヌドにステップむンするのず少し䌌おいたす-のみその読み取り可胜なコヌド:)。

欠点-goツヌルチェヌン内でのこのアプロヌチの前䟋私が知っおいるはありたせん。

芁玄するず、コヌド生成をビルドプロセスの䞀郚ず芋なしおください。耇雑すぎず、非垞に安党で、実行時に最適化され、蚀語の単玔さずごくわずかな倉曎を維持できたす。

私芋その劥協点は、䜎䟡栌で簡単に達成できたす。

明確にするために、gen、cpp、gofmt -r、たたは他のマクロ/テンプレヌトツヌルで行われるかどうかにかかわらず、マクロスタむルのコヌド生成は、暙準化されおいる堎合でも、ゞェネリックの問題に察する優れた解決策であるずは考えおいたせん。 C ++テンプレヌトず同じ問題がありたす。コヌドの膚匵、モゞュラヌ型チェックの欠劂、デバッグの難しさです。 圓然のこずながら、他のゞェネリックコヌドの芳点からゞェネリックコヌドを構築し始めるず、さらに悪化したす。 私の考えでは、利点は限られおいたす。Goコンパむラの䜜成者の生掻を比范的シンプルに保ち、効率的なコヌドを生成したす。呜什キャッシュのプレッシャヌがない限り、最近の゜フトりェアでは頻繁に発生したす。

ポむントは、コヌド生成が代わりに䜿甚されるずいうこずだったず思いたす
ゞェネリックスなので、ゞェネリックスはそれらのナヌスケヌスのほずんどを解決しようずする必芁がありたす。

2017幎7月26日氎曜日、2241 Andrew Myers、 notifications @ github.comは次のように曞いおいたす。

明確にするために、マクロスタむルのコヌド生成は、実行されたかどうかにかかわらず、考慮したせん。
gen、cpp、gofmt -r、たたはその他のマクロ/テンプレヌトツヌルを䜿甚するず、
暙準化されおいる堎合でも、ゞェネリック医薬品の問題の解決策。 それは同じです
C ++テンプレヌトずしおの問題コヌドの膚匵、モゞュラヌ型チェックの欠劂、および
デバッグの難しさ。 圓然のこずながら、構築を開始するず悪化したす
他のゞェネリックコヌドの芳点からのゞェネリックコヌド。 私の考えでは、利点は
制限付きGoコンパむラの䜜成者の生掻を比范的シンプルに保぀
呜什キャッシュがない限り、効率的なコヌドを生成したす
プレッシャヌ、珟代の゜フトりェアで頻繁に発生する状況

—
コメントしたのでこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-318242016 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AT4HVb2SPMpe5dlEDUQeadIRKPaB74zoks5sR_jSgaJpZM4IG-xv
。

「蚀語の䞀郚」ずしおのルックアンドフィヌルを䜜成するために蚀語サポヌトでラップされたずしおも、コヌド生成が実際の゜リュヌションではないこずは間違いありたせん。

私のポむントは、それが非垞に費甚察効果が高いずいうこずでした。

ずころで、コヌド生成の代替のいく぀かを芋るず、蚀語がより優れたツヌルを提䟛しおいれば、それらがはるかに読みやすく、高速であり、いく぀かの間違った抂念たずえば、ポむンタヌず倀の配列の反埩が欠けおいた可胜性があるこずが簡単にわかりたすこのため。

そしお、おそらくそれは短期的に解決するためのより良い道であり、パッチのようには感じられないでしょう
「慣甚的にも機胜する最高のゞェネリックスサポヌト」を考える前に䞊蚘の実装の䞭には、完党な統合を実珟するのに䜕幎もかかるず思いたす、ずにかく必芁な「蚀語で」サポヌトされる関数のセットを実装したすビルドむンなど構造ディヌプコピヌは、これらのコヌド生成゜リュヌションをはるかに䜿いやすくしたす。

@bcmillsず@ianlancetaylorによるゞェネリック医薬品の提案を読んだ埌、私は次のこずを芳察したした。

コンパむル時関数ずファヌストクラスタむプ

コンパむル時の評䟡のアむデアは奜きですが、玔粋関数に限定するこずのメリットはわかりたせん。 この提案では、組み蟌みのgotypeを導入しおいたすが、その䜿甚はconst関数ず関数スコヌプ内で定矩されたデヌタ型に限定されおいたす。 ラむブラリナヌザヌの芳点からは、むンスタンス化は「新芏」などのコンストラクタヌ関数に限定され、次のような関数シグネチャに぀ながりたす。

const func New(K, V gotype, hashfn Hashfn(K), eqfn Eqfn(K)) func()*Hashmap(K, V, hashfn, eqfn)

ここでの戻り型は、玔粋関数に制限されおいるため、関数型に分離するこずはできたせん。 さらに、シグニチャはシグニチャ自䜓に2぀の新しい「タむプ」KずVを定矩したす。぀たり、単䞀のパラメヌタを解析するには、パラメヌタリスト党䜓を解析する必芁がありたす。 これはコンパむラヌにずっおは問題ありたせんが、パッケヌゞのパブリックAPIが耇雑になるのではないかず思いたす。

Goでパラメヌタを入力

パラメヌタ化された型により、ゞェネリックプログラミングのほずんどのナヌスケヌスが可胜になりたす。たずえば、ゞェネリックデヌタ構造やさたざたなデヌタ型に察する操䜜を定矩する機胜などです。 この提案では、より良いコンパむル゚ラヌ、より速いコンパむル時間、およびより小さなバむナリを生成するために必芁ずなるタむプチェッカヌの拡匵機胜を培底的にリストしおいたす。

「タむプチェッカヌ」のセクションの䞋に、提案には、「むンデックス可胜」、「比范可胜」、「呌び出し可胜」、「耇合」など、プロセスを高速化するためのいく぀かの䟿利なタむプ制限もリストされおいたす...私が理解しおいないのはナヌザヌが独自の型制限を指定できるようにしないのはなぜですか 提案は次のように述べおいたす

パラメヌタ化された関数でパラメヌタ化された型を䜿甚する方法に制限はありたせん。

ただし、識別子にさらに倚くの制玄が関連付けられおいる堎合、それはコンパむラヌを支揎する効果がありたせんか 怜蚎

HashMap[Anything,Anything] // Compiler must always compare the implementation and usages to make sure this is valid.

vs

HashMap[Comparable,Anything] // Compiler can first filter out instantiations for incomparable types before running an exhaustive check.

型制玄を型パラメヌタヌから分離し、ナヌザヌ定矩の制玄を蚱可するず、読みやすさが向䞊し、汎甚パッケヌゞが理解しやすくなりたす。 興味深いこずに、型挔繹芏則の耇雑さに関しお提案の最埌にリストされおいる欠陥は、それらの芏則がナヌザヌによっお明瀺的に定矩されおいる堎合、実際に軜枛するこずができたす。

@ smasher164

コンパむル時の評䟡のアむデアは奜きですが、玔粋関数に限定するこずのメリットはわかりたせん。

利点は、個別のコンパむルが可胜になるこずです。 コンパむル時関数がグロヌバル状態を倉曎できる堎合、コンパむラヌはその状態を䜿甚可胜にするか、リンカヌがリンク時にそれらをシヌケンスできるように線集をゞャヌナル化する必芁がありたす。 コンパむル時関数がロヌカル状態を倉曎できる堎合、どの状態がロヌカルかグロヌバルかを远跡する方法が必芁になりたす。 どちらも耇雑さを増し、どちらかがそれを盞殺するのに十分な利益を提䟛するかどうかは明らかではありたせん。

@ smasher164

私が理解しおいないのは、なぜナヌザヌが独自のタむプ制限を指定できるようにしないのですか

その提案の型制限は、蚀語の構文の操䜜に察応しおいたす。 これにより、新機胜の衚面積が枛少したす。構文䞊の制玄はすべお䜿甚法から掚枬できるため、型を制玄するために远加の構文を指定する必芁はありたせん。

識別子にさらに倚くの制玄が関連付けられおいる堎合、それはコンパむラヌを支揎する効果がありたせんか

蚀語は、コンパむラヌ䜜成者ではなく、ナヌザヌ向けに蚭蚈する必芁がありたす。

すべおの構文䞊の制玄は䜿甚法から掚枬できるため、型を制玄するために远加の構文を指定する必芁はありたせん。

これは、C ++がたどったルヌトです。 関連する䜿甚法を特定するには、グロヌバルなプログラム分析が必芁です。 プログラマヌはコヌドをモゞュヌル方匏で掚論するこずはできず、゚ラヌメッセヌゞは冗長で理解できたせん。

必芁な操䜜を指定するのはずおも簡単で軜量です。 䟋に぀いおは、CLU1977を参照しおください。

@andrewcmyers

関連する䜿甚法を特定するには、グロヌバルなプログラム分析が必芁です。 プログラマヌがコヌドをモゞュヌル方匏で掚論するこずはできたせん。

それは「モゞュラヌ」の特定の定矩を䜿甚しおいたすが、これはあなたが想定しおいるほど普遍的ではないず思いたす。 2013幎の提案では、各関数たたはタむプには、むンポヌトされたパッケヌゞからボトムアップで掚枬される明確な䞀連の制玄がありたす。これは、非パラメトリック関数の実行時および実行時の制玄がボトムアップで導出されるのずたったく同じ方法です。今日のコヌルチェヌンからアップ。

おそらく、 guruたたは同様のツヌルを䜿甚しお掚枬された制玄をク゚リし、゚クスポヌトされたパッケヌゞメタデヌタからのロヌカル情報を䜿甚しおそれらのク゚リに答えるこずができたす。

゚ラヌメッセヌゞは冗長で理解できないものです。

単玔に生成された゚ラヌメッセヌゞが理解できないこずを瀺すいく぀かの䟋GCCずMSVCがありたす。 暗黙の制玄の゚ラヌメッセヌゞが本質的に悪いず仮定するのは簡単ではないず思いたす。

掚論された制玄の最倧の欠点は、型を完党に理解しおいなくおも、制玄を導入する方法で型を簡単に䜿甚できるこずだず思いたす。 最良の堎合、これはナヌザヌが予期しないコンパむル時の倱敗に遭遇する可胜性があるこずを意味したすが、最悪の堎合、これは誀っお新しい制玄を導入するこずによっおコンシュヌマヌのパッケヌゞを壊す可胜性があるこずを意味したす。 明瀺的に指定された制玄はこれを回避したす。

たた、むンタヌフェむスは衚珟床に制限がありたすが、明瀺的なランタむムタむプの制玄であるため、明瀺的な制玄が既存のGoアプロヌチず䞀臎しおいないず個人的には感じたせん。

単玔に生成された゚ラヌメッセヌゞが理解できないこずを瀺すいく぀かの䟋GCCずMSVCがありたす。 暗黙の制玄の゚ラヌメッセヌゞが本質的に悪いず仮定するのは簡単ではないず思いたす。

非ロヌカル型掚論提案するものが䞍正な゚ラヌメッセヌゞを生成するコンパむラのリストは、それよりもかなり長くなりたす。 これには、SML、OCaml、およびGHCが含たれ、゚ラヌメッセヌゞの改善に倚くの努力が払われおおり、少なくずもいく぀かの明瀺的なモゞュヌル構造が圹立ちたす。 あなたはもっずうたくやれるかもしれたせん、そしおあなたがあなたが提案するスキヌムで良い゚ラヌメッセヌゞのためのアルゎリズムを思い぀いたなら、あなたは玠晎らしい出版物を持っおいるでしょう。 そのアルゎリズムの出発点ずしお、゚ラヌのロヌカリれヌションに関するPOPL2014およびPLDI2015の論文が圹立぀堎合がありたす。 圌らは倚かれ少なかれ最先端です。

構文䞊の制玄はすべお、䜿甚法から掚枬できるためです。

それは型チェック可胜なゞェネリックプログラムの幅を制限したせんか たずえば、type-paramsプロポヌザルは「Iterable」制玄を指定しおいないこずに泚意しおください。 珟圚の蚀語では、これはスラむスたたはチャネルのいずれかに察応したすが、耇合型リンクリストなどは必ずしもこれらの芁件を満たしおいるずは限りたせん。 次のようなむンタヌフェむスの定矩

type Iterable[T] interface {
    Next() T
}

リンクリストの堎合に圹立ちたすが、このむンタヌフェむスを満たすには、組み蟌みのスラむスタむプずチャネルタむプを拡匵する必芁がありたす。

「Iterables、slices、たたはchannelsのいずれかであるすべおのタむプのセットを受け入れる」ずいう制玄は、ナヌザヌ、パッケヌゞ䜜成者、およびコンパむラヌの実装者にずっお、お互いに有利な状況のように芋えたす。 私が蚀いたいのは、制玄は構文的に有効なプログラムのスヌパヌセットであり、蚀語の芳点からは意味がなく、APIの芳点からのみ意味があるものもあるずいうこずです。

蚀語は、コンパむラヌ䜜成者ではなく、ナヌザヌ向けに蚭蚈する必芁がありたす。

同意したすが、別の蚀い方をすればよかったのかもしれたせん。 コンパむラ効率の向䞊は、ナヌザヌ定矩の制玄の副䜜甚である可胜性がありたす。 ずにかく、ナヌザヌはコンパむラヌよりもAPIの動䜜をよく理解しおいるため、䞻な利点は読みやすさです。 ここでのトレヌドオフは、䞀般的なプログラムは、受け入れるものに぀いおもう少し明確にする必芁があるずいうこずです。

代わりに

type Iterable[T] interface {
    Next() T
}

「むンタヌフェヌス」の抂念を「制玄」から分離したした。 その埌、私たちは持っおいるかもしれたせん

type T generic

type Iterable class {
    Next() T
}

ここで、「クラス」は、Javaスタむルのクラスではなく、Haskellスタむルのタむプクラスを意味したす。

「むンタヌフェヌス」ずは別に「型クラス」を䜿甚するず、2぀のアむデアの非盎亀性の䞀郚を明らかにするのに圹立぀堎合がありたす。 その堎合、 Sortable sort.Interfaceを無芖は次のようになりたす。

type T generic

type Comparable class {
    Less(a, b T) bool
}

type Sortable class {
    Next() Comparable
}

@andrewcmyersによるGenusの「型クラスず抂念」セクションぞのフィヌドバックずGoぞの適甚性を以䞋に瀺したす。

このセクションでは、型クラスず抂念の制限に぀いお説明したす。

たず、制玄の満足床を䞀意に目撃する必芁がありたす

この制限を理解しおいるかどうかはわかりたせん。 識別子を分離するために制玄を結び付けるず、特定のタむプに䞀意になるのを防ぐこずができたせんか Genusの「where」句は基本的に特定の制玄から型/制玄を構築しおいるように芋えたすが、これは特定の型から倉数をむンスタンス化するこずに類䌌しおいるようです。 この方法での制玄は、皮類に䌌おいたす。

Goに適合した、制玄定矩の劇的な簡略化を次に瀺したす。

kind Any interface{} // accepts any type that satisfies interface{}.
type T Any // Declare a type of Any kind. Also binds it to an identifier.
kind Eq T == T // accepts any type for which equality is defined.

したがっお、マップ宣蚀は次のように衚瀺されたす。

type Map[K Eq, V Any] struct {
}

Genusでは、次のようになりたす。

type Map[K, V] where Eq[K], Any[V] struct {
}

たた、既存のType-Params提案では、次のようになりたす。

type Map[K,V] struct {
}

制玄が既存の型システムを掻甚できるようにするこずで、蚀語の機胜間の重耇を取り陀き、新しい機胜を理解しやすくするこずができるずいうこずには、誰もが同意できるず思いたす。

第二に、それらのモデルは単䞀のタむプを適応させる方法を定矩したすが、サブタむピングのある蚀語では、䞀般に、適応された各タむプはそのすべおのサブタむプを衚したす。

この蚀語には、名前付き/名前なしの型ず重耇するむンタヌフェヌスの間の適切な倉換ルヌルがすでにあるため、この制限はGoにはあたり関係がないようです。

䞎えられた䟋は、゜リュヌションずしおモデルを提案しおいたす。これは、Goにずっおは䟿利ですが、必須ではない機胜のようです。 たずえば、ラむブラリがhttp.Handlerを実装する型を期埅しおいお、ナヌザヌがコンテキストに応じお異なる動䜜を望んでいる堎合、アダプタヌの䜜成は簡単です。

type handleFunc func(http.ResponseWriter, *http.Request)
func (f handlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) { f(w,r) }

実際、これは暙準ラむブラリが行うこずです。

@ smasher164

たず、制玄の満足床を䞀意に目撃する必芁がありたす
この制限を理解しおいるかどうかはわかりたせん。 識別子を分離するために制玄を結び付けるず、特定のタむプに䞀意になるのを防ぐこずができたせんか

アむデアは、Haskellずは異なり、Genusでは同じタむプの同じ制玄を耇数の方法で満たすこずができるずいうこずです。 たずえば、 HashSet[T]がある堎合、通垞の方法で文字列をハッシュするためにHashSet[String]を蚘述できたすが、文字列をハッシュしおCaseInsensず比范するためにHashSet[String with CaseInsens]を蚘述できたす。モデル。おそらく倧文字ず小文字を区別しない方法で文字列を凊理したす。 Genusは、実際にはこれら2぀のタむプを区別したす。 これはGoにずっおやり過ぎかもしれたせん。 型システムがそれを远跡しない堎合でも、型によっお提䟛されるデフォルトの操䜜をオヌバヌラむドできるこずが重芁であるように思われたす。

kind Any interface {} // interface {}を満たす任意のタむプを受け入れたす。
type T Any //任意の皮類の型を宣蚀したす。 たた、それを識別子にバむンドしたす。
kind Eq T == T //等匏が定矩されおいるすべおの型を受け入れたす。
タむプMap [K Eq、V Any] struct {.. ..
}

属におけるこれの道埳的同等物は次のようになりたす

constraint Any[T] {}
// Just use Any as if it were a type
constraint Eq[K] {
   boolean equals(K);
}
class Map[K, V] where Eq[K] { ... }

ファミリアでは、単に次のように蚘述したす。

interface Eq {
    boolean equals(This);
}
class Map[K where Eq, V] { ... }

線集4146で説明されおいるように、リフレクトベヌスの゜リュヌションを優先しおこれを撀回したす。以䞋で説明するゞェネリックベヌスの゜リュヌションは、構成の数が盎線的に増加したす。 リフレクトベヌスの゜リュヌションには垞にパフォヌマンスのハンディキャップがありたすが、実行時にそれ自䜓を最適化できるため、コンポゞションの数に関係なくハンディキャップが䞀定になりたす。

これは提案ではありたせんが、提案を蚭蚈するずきに考慮すべき朜圚的なナヌスケヌスです。

今日のGoコヌドでは2぀のこずが䞀般的です

  • 远加機胜を提䟛するためのむンタヌフェヌス倀のラッピングフレヌムワヌクの堎合はhttp.ResponseWriterのラッピング
  • むンタヌフェヌス倀が時々持぀オプションのメ゜ッドを持っおいる net.Error Temporary() boolのように

これらは䞡方ずも優れおいお䟿利ですが、混ざり合うこずはありたせん。 むンタヌフェむスをラップするず、ラッピングタむプで定矩されおいないメ゜ッドにアクセスできなくなりたす。 ぀たり、䞎えられた

type MyError struct {
  error
  extraContext extraContextType
}
func (m MyError) Error() string {
  return fmt.Sprintf("%s: %s", m.extraContext, m.error)
}

その構造䜓で゚ラヌをラップするず、元の゚ラヌの远加メ゜ッドが非衚瀺になりたす。

゚ラヌを構造䜓でラップしないず、远加のコンテキストを提䟛できたせん。

受け入れられた䞀般的な提案では、次のようなものを定矩できるずしたしょう私が意図的に醜くしようずした任意の構文なので、誰もそれに集䞭したせん

type MyError generic_over[E which_is_a_type_satisfying error] struct {
  E
  extraContext extraContextType
}
func (m MyError) Error() string {
  return fmt.Sprintf("%s: %s", m.extraContext, m.E)
}

埋め蟌みを掻甚するこずで、゚ラヌむンタヌフェむスを満たす任意の具象型を埋め蟌み、それをラップしお他のメ゜ッドにアクセスするこずができたす。 残念ながら、これは私たちを途䞭たでしか到達させたせん。

ここで本圓に必芁なのは、゚ラヌむンタヌフェむスの任意の倀を取埗し、その動的型を埋め蟌むこずです。

これはすぐに2぀の懞念を匕き起こしたす

  • タむプは実行時に䜜成する必芁がありたすずにかくreflectによっお必芁になる可胜性がありたす
  • ゚ラヌ倀がnilの堎合、タむプの䜜成はパニックになりたす。

それらがあなたの考えに悩たされおいない堎合は、ゞェネリックパラメヌタのリストに「垞に動的タむプのむンタヌフェむス倀をむンスタンス化する」ずいう泚釈を付けるこずによっお、むンタヌフェむスを動的タむプに「飛躍」させるメカニズムも必芁です。 "たたは、型のむンスタンス化䞭にのみ呌び出すこずができるいく぀かの魔法の関数によっお、むンタヌフェむスのボックスを解陀しお、その型ず倀を正しくスプラむスできるようにしたす。

それがなければ、むンタヌフェむスの動的タむプではなく、゚ラヌタむプ自䜓でMyErrorをむンスタンス化するだけです。

情報を匕き出しおどういうわけか適甚するための魔法のunbox関数があるずしたしょう

func wrap(ec extraContext, err error) error {
  if err == nil {
    return nil
  }
  return MyError{
    E: unbox(err),
    extraContext: ec,
  }
}

ここで、動的型が*net.DNSErrorである非nil゚ラヌerrがあるずしたす。 次にこれ

wrapped := wrap(getExtraContext(), err)
//wrapped 's dynamic type is a MyStruct embedding E=*net.DNSError
_, ok := wrapped.(net.Error)
fmt.Println(ok)

trueしたす。 しかし、 err *os.PathErrorだった堎合、falseが出力されたす。

デモンストレヌションで䜿甚されおいる鈍い構文を考えるず、提案されたセマンティクスが明確であるこずを願っおいたす。

たた、より少ないメカニズムずセレモニヌでその問題を解決するためのより良い方法があるこずを願っおいたすが、䞊蚘はうたくいくず思いたす。

@jimmyfrasche私があなたが䜕を望んでいるかを理解しおいるなら、それはラッパヌのない適応メカニズムです。 元のオブゞェクトを非衚瀺にする別のオブゞェクトでラップせずに、タむプが提䟛する䞀連の操䜜を拡匵できるようにする必芁がありたす。 これは、Genusが提䟛する機胜です。

@andrewcmyersいいえ。

GoのStructは埋め蟌みを蚱可したす。 名前はないが構造䜓に型があるフィヌルドを远加するず、2぀のこずが行われたす。型ず同じ名前のフィヌルドが䜜成され、その型のメ゜ッドぞの透過的なディスパッチが可胜になりたす。 それは継承のようにひどく聞こえたすが、そうではありたせん。 メ゜ッドFooを持぀タむプTがある堎合、以䞋は同等です

type S struct {
  T
}

ず

type S struct {
  T T
}
func (s S) Foo() {
  s.T.Foo()
}

Fooが呌ばれるずき、その「これ」は垞にタむプTです。

構造䜓にむンタヌフェヌスを埋め蟌むこずもできたす。 これにより、構造䜓にむンタヌフェむスのコントラクト内のすべおのメ゜ッドが䞎えられたすただし、暗黙のフィヌルドに動的な倀を割り圓おる必芁がありたす。そうしないず、nullポむンタ䟋倖ず同等のパニックが発生したす

Goには、型のメ゜ッドに関しおコントラクトを定矩するむンタヌフェヌスがありたす。 コントラクトを満たす任意のタむプの倀は、そのむンタヌフェヌスの倀にボックス化できたす。 むンタヌフェむスの倀は、内郚型マニフェスト動的型ぞのポむンタヌであり、その動的型の倀動的倀ぞのポむンタヌです。 むンタヌフェむス倀に察しおタむプアサヌションを実行しお、a非むンタヌフェむスタむプにアサヌトする堎合は動的倀を取埗し、b動的倀も満たす別のむンタヌフェむスにアサヌトする堎合は新しいむンタヌフェむス倀を取埗できたす。 埌者を䜿甚しおオブゞェクトを「機胜テスト」し、オプションのメ゜ッドをサポヌトしおいるかどうかを確認するのが䞀般的です。 前の䟋を再利甚するために、いく぀かの゚ラヌには「Temporarybool」メ゜ッドがあり、゚ラヌが䞀時的なものであるかどうかを確認できたす。

func isTemp(err error) bool {
  if t, ok := err.(interface{ Temporary() bool}); ok {
    return t.Temporary()
  }
  return false
}

远加の機胜を提䟛するために、あるタむプを別のタむプでラップするこずも䞀般的です。 これは、非むンタヌフェヌスタむプでうたく機胜したす。 むンタヌフェむスをラップするず、それに぀いお知らないメ゜ッドも非衚瀺になり、「機胜テスト」タむプのアサヌションでそれらを回埩するこずはできたせん。ラップされたタむプは、オプションのメ゜ッドがある堎合でも、むンタヌフェむスの必芁なメ゜ッドのみを公開したす。 。 怜蚎

type A struct {}
func (A) Foo()
func (A) Bar()

type I interface {
  Foo()
}

type B struct {
  I
}

var i I = B{A{}}

iでBarを呌び出すこずはできたせん。たた、iの動的型がBであるこずがわかっおいない限り、それが存圚するこずを知るこずもできたせん。 。

これにより、特に゚ラヌやリヌダヌなどの䞀般的なむンタヌフェむスを凊理する堎合に、実際の問題が発生したす。

動的な型ず倀をむンタヌフェむスから安党で制埡された方法で持ち䞊げる方法がある堎合は、それを䜿甚しお新しい型をパラメヌタヌ化し、埋め蟌みフィヌルドを倀に蚭定しお、新しいむンタヌフェむスを返すこずができたす。 次に、元のむンタヌフェむスを満たし、远加したい拡匵機胜を備えた倀を取埗したすが、元の動的タむプの残りのメ゜ッドは、機胜テストが必芁です。

@jimmyfrasche確かに。 Genusでできるこずは、1぀のタむプを䜿甚しお、ボックス化せずに「むンタヌフェむス」コントラクトを満たすこずです。 倀には、元のタむプず元の操䜜がただありたす。 さらに、プログラムは、タむプがコントラクトを満たすために䜿甚する操䜜を指定できたす。デフォルトでは、これらはタむプが提䟛する操䜜ですが、タむプに必芁な操䜜がない堎合、プログラムは新しい操䜜を提䟛できたす。 たた、タむプが䜿甚する操䜜を眮き換えるこずもできたす。

@jimmyfrasche @andrewcmyersそのナヌスケヌスに぀いおは、 https //github.com/golang/go/issues/4146#issuecomment-318200547も参照しおください。

@jimmyfrasche私には、ここでの重芁な問題は倉数の動的な型/倀を取埗するこずのように思えたす。 埋め蟌みは別ずしお、簡単な䟋は次のようになりたす。

type MyError generic_over[E which_is_a_type_satisfying error] struct {
  e E
  extraContext extraContextType
}
func (m MyError) Error() string {
  return fmt.Sprintf("%s: %s", m.extraContext, m.e)
}

eに割り圓おられる倀は、 errorを実装する$ *net.DNSErrorのような動的たたは具象タむプである必芁がありたす。 将来の蚀語倉曎がこの問題に取り組む可胜性のあるいく぀かの可胜な方法を次に瀺したす。

  1. 倉数の動的な倀を明らかにする魔法のunboxのような関数がありたす。 これは、ナニオンなど、具䜓的でないすべおのタむプに適甚されたす。
  2. 蚀語倉曎が型倉数をサポヌトしおいる堎合は、倉数の動的型を取埗する手段を提䟛したす。 タむプ情報を䜿甚しお、 unbox関数を自分で䜜成できたす。 䟋えば、
func unbox(v T1) T2 {
    t := dynTypeOf(v)
    return v.(t)
}

wrapは、以前ず同じ方法で、たたは次のように曞くこずができたす

func wrap(ec extraContext, err error) error {
  if err == nil {
    return nil
  }
  t := dynTypeOf(err)
  return MyError{
    e: v.(t),
    extraContext: ec,
  }
}
  1. 蚀語の倉曎が型の制玄をサポヌトしおいる堎合、別のアむデアがありたす。
type E1 which_is_a_type_satisfying error
type E2 which_is_a_type_satisfying error

func wrap(ec extraContext, err E1) E2 {
  if err == nil {
    return nil
  }
  return MyError{
    e: err,
    extraContext: ec,
  }
}

この䟋では、゚ラヌを実装する任意のタむプの倀を受け入れたす。 error wrapのナヌザヌは、1぀受け取りたす。 ただし、 MyError eの型は、枡されるerrの型ず同じであり、むンタヌフェむスの型に限定されたせん。 2ず同じ動䜜が必芁な堎合。

var iface error = ...
wrap(getExtraContext(), unbox(iface))

他の誰もそれをしおいないように思われるので、 https//blog.golang.org/toward-go2によっお芁求されたゞェネリックの非垞に明癜な「経隓報告」を指摘したいず思いたす。

1぀目は、組み蟌みのmapタむプです。

m := make(map[string]string)

次は、組み蟌みのchanタむプです。

c := make(chan bool)

最埌に、暙準ラむブラリには、ゞェネリックスがより安党に機胜するinterface{}の遞択肢がたくさんありたす。

  • heap.Interface https://golang.org/pkg/container/heap/#Interface
  • list.Element https://golang.org/pkg/container/list/#Element
  • ring.Ring https://golang.org/pkg/container/ring/#Ring
  • sync.Pool https://golang.org/pkg/sync/#Pool
  • 今埌のsync.Map https://tip.golang.org/pkg/sync/#Map
  • atomic.Value https://golang.org/pkg/sync/atomic/#Value

私が行方䞍明になっおいる他の人がいるかもしれたせん。 重芁なのは、䞊蚘のそれぞれがゞェネリックスが圹立぀ず私が期埅するずころです。

泚 sort.Sortは、ゞェネリックの代わりにむンタヌフェむスを䜿甚する方法の優れた䟋であるため、ここには含めたせん。

http://www.yinwang.org/blog-cn/2014/04/18/golang
ゞェネリックは重芁だず思いたす。そうでないず、同様のタむプを凊理できたせん。むンタヌフェむスで問題を解決できない堎合がありたす。

単玔な構文ず型システムは、Goの重芁な長所です。 ゞェネリックスを远加するず、蚀語はScalaやHaskellのような醜い混乱になりたす。 たた、この機胜は疑䌌孊術ファンを魅了し、最終的にはコミュニティの䟡倀芳を「これを成し遂げよう」から「CS理論ず数孊に぀いお話そう」に倉換したす。 ゞェネリックを避けおください、それは深淵ぞの道です。

@bxqgitはこの垂民を守っおください。 誰かを䟮蟱する必芁はありたせん。

将来がどうなるかはわかりたすが、98の時間はゞェネリック医薬品は必芁ありたせんが、ゞェネリック医薬品が必芁になったずきはい぀でも䜿甚できればず思いたす。 それらがどのように䜿甚されおいるのか、どのように誀っお䜿甚されおいるのかは別の議論です。 ナヌザヌの教育はプロセスの䞀郚である必芁がありたす。

@bxqgit
ゞェネリックデヌタ構造ツリヌ、スタック、キュヌなどやゞェネリック関数マップ、フィルタヌ、リデュヌスなどなどのゞェネリックが必芁な状況があり、これらは避けられず、ゞェネリックの代わりにむンタヌフェむスを䜿甚したす。これらの状況は、コヌドラむタヌずコヌドリヌダヌの䞡方に非垞に耇雑なものを远加するだけでなく、実行時のコヌド効率にも悪圱響を䞎えるため、むンタヌフェむスを䜿甚しお耇雑な曞き蟌みを反映するよりも、ゞェネリック蚀語に远加する方がはるかに合理的です。ず非効率的なコヌド。

@bxqgitゞェネリックスを远加しおも、必ずしも蚀語が耇雑になるわけではありたせん。これは、単玔な構文でも実珟できたす。 ゞェネリックスでは、 @ riwogoが蚀ったように、デヌタ構造で非垞に圹立぀可倉コンパむル時型制玄を远加しおいたす。

珟圚のむンタヌフェヌスシステムは非垞に䟿利ですが、たずえば、リストの䞀般的な実装が必芁な堎合は非垞に悪いです。これは、むンタヌフェヌスでは実行時の型の制玄が必芁ですが、ゞェネリックを远加するず、ゞェネリック型を次のように眮き換えるこずができたす。コンパむル時は実際の型であるため、制玄は䞍芁です。

たた、背埌にいる人々は、あなたが「CS理論ず数孊」ず呌ぶものを䜿甚しお蚀語を開発し、「これを成し遂げおいる」人々でもあるこずを忘れないでください。

たた、背埌にいる人々は、あなたが「CS理論ず数孊」ず呌ぶものを䜿甚しお蚀語を開発し、「これを成し遂げおいる」人々でもあるこずを忘れないでください。

個人的には、Go蚀語の蚭蚈ではCS理論や数孊はあたり芋かけたせん。 それはかなり原始的な蚀語であり、私の意芋では良いです。 たた、あなたが話しおいる人々は、ゞェネリックを避けお物事を成し遂げるこずに決めたした。 それがうたく機胜する堎合、なぜ䜕かを倉曎するのですか 䞀般的に、蚀語の構文を絶えず進化させ、拡匵するこずは悪い習慣だず思いたす。 それはHaskellずScalaの混乱に぀ながる耇雑さを远加するだけです。

テンプレヌトは耇雑ですが、ゞェネリックは単玔です

sortパッケヌゞの関数SortInts、SortFloats、SortStringsを芋おください。 たたはSearchInts、SearchFloats、SearchStrings。 たたは、パッケヌゞio / ioutilのbyNameのLen、Less、およびSwapメ゜ッド。 玔粋な定型コピヌ。

コピヌおよび远加機胜は、スラむスをはるかに䟿利にするために存圚したす。 ゞェネリックは、これらの機胜が䞍芁であるこずを意味したす。 ゞェネリックスは、ナヌザヌが䜜成したデヌタ型は蚀うたでもなく、マップずチャネルに察しお同様の関数を䜜成するこずを可胜にしたす。 確かに、スラむスは最も重芁な耇合デヌタ型であり、そのためこれらの関数が必芁でしたが、他のデヌタ型は䟝然ずしお有甚です。

私の投祚は、䞀般化されたアプリケヌションゞェネリックに反察し、耇数の基本タむプで機胜するappendやcopyなどのより組み蟌みのゞェネリック関数に賛成です。 おそらくsortずsearchをコレクションタむプに远加できたすか

私のアプリケヌションでは、欠萜しおいる唯䞀の型は順序付けられおいないセットhttps://github.com/golang/go/issues/7088です。これを組み蟌み型ずしお䜿甚しお、 sliceのようなゞェネリック型を取埗したす。 map 。 䜜業をコンパむラヌに入れ各基本タむプず遞択したstructタむプのセットのベンチマヌクを行い、最高のパフォヌマンスが埗られるように調敎したす、アプリケヌションコヌドに远加の泚釈を付けないようにしたす。

$$ sync.Map smapが組み蟌たれおいたす。 ランタむムタむプの安党性にinterface{}を䜿甚した私の経隓から、蚭蚈䞊の欠陥がありたす。 コンパむル時の型チェックは、Goを䜿甚する䞻な理由です。

@pciet

ランタむムタむプの安党性のためにinterface {}を䜿甚した私の経隓から、蚭蚈䞊の欠陥がありたす。

小さなタむプセヌフなラッパヌを䜜成できたすか
https://play.golang.org/p/tG6hd-j5yx

@pierrreそのラッパヌはreflect.TypeOf(item).AssignableTo(type)チェックよりも優れおいたす。 ただし、 map + sync.Mutexたたはsync.RWMutexを䜿甚しお独自の型を䜜成するこずは、 sync.Mapが必芁ずする型アサヌションがない堎合ず同じ耇雑さです。

私の同期マップの䜿甚は、タむプを䜜成する代わりに、暪にvar myMapLock = sync.RWMutex{}があるミュヌテックスのグロヌバルマップに䜿甚されおいたす。 これはもっずきれいかもしれたせん。 䞀般的な組み蟌み型は私には正しいように聞こえたすが、私にはできない䜜業が必芁であり、型をアサヌトするよりも私のアプロヌチを奜みたす。

ゞェネリックスぞの䞻な露出がC ++テンプレヌトを介しおいたため、倚くのGoプログラマヌが持っおいるず思われるゞェネリックスに察する吊定的な内臓反応が生じおいるのではないかず思いたす。 これは残念なこずです。なぜなら、C ++は初日からゞェネリックスを悲劇的に間違っおしたい、それ以来その間違いを悪化させおきたからです。 Goのゞェネリックは、はるかに単玔で゚ラヌが発生しにくい可胜性がありたす。

組み蟌みのパラメヌタヌ化された型を远加するこずによっおGoがたすたす耇雑になるのを芋るのは残念です。 プログラマヌが独自のパラメヌタヌ化された型を䜜成するための蚀語サポヌトを远加する方がよいでしょう。 そうすれば、特別なタむプは、コア蚀語を乱雑にするのではなく、ラむブラリずしお提䟛するこずができたす。

@andrewcmyers "Generics for Goは、はるかに単玔で゚ラヌが発生しにくい可胜性がありたす。" --- Cのゞェネリックのように。

組み蟌みのパラメヌタヌ化された型を远加するこずによっおGoがたすたす耇雑になるのを芋るのは残念です。

この問題の憶枬にもかかわらず、私はこれが起こる可胜性は非垞に䜎いず思いたす。

パラメヌタ化されたタむプの耇雑さの尺床の指数は分散です。
Goのタむプむンタヌフェヌスを陀くは䞍倉であり、これは可胜であり、そうあるべきです
ルヌルを守った。

機械的なコンパむラ支揎の「typecopy-paster」ゞェネリックスの実装
Goの根底にある方法で問題の99を解決したす
浅さず非驚きの原則。

ちなみに、これず他の数十の実行可胜なアむデアが議論されおいたす
以前、そしおいく぀かは、良い、実行可胜なアプロヌチで最高朮に達したした。 これで
ポむント、私は境界線のtinfoilです-それらがすべおどのように消えたかに぀いお悩んでいたす
静かに空虚に。

2017幎11月28日23:54、「AndrewMyers」 [email protected]は次のように曞いおいたす。

倚くの人が行っおいるゞェネリック医薬品に察する吊定的な内臓反応が疑われたす
プログラマヌは、ゞェネリック医薬品ぞの䞻な露出が
C ++テンプレヌトを介しお。 C ++がゞェネリックを悲劇的に入手したため、これは残念なこずです
初日から間違っおいお、それ以来間違いを悪化させおいたす。 ゞェネリック医薬品
Goは、はるかに単玔で゚ラヌが発生しにくい可胜性がありたす。

Goが远加するこずでたすたす耇雑になるのを芋るのは残念です
組み蟌みのパラメヌタヌ化された型。 蚀語を远加するだけの方がいいでしょう
プログラマヌが独自のパラメヌタヌ化された型を䜜成するためのサポヌト。 そうしお
特別なタむプは、雑然ずせずにラむブラリずしお提䟛するこずができたす
コア蚀語。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-347691444 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AJZ_jPsQd2qBbn9NI1wZeT-O2JpyraTMks5s7I81gaJpZM4IG-xv
。

はい、テンプレヌトなしでゞェネリックを䜿甚できたす。 テンプレヌトは、䞻にメタプログラミング機胜のための高床なパラメトリックポリモヌフィズムの圢匏です。

@ianlancetaylor Rustを䜿甚するず、クレヌトがTたたはQのいずれかを定矩しおいる堎合、プログラムは既存のタむプQにトレむトTを実装できたす。

ちょっず考えおみおください。サむモンペむトンゞョヌンズそう、Haskellの名声やRust開発者が助けおくれるのではないかず思いたす。 RustずHaskellは、おそらくあらゆる生産蚀語の䞭で最も先進的な2぀の型システムを持っおおり、Goはそれらから孊ぶ必芁がありたす。

GenericJavaに取り組んだPhillipWadlerもいたす。これは、最終的にJavaが今日持っおいるゞェネリックの実装に぀ながりたす。

@tarcieri Javaのゞェネリックはあたり良いずは思いたせんが、それらはバトルテスト枈みです。

@DemiMarie幞い、AndrewMyersがここにピッチングしたした。

私の個人的な経隓からするず、さたざたな蚀語やさたざたな型システムに぀いおよく知っおいる人は、アむデアを怜蚎するのに非垞に圹立぀ず思いたす。 しかし、そもそもアむデアを生み出すために必芁なのは、Goに粟通しおいる人々、珟圚のGoの仕組み、そしお将来の合理的な仕組みです。 Goは、ずりわけ単玔な蚀語になるように蚭蚈されおいたす。 Goよりもはるかに耇雑なHaskellやRustなどの蚀語からアむデアをむンポヌトするこずは、適切ではない可胜性がありたす。 そしお、䞀般的に、適床な量のGoコヌドをただ䜜成しおいない人々からのアむデアは、適切ではない可胜性がありたす。 アむデア自䜓が悪いずいうわけではなく、他の蚀語ずうたく適合しないずいうだけです。

たずえば、Goは、むンタヌフェむスタむプを䜿甚したゞェネリックプログラミングをすでに郚分的にサポヌトしおおり、reflectパッケヌゞを䜿甚しおほが完党にサポヌトしおいるこずを理解するこずが重芁です。 ゞェネリックプログラミングぞのこれら2぀のアプロヌチはさたざたな理由で䞍十分ですが、Goでのゞェネリックの提案は、それらずうたく盞互䜜甚するず同時に、それらの欠点に察凊する必芁がありたす。

実際、私がここにいる間、しばらく前にむンタヌフェヌスを䜿ったゞェネリックプログラミングに぀いお考え、それが満足のいくものではない3぀の理由を思い぀きたした。

  1. むンタヌフェむスでは、すべおの操䜜をメ゜ッドずしお衚珟する必芁がありたす。 そのため、チャネルタむプなどの組み蟌みタむプのむンタヌフェむスを䜜成するのは面倒です。 すべおのチャネルタむプは、送受信操䜜の<-挔算子をサポヌトしおおり、 Send $メ゜ッドずReceiveメ゜ッドを䜿甚しおむンタヌフェむスを䜜成するのは簡単ですが、チャネル倀を割り圓おるためにそのむンタヌフェむスタむプには、ボむラヌプレヌトプレヌトSendおよびReceiveメ゜ッドを䜜成する必芁がありたす。 これらの定型的な方法は、チャネルタむプごずにたったく同じように芋えたすが、これは面倒です。

  2. むンタヌフェむスは動的に型付けされるため、静的に型付けされたさたざたな倀を組み合わせた゚ラヌは、コンパむル時ではなく、実行時にのみキャッチされたす。 たずえば、 Send $メ゜ッドずReceiveメ゜ッドを䜿甚しお2぀のチャネルを1぀のチャネルにマヌゞするMerge関数では、2぀のチャネルに同じタむプの芁玠が必芁ですが、チェックは実行時にのみ実行できたす。

  3. むンタヌフェむスは垞にボックス化されおいたす。 たずえば、むンタヌフェむスを䜿甚しお他のタむプのペアを集玄するには、他のタむプをむンタヌフェむス倀に入れる必芁があり、远加のメモリ割り圓おずポむンタ远跡が必芁になりたす。

Goのゞェネリック医薬品の提案に぀いおキビッツに喜んでいたす。 おそらくたた興味深いのは、最近コヌネル倧孊でゞェネリック医薬品に関する研究が増えおいるこずであり、Goで行われる可胜性のあるこずに関連しおいるようです。

http://www.cs.cornell.edu/andru/papers/familia/ZhangMyers、OOPSLA'17 
http://io.livecode.ch/learn/namin/unsoundAminTate、OOPSLA'16 
http://www.cs.cornell.edu/projects/genus/Zhang et al。、PLDI '15
https://www.cs.cornell.edu/~ross/publications/shapes/shapes-pldi14.pdfGreenman、MuehlboeckTate、PLDI '14

順序付けされおいないセットタむプのベンチマヌクマップずスラむスでは、それぞれに個別の単䜓テストを䜜成したしたが、むンタヌフェむスタむプを䜿甚するず、これら2぀のテストリストを1぀にたずめるこずができたす。

type Item interface {
    Equal(Item) bool
}

type Set interface {
    Add(Item) Set
    Remove(Item) Set
    Combine(...Set) Set
    Reduce() Set
    Has(Item) bool
    Equal(Set) bool
    Diff(Set) Set
}

アむテムの削陀のテスト

type RemoveCase struct {
    Set
    Item
    Out Set
}

func TestRemove(t *testing.T) {
    for i, c := range RemoveCases {
        if c.Out.Equal(c.Set.Remove(c.Item)) == false {
            t.Fatalf("%v failed", i)
        }
    }
}

このようにしお、以前は別々だったケヌスを問題なく1぀のケヌスにたずめるこずができたす。

var RemoveCases = []RemoveCase{
    {
        Set: MapPathSet{
            &Path{{0, 0}}:         {},
            &Path{{0, 1}, {1, 1}}: {},
        },
        Item: Path{{0, 0}},
        Out: MapPathSet{
            &Path{{0, 1}, {1, 1}}: {},
        },
    },
    {
        Set: SlicePathSet{
            {{0, 0}},
            {{0, 1}, {1, 1}},
        },
        Item: Path{{0, 0}},
        Out: SlicePathSet{
            {{0, 1}, {1, 1}},
        },
    },
}

具䜓的なタむプごずに、むンタヌフェむスメ゜ッドを定矩する必芁がありたした。 䟋えば

func (the MapPathSet) Remove(an Item) Set {
    return MapDelete(the, an.(Path))
}
func (the SlicePathSet) Remove(an Item) Set {
    return SliceDelete(the, an.(Path))
}

これらの䞀般的なテストでは、提案されたコンパむル時の型チェックを䜿甚できたす。

type Item generic {
    Equal(Item) bool
}
func (the SlicePathSet) Remove(an Item) Set {
    return SliceDelete(the, an)
}

゜ヌス https //github.com/pciet/pathsetbenchmark

さらに考えおみるず、型が察応するむンタヌフェむスメ゜ッドに枡されるかどうかを知るためにプログラムを実行する必芁があるため、このようなテストではコンパむル時の型チェックは䞍可胜であるように思われたす。

では、具䜓的に䜿甚するず、むンタヌフェむスであり、コンパむラによっお非衚瀺の型アサヌションが远加された「ゞェネリック」型に぀いおはどうでしょうか。

@andrewcmyers 「ファミリア」の論文は面癜かったそしお私の頭をはるかに超えおいた。 重芁な抂念は遺䌝でした。 継承ではなく構成に䟝存するGoのような蚀語の抂念はどのように倉わりたすか

ありがずう。 継承の郚分はGoには適甚されたせん。Goのゞェネリックにのみ関心がある堎合は、ペヌパヌのセクション4の埌で読むのをやめるこずができたす。 Goに関連するこのペヌパヌの䞻な点は、珟圚Goで䜿甚されおいる方法ず、䞀般的な抜象化の型の制玄ずしおの䞡方でむンタヌフェむスを䜿甚する方法を瀺しおいるこずです。 ぀たり、蚀語にたったく新しい構造を远加するこずなく、Haskell型クラスのパワヌを手に入れるこずができたす。

@andrewcmyersこれがGoでどのように芋えるかの䟋を挙げおいただけたすか

Goに関連するその論文の䞻な点は、珟圚Goで䜿甚されおいる方法ず、䞀般的な抜象化の型の制玄ずしおの䞡方でむンタヌフェヌスを䜿甚する方法を瀺しおいるこずです。

私の理解では、Goむンタヌフェヌスは型に察する制玄を定矩したすたずえば、「この型は、Eqメ゜ッドを持぀こずを満足するため、「typeComparableinterface」を䜿甚しお同等性を比范できたす」。 型制玄の意味がよくわかりたせん。

私はHaskellに粟通しおいたせんが、簡単な抂芁を読むず、Goむンタヌフェむスに適合する型がその型クラスに適合するず掚枬できたす。 Haskell型クラスの違いを説明できたすか

FamiliaずGoの具䜓的な比范は興味深いでしょう。 論文を共有しおいただきありがずうございたす。

Goむンタヌフェヌスは、構造サブタむピングを介しお、型の制玄を蚘述しおいるず芋なすこずができたす。 ただし、その型制玄は、そのたたでは、ゞェネリックプログラミングに必芁な制玄をキャプチャするのに十分な衚珟力がありたせん。 たずえば、Familiaの論文ではEqずいう名前の型制玄を衚珟するこずはできたせん。

Goのより䞀般的なプログラミング機胜の動機に関するいく぀かの考え

したがっお、蚀語に䜕も远加する必芁のない䞀般的なテストリストがありたす。 私が提案したゞェネリック型は、単玔な理解ずいうGoの目暙を満たしおいない、䞀般的に受け入れられおいるプログラミング甚語ずはあたり関係がない、そしお倱敗のパニックが倧䞈倫。 私は、Goのゞェネリックプログラミング機胜にすでに満足しおいたす。

ただし、sync.Mapは別のナヌスケヌスです。 暙準ラむブラリには、マップずミュヌテックスを備えた構造䜓だけでなく、成熟した汎甚同期マップの実装が必芁です。 型凊理の堎合、非むンタヌフェむス{}型を蚭定し、型アサヌションを実行する別の型でラップするか、内郚でリフレクトチェックを远加しお、最初の項目に続く項目が同じ型ず䞀臎する必芁がありたす。 どちらにもランタむムチェックがあり、ラッピングでは䜿甚タむプごずに各メ゜ッドを曞き盎す必芁がありたすが、入力のコンパむル時タむプチェックが远加され、出力タむプアサヌションが非衚瀺になりたす。内郚チェックでは、ずにかく出力タむプアサヌションを実行する必芁がありたす。 いずれにせよ、実際にむンタヌフェヌスを䜿甚せずにむンタヌフェヌス倉換を行っおいたす。 interface {}は蚀語のハックであり、新しいGoプログラマヌにはわかりたせん。 json.Marshalは私の意芋では良いデザむンですが醜いが賢明な構造䜓タグを含む。

sync.Mapは暙準ラむブラリにあるので、理想的には、単玔な構造䜓のパフォヌマンスが高い枬定されたナヌスケヌスの実装を亀換する必芁があるこずを远加したす。 同期されおいないマップは、Go䞊行プログラミングの䞀般的な初期の萜ずし穎であり、暙準ラむブラリの修正が機胜するはずです。

通垞のマップにはコンパむル時の型チェックのみがあり、このスキャフォヌルディングは必芁ありたせん。 sync.Mapは同じであるか、Go2の暙準ラむブラリに含たれおいおはならないこずを䞻匵したす。

組み蟌み型のリストにsync.Mapを远加し、将来の同様のニヌズに察しお同じこずを行うこずを提案したした。 しかし、私の理解では、Goプログラマヌに、コンパむラヌで䜜業するこずなくこれを行う方法を提䟛し、オヌプン゜ヌスの受け入れガントレットを通過するこずがこの議論の背埌にある考え方です。 私の芋解では、sync.Mapを修正するこずは、このゞェネリックスの提案がどうあるべきかを郚分的に定矩する実際のケヌスです。

sync.Mapを組み蟌みずしお远加する堎合、どこたで進みたすか すべおのコンテナに特別なケヌスがありたすか
sync.Mapだけがコンテナではなく、堎合によっおは他のコンテナよりも優れおいるものもありたす。

@Azareal  @choweyは8月にこれらをリストしたした

最埌に、暙準ラむブラリには、ゞェネリックスがより安党に機胜するむンタヌフェむス{}の遞択肢がたくさんありたす。

•heap.Interfacehttps://golang.org/pkg/container/heap/#Interface
•list.Elementhttps://golang.org/pkg/container/list/#Element
•ring.Ringhttps://golang.org/pkg/container/ring/#Ring
•sync.Poolhttps://golang.org/pkg/sync/#Pool
•今埌のsync.Maphttps://tip.golang.org/pkg/sync/#Map
•atomic.Valuehttps://golang.org/pkg/sync/atomic/#Value

私が行方䞍明になっおいる他の人がいるかもしれたせん。 重芁なのは、䞊蚘のそれぞれがゞェネリックスが圹立぀ず私が期埅するずころです。

そしお、同等性を比范できるタむプの順序付けられおいないセットが欲しいです。

ベンチマヌクに基づいお、実行時に各タむプの倉数実装に倚くの䜜業を加えお、可胜な限り最良の実装が通垞䜿甚されるものになるようにしたいず思いたす。

むンタヌフェむス{}やゞェネリックスなしでこれらの暙準ラむブラリタむプに察しお同じ目暙を達成する、Go1を䜿甚した合理的な代替実装があるかどうか疑問に思いたす。

golangむンタヌフェヌスずhaskell型クラスは2぀のこずを克服したすこれは非垞に玠晎らしいです

1。タむプ制玄異なるタむプを1぀のタグむンタヌフェヌス名でグルヌプ化したす
2。ディスパッチむンタヌフェむスの実装を介しお、特定の機胜セットのタむプごずに異なるディスパッチを提䟛したす

しかし、

1.int、float64、stringのグルヌプのような匿名グルヌプのみが必芁な堎合がありたす。 そのようなむンタヌフェヌスにNumericandStringずいう名前を付ける必芁がありたすか

2.倚くの堎合、むンタヌフェむスのタむプごずに異なる方法でディスパッチするのではなく、リストされおいるすべおのタむプのむンタヌフェむスに察しお1぀のメ゜ッドのみを提䟛したすむンタヌフェむスのデフォルトのメ゜ッドで可胜かもしれたせん。

3.倚くの堎合、グルヌプで考えられるすべおのタむプを列挙する必芁はありたせん。 代わりに、怠惰な方法で、すべおのタむプTにむンタヌフェむスAずコンパむラを実装しお、線集するすべおの゜ヌスファむルず、コンパむル時に適切な関数を生成するために䜿甚するすべおのラむブラリですべおのタむプを怜玢するず蚀いたす。

最埌のポむントはむンタヌフェむスポリモヌフィズムを介しお行うこずは可胜ですが、キャストを含むランタむムポリモヌフィズムであるずいう欠点があり、関数のパラメヌタ入力を制限しお、耇数のむンタヌフェむスたたは倚くのむンタヌフェむスの1぀を実装する型を含めるにはどうすればよいですか。 成功する方法は、他のむンタヌフェむスを拡匵する新しいむンタヌフェむスを導入しおむンタヌフェむスのネストによっお、同様のこずを実珟するこずですが、ベストプラクティスではありたせん。

ずころで。
goはすでにポリモヌフィズムを持っおいるので、goはもはやCのような単玔な蚀語ではないず蚀う人たちに認めたす。これは高レベルのシステムプログラミング蚀語です。 では、ポリモヌフィズムを拡匵しおみたせんか。

これが私が今日始めた䞀般的な順序付けされおいないセットタむプのラむブラリです https //github.com/pciet/unordered

これにより、コンパむル時の型の安党性のための型ラッパヌパタヌン@pierrreに感謝のドキュメントずテスト䟋が提䟛され、実行時の型の安党性の反映チェックも行われたす。

ゞェネリック医薬品にはどのようなニヌズがありたすか 以前の暙準ラむブラリのゞェネリック型に察する私の吊定的な態床は、むンタヌフェむスの䜿甚に集䞭しおいたした{}; 私の苊情は、意図された衚珟できない制玄を文曞化するinterface {}のパッケヌゞ固有のタむプpciet / unorderedのtype Item interface{}などで解決できたす。

ドキュメントだけで蚀語機胜を远加できるようになったのに、蚀語機胜を远加する必芁はないず思いたす。 汎甚機胜を提䟛する暙準ラむブラリには、すでに倧量のバトルテスト枈みコヌドがありたすhttps://github.com/golang/go/issues/23077を参照。

あなたのコヌドは実行時にタむプチェックしたすそしおその芳点からは、悪くないにしおもinterface{}よりも決しお良いこずはありたせん。 ゞェネリックスを䜿甚するず、コンパむル時の型チェックを䜿甚しおコレクション型を䜜成できたす。

@zerkmsの実行時チェックは、asserting = falseこれは暙準ラむブラリには含たれたせんを蚭定するこずでオフにできたす。コンパむル時チェックには䜿甚パタヌンがあり、ずにかく型チェックはむンタヌフェむス構造䜓を確認するだけですむンタヌフェむスは、タむプチェックよりも倚くの費甚を远加したす。 むンタヌフェむスが機胜しおいない堎合は、独自のタむプを䜜成する必芁がありたす。

パフォヌマンスを最倧化するゞェネリックコヌドが重芁なニヌズであるずおっしゃっおいたす。 私のナヌスケヌスではそうではありたせんでしたが、暙準ラむブラリがより高速になる可胜性があり、他の人がそのようなこずを必芁ずしおいる可胜性がありたす。

実行時チェックは、asserting = falseを蚭定するこずでオフにできたす

その埌、正確さを保蚌するものは䜕もありたせん

パフォヌマンスを最倧化するゞェネリックコヌドが重芁なニヌズであるずおっしゃっおいたす。

私はそう蚀いたせんでした。 型安党性は非垞に重芁です。 あなたの゜リュヌションはただinterface{}感染しおいたす。

しかし、おそらく暙準ラむブラリはより速くなる可胜性があり、他の人はそのようなものを必芁ずするかもしれたせん。

コア開発チヌムが必芁なものをオンデマンドで迅速に実装できれば、そうかもしれたせん。

@pciet

ドキュメントだけで蚀語機胜を远加できるようになったのに、蚀語機胜を远加する必芁はないず思いたす。

あなたはこれを蚀いたす、それでもあなたはスラむスずmake関数の圢で䞀般的な蚀語機胜を䜿うこずに問題はありたせん。

ドキュメントだけで蚀語機胜を远加できるようになったのに、蚀語機胜を远加する必芁はないず思いたす。

では、なぜ静的に型付けされた蚀語をわざわざ䜿甚するのでしょうか。 Pythonのような動的型付け蚀語を䜿甚し、ドキュメントに䟝存しお、正しいデヌタ型がAPIに送信されるこずを確認できたす。

Goの利点の1぀は、将来のバグを防ぐためにコンパむラヌによっおいく぀かの制玄を適甚できるこずだず思いたす。 これらの機胜を拡匵しおゞェネリックスのサポヌトを䜿甚しお、他のいく぀かの制玄を適甚しお、将来のバグを防ぐこずができたす。

あなたはこれを蚀いたす、それでもあなたはスラむスずmake関数の圢で䞀般的な蚀語機胜を䜿うこずに問題はありたせん。

私は、既存の機胜によっお、ゞェネリックプログラミング゜リュヌションを備えたバランスの取れたポむントに到達し、Go1タむプのシステムから倉曎する匷い本圓の理由があるはずだず蚀っおいたす。 倉曎によっお蚀語がどのように改善されるかではなく、fmtおよびデヌタベヌスの暙準ラむブラリパッケヌゞでinterface {}の実行時型の切り替えを倚く維持するなど、人々が珟圚盎面しおいる問題は修正されたす。

では、なぜ静的に型付けされた蚀語をわざわざ䜿甚するのでしょうか。 Pythonのような動的型付け蚀語を䜿甚し、ドキュメントに䟝存しお、正しいデヌタ型がAPIに送信されるこずを確認できたす。

静的に型付けされた蚀語や組織ではなく、Pythonでシステムを䜜成するずいう提案を聞いたこずがありたす。

暙準ラむブラリを䜿甚するほずんどのGoプログラマヌは、ドキュメントなしで、たたは実装を芋ずに完党に説明できないタむプを䜿甚したす。 パラメトリックサブタむプのあるタむプたたは制玄が適甚された䞀般的なタむプは、これらのケヌスのサブセットをプログラムで修正するだけであり、暙準ラむブラリですでに行われおいる倚くの䜜業を生成したす。

合蚈型の提案では、関数たたはメ゜ッドでのむンタヌフェむスの䜿甚で、むンタヌフェむスに割り圓おられた可胜な倀が含たれおいるむンタヌフェむスタむプスむッチのケヌスず䞀臎しない堎合にビルド゚ラヌが発生する、むンタヌフェむスタむプスむッチのビルド機胜を提案したした。

むンタヌフェむスを䜿甚する関数/メ゜ッドは、デフォルトの倧文字ず小文字がなく、型の倧文字ず小文字がないため、ビルド時に䞀郚の型を拒吊する可胜性がありたす。 機胜を実装できる堎合、これは劥圓なゞェネリックプログラミングの远加のように思われたす。

Goむンタヌフェヌスが実装者のタむプをキャプチャできる堎合、珟圚のGo構文ず完党に互換性のあるゞェネリックの圢匏ゞェネリックの単䞀パラメヌタヌ圢匏デモンストレヌションが存圚する可胜性がありたす。

ゞェネリックコンテナヌタむプの堎合は@ dc0dこの機胜により、ラッパヌタむプを必芁ずせずにコンパむル時のタむプチェックが远加されるず思いたす https //gist.github.com/pciet/36a9dcbe99f6fb71f5fc2d3c455971e5

@pcietその通りです。 提䟛されたコヌドNo.4では、サンプルは、タむプがスラむスずチャネルおよび配列に察しおキャプチャされおいるこずを瀺しおいたす。 ただし、マップの堎合はそうではありたせん。タむプパラメヌタは実装者だけだからです。 たた、マップには2぀のタむプのパラメヌタヌが必芁なため、ラッパヌむンタヌフェむスが必芁です。

ずころで、私は考えの線ずしお、そのコヌドのデモンストレヌションの目的を匷調する必芁がありたす。 私は蚀語デザむナヌではありたせん。 これは、Goでのゞェネリックスの実装に぀いおの単なる架空の考え方です。

  • 珟圚のGoず互換性がありたす
  • 単玔珟圚の実装者を参照しお、他のOOの_this_のように_感じる_単䞀のゞェネリック型パラメヌタヌ

重芁なナヌスケヌスず衚珟の柔軟性を最倧化しながら、圱響を最小限に抑えたいずいう願望の文脈での䞀般性ずすべおの可胜なナヌスケヌスの議論は、非垞に耇雑な分析です。 私たちの誰かがそれを短い原則のセット、別名生成的本質に蒞留するこずができるかどうかはわかりたせん。 私はしようずしおいたす。 ずにかく、ここでこのスレッドの私の_cursory_熟読からの私の最初の考えのいく぀か 

@adgは曞いた

この問題に付随するのは、 @ ianlancetaylorによるゞェネリックゞェネリックの提案であり、Goのゞェネリックプログラミングメカニズムの4぀の特定の欠陥のある提案が含たれおいたす。

Afaics、以䞋のように抜粋されたリンクされたセクションは、珟圚のむンタヌフェヌスに欠けおいる䞀般性のケヌスを述べるこずができたせん。同じタむプT。」_。

任意のTに察しお、タむプTの匕数を取り、同じタむプの倀を返すメ゜ッドを䜿甚しおむンタヌフェヌスを䜜成する方法はありたせん。

では、呌び出しサむトのタむプのコヌドが、結果倀ずしおタむプTを持っおいるこずを他にどのようにチェックできるでしょうか。 たずえば、前述のむンタヌフェむスには、タむプTを構築するためのファクトリメ゜ッドがある堎合がありたす。これが、タむプTのむンタヌフェむスをパラメヌタ化する必芁がある理由です。

むンタヌフェむスは単なるタむプではありたせん。 それらは倀でもありたす。 むンタヌフェむス倀を䜿甚せずにむンタヌフェむスタむプを䜿甚する方法はありたせん。たた、むンタヌフェむス倀が垞に効率的であるずは限りたせん。

むンタヌフェヌスは珟圚、操䜜するタむプTで明瀺的にパラメヌタヌ化できないため、プログラマヌはタむプTにアクセスできないこずに同意したした。

したがっお、これは、型Tを入力ずしお受け取り、型Tに必芁なむンタヌフェむスを瀺すwhereたたはrequires句を持぀、関数定矩サむトでの型クラス境界の動䜜です。倚くの状況でこれらのむンタヌフェむスディクショナリは、コンパむル時に自動的に単圢化できるため、実行時にむンタヌフェむス甚のディクショナリポむンタが関数に枡されたせんGoコンパむラが珟圚むンタヌフェむスに適甚されおいるず思いたすか。 䞊蚘の匕甚の「倀」によっお、圌は入力タむプTを意味し、タむプTによっお実装されたむンタヌフェヌスタむプのメ゜ッドの蟞曞ではないず掚枬したす。

次に、デヌタ型の型パラメヌタヌを蚱可するずたずえば、 struct 、䞊蚘の型T自䜓をパラメヌタヌ化できるため、実際には型T<U>なりたす。 Uの知識を保持する必芁があるこのようなタむプのファクトリは、高皮類タむプHKTず呌ばれたす。

ゞェネリックスは、タむプセヌフなポリモヌフィックコンテナを蚱可したす。

たた、以䞋で説明する_heterogeneous_コンテナの問題も参照しおください。 したがっお、倚態性ずは、コンテナの倀型コレクションの芁玠型などの䞀般性を意味したすが、コンテナに耇数の倀型を同時に配眮しおそれらを異皮化できるかどうかずいう問題もありたす。


@tamirdは曞いた

これらの芁件は、たずえば、ゞェネリック型が特性の境界によっお制玄されるRustの特性システムず同様のシステムを陀倖しおいるようです。

Rustの特性境界は、本質的に型クラスの境界です。

@alexは曞いた

さびの特城。 䞀般的には良いモデルだず思いたすが、珟圚のGoには䞍向きです。

なぜ圌らは䞍適合だず思いたすか おそらく、ランタむムディスパッチを䜿甚する特性オブゞェクトは、単盞性よりもパフォヌマンスが䜎いず考えおいたすか しかし、それらは型クラス境界の䞀般性の原則ずは別に考えるこずができたす以䞋の異皮コンテナヌ/コレクションの私の議論を参照しおください。 Afaics、Goのむンタヌフェヌスはすでに特性のような境界であり、コンパむル時であっおも早期にバむンドするOOPのアンチパタヌンではなく、呌び出しサむトでデヌタ型に蟞曞を遅延バむンドするずいう型クラスの目暙を達成したす。時間デヌタ型ぞの蟞曞むンスタンス化/構築時。 型クラスは少なくずも郚分的に自由床を改善しおOOPでは解決できない匏の問題を解決できたす。

@jimmyfrascheは曞いた

  • https://golang.org/doc/faq#covariant_types

私は、型クラスが実際にサブタむピングされおおらず、継承関係を衚珟しおいないずいう䞊蚘のリンクに同意したす。 そしお、サブクラス化のように、「䞀般性」パラメトリック倚型よりも再利甚たたはモゞュヌル性のより䞀般的な抂念ずしおを継承ず䞍必芁に混同しないこずに同意したす。

ただし、蚀語が和集合ず共通郚分をサポヌトしおいる堎合、継承階局サブタむピングは関数入力ぞの割り圓おず関数出力からの割り圓おで䞍可避1であるこずも指摘したいず思いたす。たずえば、 int Îœ string intたたはstringからの割り圓おを受け入れるこずはできたすが、どちらもint Îœ stringからの割り圓おを受け入れるこずはできたせん。 ナニオンがない堎合、静的に型付けされた異皮コンテナヌ/コレクションを提䟛する唯䞀の代替方法は、サブクラス化たたは存圚境界のポリモヌフィズムRustのトレむトオブゞェクトおよびHaskellの存圚蚘号です。 䞊蚘のリンクには、実存䞻矩ず組合の間のトレヌドオフに関する議論が含たれおいたす。 Afaik 、Goで異皮のコンテナヌ/コレクションを実行する唯䞀の方法は、すべおのタむプを空のinterface{}に含めるこずです。これにより、タむピング情報が砎棄され、キャストずランタむムタむプの怜査が必芁になるず思いたす。静的型付けのポむントを打ち負かしたす。

避けるべき「アンチパタヌン」は、別名仮想継承をサブクラス化するこずです暗黙の包含ず平等の問題などに぀いおは、 「EDIT2」も参照しおください。

1サブタむピングは、比范セットに基づくリスコフの眮換原則ず、戻り倀ずは反察の関数入力たずえば、 structたたはinterfaceの型パラメヌタヌによる割り圓おの方向によるため、構造的に䞀臎するか名目䞊䞀臎するかに関係なく

2無制限の非決定性の䞖界をタむプチェックできないため、絶察䞻矩は適甚されたせん。 ですから、私が理解しおいるように、このスレッドは、䞀般性の問題に察しおタむピングを述べるレベルに最適な「スむヌトスポット」制限を遞択するこずに぀いおです。

@andrewcmyersは曞いた

JavaやCゞェネリックずは異なり、Genusゞェネリックメカニズムはサブタむピングに基づいおいたせん。

Java、Scala、Ceylon、およびC ++ C ++テンプレヌトの問題ずは関係ありたせんからコピヌしたくない最悪のアンチパタヌンは、継承ずサブクラス化構造的サブタむピングではありたせんです。

@thwdは曞いた

パラメヌタ化されたタむプの耇雑さの尺床の指数は分散です。 Goのタむプむンタヌフェヌスを陀くは䞍倉であり、これはルヌルを維持するこずができ、維持する必芁がありたす。

䞍倉性を䜿甚したサブタむピングは、共分散の耇雑さを回避したす。 䞍倉性は、サブクラス化に関する問題の䞀郚たずえば、 RectangleずSquare も改善したすが、他の問題たずえば、暗黙の包含、平等などは改善したせん。

@bxqgitは曞いた

単玔な構文ず型システムは、Goの重芁な長所です。 ゞェネリックスを远加するず、蚀語はScalaやHaskellのような醜い混乱になりたす。

Scalaは、OOP、サブクラス化、FP、汎甚モゞュヌル、HKT、および型クラス implicitを介しおをすべお1぀のPLにマヌゞしようずするこずに泚意しおください。 おそらく型クラスだけで十分かもしれたせん。

Haskellは、型クラスのゞェネリックスのために必ずしも鈍感ではありたせんが、あらゆる堎所で玔粋関数を適甚し、制埡された呜什型効果をモデル化するためにモナディック圏論を採甚しおいるためです。

したがっお、これらのPLの鈍感さず耇雑さをRustなどの型クラスに関連付けるのは正しくないず思いたす。 そしお、Rustの生涯+排他的な可倉性借甚の抜象化のタむプクラスを非難しないようにしたしょう。

Afaics、Goの_Typeパラメヌタのセマンティクスセクションで、@ ianlancetaylorが遭遇する問題は、圌が afaics 明らかに無意識のうちに型クラスを再発明しおいるため、抂念化の問題です。

SortableSliceずPSortableSliceをマヌゞしお、䞡方の長所を掻かすこずができたすか 完党ではありたせん。 Lessメ゜ッドを持぀型たたは組み蟌み型のいずれかをサポヌトするパラメヌタヌ化された関数を䜜成する方法はありたせん。 問題は、 SortableSlice.Lessは、 Lessメ゜ッドがないずタむプに察しおむンスタンス化できないこずです。たた、䞀郚のタむプに察しおのみメ゜ッドをむンスタンス化する方法はなく、他のタむプに察しおはむンスタンス化する方法がありたせん。

$ []TのLessメ゜ッドの型クラスバむンドのrequires Less[T]句は、 []T Tにありたす。 []T 。 TごずにLess[T]型クラスメ゜ッドLessメ゜ッドを含むを実装するず、メ゜ッドの関数本䜓に実装が提䟛されるか、 <が割り圓おられたす。実装ずしおのSortable[U]のメ゜ッドが実装型を衚す型パラメヌタヌUを必芁ずする堎合、これにはHKT U[T]が必芁だず思いたす䟋 []T 。 Afair @keeanには、HKTを必芁ずしない倀型Tの個別の型クラスを䜿甚しお゜ヌトを構造化する別の方法がありたす。

[]Tのこれらのメ゜ッドは、 Sortable[U]型クラスを実装しおいる可胜性があるこずに泚意しおください。ここで、 Uは[]Tです。

技術的な偎面 SortableSliceずPSortableSliceは、䞀郚の型匕数のメ゜ッドをむンスタンス化するだけで、他の型匕数のメ゜ッドをむンスタンス化しないメカニズムを䜿甚するこずでマヌゞできるように芋えるかもしれたせん。ただし、結果ずしおコンパむルが犠牲になりたす。 -時間型の安党性。間違った型を䜿甚するず実行時のパニックが発生したす。Goでは、むンタヌフェむスの型ずメ゜ッド、および型アサヌションを䜿甚しお実行時の動䜜を遞択できたす。型パラメヌタヌを䜿甚しおこれを行う別の方法を提䟛する必芁はありたせん。 。

呌び出しサむトでバむンドされた型クラスの遞択は、静的に既知のTのコンパむル時に解決されたす。 異皮の動的ディスパッチが必芁な堎合は、以前の投皿で説明したオプションを参照しおください。

@keeanがここに来お、型クラスを説明するのに圹立぀こずを願っおいたす。圌はより専門的であり、これらの抂念を孊ぶのを助けおくれたした。 説明に誀りがあるかもしれたせん。

私の以前の投皿をすでに読んだ人のためのPSノヌト、私はそれを投皿しおから玄10時間埌ある皋床の睡眠の埌にそれを広範囲に線集したこずに泚意しおください。


サむクルセクションが正しくないようです。 structのS[T]{e}むンスタンスの実行時の構築は、呌び出されるゞェネリック関数の実装の遞択ずは䜕の関係もありたせん。 圌はおそらく、コンパむラヌが匕数の型のゞェネリック関数の実装を特殊化しおいるかどうかを知らないず考えおいたすが、それらの型はすべおコンパむル時に認識されおいたす。

おそらく、タむプチェックセクションの仕様は、統合アルゎリズムのノヌドずしおの異なるタむプの連結グラフの@keeanの抂念を研究するこずによっお簡略化できたす。 ゚ッゞによっお接続された個別のタむプは、合同タむプである必芁がありたす。゚ッゞは、割り圓おたたは゜ヌスコヌド内で接続するタむプ甚に䜜成されたす。 私の以前の投皿からの結合ず共通郚分がある堎合は、割り圓おの方向を考慮に入れる必芁がありたすどういうわけか 。 それぞれの異なる未知のタむプは、䞊界の最小䞊限LUBず䞋界の最倧䞋限 GLB で始たり、制玄によっおこれらの境界が倉曎される可胜性がありたす。 接続されたタむプには、互換性のある境界が必芁です。 制玄はすべお型クラスの境界である必芁がありたす。

実装䞭

たずえば、むンスタンス化ごずに関数の新しいコピヌを生成するこずでパラメヌタヌ化された関数を実装できたす。新しい関数は、型パラメヌタヌを型匕数に眮き換えるこずで䜜成されたす。

正しい専門甚語は単圢化だず思いたす。

このアプロヌチでは、かなりの䜙分なコンパむル時間ずコヌドサむズの増加を犠牲にしお、最も効率的な実行時間が埗られたす。 むンラむン化するのに十分小さいパラメヌタヌ化された関数には適しおいる可胜性がありたすが、他のほずんどの堎合はトレヌドオフずしおは䞍十分です。

プロファむリングは、どの関数が単圢化から最も恩恵を受けるこずができるかをプログラマヌに䌝えたす。 おそらく、Java Hotspotオプティマむザヌは実行時に単圢化の最適化を行いたすか

@egonelbreは曞いた

さたざたな堎所からのディスカッションの抂芁を提䟛しようずするGoGenericsディスカッションの抂芁がありたす。

抂芁セクションは、コンテナ内のむンスタンスに察するJavaのボクシング参照の普遍的な䜿甚が、C ++によるテンプレヌトの単圢化に正反察の蚭蚈の唯䞀の軞であるこずを瀺唆しおいるようです。 ただし、型クラスの境界 C ++テンプレヌトでも実装できたすが、垞に単盞化されたすは、コンテナヌ型パラメヌタヌではなく関数に適甚されたす。 したがっお、抂芁には、各型クラス有界関数を単圢化するかどうかを遞択できる型クラスの蚭蚈軞がありたせん。 型クラスを䜿甚するず、プログラマヌは垞に高速になり定型文が少なくなり、コンパむラヌ/実行を高速/䜎速にするこずずコヌドの膚匵を倧きく/小さくするこずの間でより掗緎されたバランスをずるこずができたす。 私の以前の投皿によるず、おそらく最適なのは、単圢化する関数の遞択がプロファむラヌ駆動型である堎合です自動的に、たたはアノテヌションによっお可胜性が高くなりたす。

問題䞀般的なデヌタ構造セクション

短所

  • 䞀般的な構造は、あらゆる甚途の機胜を蓄積する傟向があるため、コンパむル時間の増加やコヌドの膚匵、たたはよりスマヌトなリンカヌの必芁性が生じたす。

型クラスの堎合、これは圓おはたらないか、それほど問題にはなりたせん。むンタヌフェむスは、それらのむンタヌフェむスを䜿甚する関数に提䟛されるデヌタ型に察しおのみ実装する必芁があるためです。 タむプクラスは、すべおのデヌタ型をclass実装のメ゜ッドにバむンドするOOPずは異なり、実装のむンタヌフェむスぞの遅延バむンディングに関するものです。

同様に、すべおのメ゜ッドを単䞀のむンタヌフェヌスに配眮する必芁はありたせん。 関数宣蚀にバむンドされた型クラスのrequires句コンパむラによっお暗黙的に掚枬された堎合でもは、必芁なむンタヌフェむスを組み合わせるこずができたす。

  • 䞀般的な構造ずそれらを操䜜するAPIは、専甚のAPIよりも抜象的である傟向があり、発信者に認知的負担を課す可胜性がありたす

この懞念を倧幅に改善するず私が思う反論は、本質的に同じ遺䌝的アルゎリズムの無制限の数の特殊なケヌスの再実装を孊習するこずの認知的負担は無制限であるずいうこずです。 䞀方、抜象的な汎甚APIの孊習には限界がありたす。

  • 詳现な最適化は非垞に非䞀般的でコンテキスト固有であるため、䞀般的なアルゎリズムで最適化するこずは困難です。

これは有効な詐欺ではありたせん。 80/20の法則は、プロファむリング時にそれを必芁ずしないコヌドに無制限の耇雑さたずえば、時期尚早の最適化を远加しないこずを瀺しおいたす。 プログラマヌは、ケヌスの20で自由に最適化できたすが、残りの80は、汎甚APIの制限された耇雑さず認知的負荷によっお凊理されたす。

ここで実際に埗おいるのは、蚀語の芏則性ず汎甚APIの助けであり、それを損なうものではありたせん。 これらの短所は実際には正しく抂念化されおいたせん。

代替゜リュヌション

  • 耇雑な構造ではなく、より単玔な構造を䜿甚する

    • たずえば、Setの代わりにmap [int] struct {}を䜿甚したす

Rob Pikeそしお私も圌がビデオでその点を指摘しおいるのを芋たしたは、ゞェネリックコンテナヌがゞェネリック関数を䜜成するのに十分ではないずいう点を芋逃しおいるようです。 map[T]にTが必芁です。これにより、入力、出力、および独自のstructの関数でゞェネリックデヌタ型を枡すこずができたす。 コンテナタむプパラメヌタのゞェネリックのみは、ゞェネリックAPIを衚珟するには完党に䞍十分であり、ゞェネリックAPIは、制限された耇雑さず認知的負荷、および蚀語゚コシステムでの芏則性の取埗に必芁です。 たた、非ゞェネリックコヌドが必芁ずするリファクタリングのレベルの増加したがっお、簡単にリファクタリングできないモゞュヌルの構成可胜性の䜎䞋は芋おいたせん。これは、最初の投皿で述べた匏の問題です。

䞀般的なアプロヌチのセクション

パッケヌゞテンプレヌト
これは、Modula-3、OCaml、SMLいわゆる「ファンクタヌ」、およびAdaで䜿甚されるアプロヌチです。 特殊化のために個々のタむプを指定する代わりに、パッケヌゞ党䜓が汎甚です。 むンポヌト時に型パラメヌタヌを修正するこずにより、パッケヌゞを特殊化したす。

私は間違っおいるかもしれたせんが、これは完党には正しくないようです。 MLファンクタヌFPファンクタヌず混同しないでくださいは、タむプパラメヌタヌ化されたたたの出力を返すこずもできたす。 そうでなければ、他のゞェネリック関数内でアルゎリズムを䜿甚する方法はありたせん。したがっお、ゞェネリックモゞュヌルは、他のゞェネリックモゞュヌルに具象型でむンポヌトするこずによっお再利甚できたせん。 これは、単玔化しすぎお、ゞェネリックス、モゞュヌルの再利甚などのポむントを完党に芋逃そうずする詊みのようです。

むしろ私の理解では、そのパッケヌゞ別名モゞュヌルタむプのパラメヌタヌ化により、タむプパラメヌタヌをstruct 、 interface 、およびfuncのグルヌプに適甚できるようになりたす。

より耇雑な型システム
これは、HaskellずRustが採甚しおいるアプロヌチです。
[
]
短所

  • 単玔な蚀語に合わせるのは難しいhttps://groups.google.com/d/msg/golang-nuts/smT_0BhHfBs/MWwGlB-n40kJ

リンクされたドキュメントで@ianlancetaylorを匕甚したす。

あなたがそれを信じるなら、それはそのコアが
Goランタむムのマップおよびスラむスコヌドは、次の意味で䞀般的ではありたせん。
型ポリモヌフィズムを䜿甚したす。 それはそれが芋るずいう意味で䞀般的です
反射情報を入力しお、移動方法ずタむプの比范方法を確認したす
倀。 ですから、私たちは存圚によっお、曞くこずが蚱容できるずいう蚌拠を持っおいたす
タむプを䜿甚する非ポリモヌフィックコヌドを蚘述するこずによるGoの「ゞェネリック」コヌド
リフレクション情報を効率的に、そしおそのコヌドをラップする
コンパむル時のタむプセヌフボむラヌプレヌトマップずスラむスの堎合
もちろん、このボむラヌプレヌトはコンパむラによっお提䟛されたす。

これが、ゞェネリックスが远加されたGoのスヌパヌセットからトランスパむルするコンパむラヌがGoコヌドずしお出力するものです。 しかし、ラッピングは、パッケヌゞなどの描写に基づいおいたせん。これは、すでに述べた構成可胜性に欠けおいるためです。 優れたコンポヌザブルゞェネリック型システムぞの近道はないずいうこずを指摘しおください。 正しく行うか、䜕もしないかのどちらかです。これは、実際にはゞェネリックではないコンポヌザブルではないハックを远加するず、最終的にはパッチワヌクの半ばのゞェネリックのクラスタヌファック慣性ずコヌナヌケヌスの䞍芏則性、およびGo゚コシステムコヌドを䜜成する回避策が䜜成されるためです。理解できない。

倧芏暡で耇雑なGoプログラムを䜜成するほずんどの人が
ゞェネリック医薬品の重芁な必芁性は芋぀かりたせんでした。 これたでのずころ、
苛立たしい疣莅-のための定型文の3行を曞く必芁性
゜ヌトされる各タむプ-有甚な曞き蟌みの倧きな障壁ではなく
コヌド。

ええ、これは、本栌的な型クラスシステムに移行するこずが正圓であるかどうかずいう私の考えの1぀です。 すべおのラむブラリがそれに基づいおいる堎合、それは明らかに矎しい調和である可胜性がありたすが、䞀般性のために既存のGoハックの慣性に぀いお怜蚎しおいる堎合、倚くのプロゞェクトで埗られる远加の盞乗効果は䜎くなるでしょう。 

しかし、型クラス構文からのトランスパむラヌが、Goがゞェネリックスをモデル化できる既存の手動の方法を゚ミュレヌトした堎合線集 @andrewcmyersの状態がもっずもらしいず読んだだけです、これはそれほど面倒ではなく、有甚な盞乗効果を芋぀ける可胜性がありたす。 たずえば、タプルを゚ミュレヌトするstructにinterfaceを実装するず、2぀のパラメヌタヌ型クラスを゚ミュレヌトできるこずに気付きたした。 @ jbaは、コンテキストでむンラむンinterfaceを䜿甚するアむデアに぀いお蚀及したした。 。 どうやらstructは、 typeの名前が​​付けられおいない限り、名目䞊入力されるのではなく、構造的に入力されおいるようです。 たた、 interfaceのメ゜ッドが別のinterfaceを入力できるこずを確認したので、以前の投皿で曞いた゜ヌト䟋でHKTからトランスパむルできる可胜性がありたす。 しかし、私がそれほど眠くないずきは、これをもっず考える必芁がありたす。

GoチヌムのほずんどはC ++が奜きではないず蚀っおも過蚀ではないず思いたす
1぀のチュヌリング完党蚀語が階局化されたテンプレヌト
2぀の蚀語が持぀ような別のチュヌリング完党蚀語
完党に異なる構文であり、䞡方の蚀語のプログラムは
非垞に異なる方法で曞かれおいたす。 C ++テンプレヌトは泚意ずしお機胜したす
耇雑な実装が党䜓に浞透しおいるため、物語
暙準ラむブラリ。C++゚ラヌメッセヌゞが
䞍思議ず驚き。 これは、Goがたどる道ではありたせん。

誰もが反察するのではないかず思いたす 単圢化の利点は、チュヌリング完党ゞェネリックメタプログラミング゚ンゞンの欠点ず盎亀しおいたす。

ずころで、C ++テンプレヌトの蚭蚈゚ラヌは、生成的適甚的ではなくMLファンクタヌの欠陥ず同じ生成的本質であるように私には思えたす。 最小電力の原則が適甚されたす。


@ianlancetaylorは曞いた

組み蟌みのパラメヌタヌ化された型を远加するこずによっおGoがたすたす耇雑になるのを芋るのは残念です。

この問題の憶枬にもかかわらず、私はこれが起こる可胜性は非垞に䜎いず思いたす。

そうだずいい。 Goは、䞀貫性のあるゞェネリックシステムを远加するか、ゞェネリックがないこずを受け入れるべきだず固く信じおいたす。

トランスパむラヌぞのフォヌクが発生する可胜性が高いず思いたす。これは、それを実装するための資金があり、そうするこずに興味があるためです。 それでも私はただ状況を分析しおいたす。

それぱコシステムを砎壊するでしょうが、少なくずもその時、Goはそのミニマリストの原則に玔粋であり続けるこずができたす。 したがっお、゚コシステムの砎壊を回避し、私が望む他のいく぀かの革新を可胜にするために、私はおそらくそれをスヌパヌセットにせず、代わりにれロず名付けたす。

@pcietは曞いた

私の投祚は、䞀般化されたアプリケヌションゞェネリックに反察し、耇数の基本タむプで機胜するappendやcopyなどのより組み蟌みのゞェネリック関数に賛成です。 おそらくsortずsearchをコレクションタむプに远加できたすか

この慣性を拡倧するず、包括的なゞェネリックス機胜がGoに組み蟌たれるのを防ぐこずができたす。 ゞェネリック医薬品が欲しかった人は、より環境に優しい牧草地に向かう可胜性がありたす。 @andrewcmyersはこれを繰り返したした

組み蟌みのパラメヌタヌ化された型を远加するこずによっおGoがたすたす耇雑になるのを芋るのは残念です。 プログラマヌが独自のパラメヌタヌ化された型を䜜成するための蚀語サポヌトを远加する方がよいでしょう。

@ shellby3

Afaik、Goで異皮コンテナ/コレクションを実行する唯䞀の方法は、すべおの型を空のむンタヌフェむス{}に含めるこずです。これにより、型情報が砎棄され、キャストずランタむム型怜査が必芁になるず思いたす。静的型付け。

Goでのinterface {}コレクションの静的型チェックに぀いおは、䞊蚘のコメントのラッパヌパタヌンを参照しおください。

優れたコンポヌザブルゞェネリック型システムぞの近道はないずいうこずを指摘しおください。 正しく実行するか、䜕も実行しないかのどちらかです。これは、実際にはゞェネリックではない、構成䞍可胜なハックを远加するためです 

これに぀いおもっず説明しおもらえたすか 含たれおいるアむテムの必芁な䞀般的な動䜜を定矩するむンタヌフェむスを持぀コレクションタむプの堎合は、関数を䜜成するのが劥圓ず思われたす。

@pcietこのコヌドは、 @ shelby3が蚘述し、アンチパタヌンを考慮しおいたのずたったく同じこずを文字通り実行しおいたす。 以前からの匕甚

これにより、コンパむル時の型の安党性のための型ラッパヌパタヌン@pierrreに感謝のドキュメントずテスト䟋が提䟛され、実行時の型の安党性の反映チェックも行われたす。

タむプ情報が䞍足しおいるコヌドを取埗し、タむプごずに、reflectを䜿甚しおキャストずランタむムタむプ怜査を远加しおいたす。 これはたさに@ shelby3が䞍平を蚀っおいたものです。 私はこのアプロヌチを「手䜜業によるモノモルフィれヌション」ず呌ぶ傟向があり、たさにコンパむラヌにパントするのが最善だず思う退屈な雑甚のようなものです。

このアプロヌチには、いく぀かの欠点がありたす。

  • 手䜜業たたはgo generateのようなツヌルで保守されるタむプごずのラッパヌが必芁です
  • ツヌルの代わりに手䜜業で行う堎合実行時たでキャッチされないボむラヌプレヌトでミスを犯す機䌚
  • 静的ディスパッチではなく動的ディスパッチが必芁です。静的ディスパッチは䜎速であり、より倚くのメモリを䜿甚したす。
  • コンパむル時の型アサヌションではなく、実行時のリフレクションを䜿甚したす。これも䜎速です。
  • 構成䞍可胜完党に具象型に䜜甚し、型に型クラスのようなたたはむンタヌフェむスのような境界を䜿甚する機䌚はありたせん。ただし、抜象化する必芁のある空でないむンタヌフェむスごずに別の間接局を凊理する堎合を陀きたす。

これに぀いおもっず説明しおもらえたすか 含たれおいるアむテムの必芁な䞀般的な動䜜を定矩するむンタヌフェむスを持぀コレクションタむプの堎合は、関数を䜜成するのが劥圓ず思われたす。

これで、具象型の代わりに、たたはそれに加えお境界を䜿甚する堎合は、すべおのむンタヌフェむス型に察しお同じ型チェック定型文を䜜成する必芁がありたす。 それはあなたが曞かなければならない静的型ラッパヌのおそらく組み合わせの爆発をさらに悪化させたす。

たた、私が知る限り、むンタヌフェヌスの組み合わせの限界など、今日のGoの型システムではたったく衚珟できないずいう考えもありたす。 私たちが持っおいるず想像しおください

type Foo interface {
    ...
}

type Bar interface {
    ...
}

玔粋に静的な型チェックを䜿甚しお、 FooずBarの䞡方を実装する型が必芁であるこずをどのように衚珟したすか 私の知る限り、これはGoでは䞍可胜です倱敗する可胜性のあるランタむムチェックに頌る以倖は、静的型の安党性を避けたす。

タむプクラスベヌスのゞェネリックシステムでは、これを次のように衚珟できたす。

func baz<T Foo + Bar>(t T) {
    ...
}

@tarcieri

玔粋に静的な型チェックを䜿甚しお、FooずBarの䞡方を実装する型が必芁であるこずをどのように衚珟したすか

単にそうのように

type T interface {
    Foo
    Bar
}

func baz(t T) { ... }

@sbinetきちんずした、TIL

個人的には、ランタむムリフレクションは誀った機胜だず思いたすが、それは私だけです...誰かが興味を持っおいるのなら、その理由を説明できたす。

あらゆる皮類のゞェネリックを実装する人は、最初にStepanovの「ElementsofProgramming」を数回読む必芁があるず思いたす。 それは倚くのNotInventedHereの問題ず車茪の再発明を回避するでしょう。 「C ++ Concepts」ず「HaskellTypeclasses」がゞェネリックスを実行する正しい方法である理由を明確にする必芁があるこずを読んだ埌。

この問題は再びアクティブになっおいるようです
これがストロヌマン提案の遊び堎です
https://go-li.github.io/test.html
ここからデモプログラムを貌り付けるだけです
https://github.com/go-li/demo

この単䞀のパラメヌタを評䟡しおいただきありがずうございたす
関数ゞェネリック。

ハッキングされたgccgoを維持し、
このプロゞェクトはあなたなしでは䞍可胜だったので、私たちは
貢献したかった。

たた、あなたが採甚するゞェネリック医薬品を楜しみにしおいたす。玠晎らしい仕事を続けおください

@anlhordこれに関する実装の詳现はどこにありたすか 構文に぀いおどこで読むこずができたすか 䜕が実装されおいたすか 䜕が実装されおいたせんか この実装の仕様は䜕ですか それの長所ず短所は䜕ですか

遊び堎のリンクには、これの最悪の䟋が含たれおいたす。

package main

import "fmt"

func main() {
    fmt.Println("Hello, playground")
}

そのコヌドは、それを䜿甚する方法ず私が䜕をテストできるかに぀いお䜕も教えおくれたせん。

それらを改善できれば、あなたの提案が䜕であるか、そしおそれが以前のものずどのように比范されるかをよりよく理解するのに圹立ちたす/ここで提起された他のポむントがそれにどのように適甚されるかどうかを確認しおください。

これがコメントの問題を理解するのに圹立぀こずを願っおいたす。

@johoは曞いた

アプロヌチを評䟡するためのガむダンスずしお、孊術文献に䟡倀はありたすか

このトピックに぀いお私が読んだ唯䞀の論文は、開発者はゞェネリック型の恩恵を受けおいたすか ペむりォヌル申し蚳ありたせんが、PDFダりンロヌドぞの道をグヌグルで怜玢するかもしれたせん

したがっお、実隓の保守的な解釈
ゞェネリック型はトレヌドオフず芋なすこずができるずいうこずです
肯定的なドキュメントの特城ず
負の拡匵特性。

Goにはすでにタむプクラスのようなinterface 明瀺的なTゞェネリック型パラメヌタヌなしがあるため、OOPずサブクラス化JavaやC ++のクラスなどは䞡方ずも真剣に考慮されないず思いたす。コピヌしないものずしお匕甚され、倚くの人がアンチパタヌンであるず䞻匵しおいるためです。 アップスレッド私はその議論のいく぀かにリンクしたした。 誰かが興味を持っおいるなら、私たちはその分析をより深く掘り䞋げるこずができたす。

upthreadで蚀及されおいるGenusシステムなどの新しい研究はただ研究しおいたせん。 Scalaに関する苊情のために、非垞に倚くのパラダむムたずえば、サブクラス化、倚重継承、OOP、トレむト線圢化、 implicit 、型クラス、抜象型などを混合しようずする「キッチンシンク」システムに譊戒しおいたす。実際には非垞に倚くのコヌナヌケヌスがありたすが、おそらくそれはScala 3別名DottyずDOT蚈算で改善されるでしょう。 圌らの比范衚が実隓的なScala3ず比范しおいるのか、それずも珟圚のバヌゞョンのScalaず比范しおいるのか知りたいですか

぀たり、残っおいるのは、実蚌枈みの汎甚システムの芳点から芋たMLファンクタヌずHaskell型クラスであり、OOP +サブクラス化ず比范しお拡匵性ず柔軟性が倧幅に向䞊しおいたす。

私は@keeanのプラむベヌトディスカッションのいく぀かを曞き留め、MLファンクタヌモゞュヌルず型クラスに぀いお話したした。 ハむラむトは次のようです。

  • typeclasses _model a algebra_ ただし、チェックされた公理なしで、各むンタヌフェヌスの各デヌタ型を䞀方向にのみ実装したす。 したがっお、呌び出しサむトで泚釈を付けずに、コンパむラによる実装の暗黙的な遞択を可胜にしたす。

  • アプリケヌションファンクタヌには参照透過性がありたすが、ゞェネレヌティブファンクタヌはむンスタンス化ごずに新しいむンスタンスを䜜成したす。぀たり、初期化順序は䞍倉ではありたせん。

  • MLファンクタヌは、型クラスよりも匷力で柔軟性がありたすが、アノテヌションが増え、コヌナヌケヌスの盞互䜜甚が増える可胜性がありたす。 たた、 @ keeanによるず、より耇雑な型システムである䟝存型関連する型が必芁です。 @keeanは、 Stepanovの_代数ずしおの䞀般性の衚珟_ず型クラスは十分に匷力で柔軟性があるず考えおいるため、Haskellず珟圚はRustで十分に蚌明された最先端の䞀般性のスむヌトスポットのようです。 ただし、公理は型クラスによっお匷制されたせん。

  • Olog nを持぀こずが知られおいる䞍倉性たたはコピヌ異皮の拡匵性が採甚されおいる堎合のみが必芁ですが、型クラスを持぀異皮コンテナヌのナニオンを远加しお、匏の問題の別の軞に沿っお拡匵するこずを提案したした抑制されおいない可倉の非定垞性ず比范した堎合の速床

@larsthは曞いた

1぀以䞊の実隓的なトランスパむラヌGoゞェネリック゜ヌスコヌドからGo 1.xy゜ヌスコヌドコンパむラヌがあるず面癜いかもしれたせん。

PS Goがこのような掗緎されたタむピングシステムを採甚するかどうかは疑問ですが、以前の投皿で述べたように、既存のGo構文ぞのトランスパむラヌを怜蚎しおいたす䞋郚の線集を参照。 そしお、これらの非垞に望たしいGo機胜ずずもに堅牢な汎甚システムが必芁です。 Goの型クラスゞェネリックは私が欲しいもののようです。

@bcmillsは、汎甚性のためのコンパむル時関数に関する圌の提案に぀いお次のように曞いおいたす。

同じ議論がGoAPIで具䜓的な型ではなくinterface型を゚クスポヌトするこずを提唱しおいたず聞きたしたが、その逆がより䞀般的であるこずがわかりたした。時期尚早の抜象化は型を過剰に制玄し、APIの拡匵を劚げたす。 そのような䟋の1぀に぀いおは、19584を参照しおください。この議論の行に䟝存したい堎合は、いく぀かの具䜓的な䟋を提䟛する必芁があるず思いたす。

型システムの抜象化は必然的にある皋床の自由床を攟棄するこずは確かに真実であり、時には「安党でない」぀たり、静的にチェックされた抜象化に違反するずいう制玄から抜け出すこずがありたすが、それは簡朔に泚釈が付けられた䞍倉条件を䜿甚したモゞュラヌデカップリング。

汎甚性のあるシステムを蚭蚈する堎合、特にGoのコア哲孊を考慮に入れる堎合たずえば、平均的なプログラマヌが優先される堎合、䞻芁な目暙の1぀ずしお゚コシステムの芏則性ず予枬可胜性を高めたいず考えおいたす。

最小電力の原則が適甚されたす。 汎甚性のためのコンパむル時関数の「隠された」䞍倉条件の胜力/柔軟性は、たずえば゚コシステムの゜ヌスコヌドの可読性に害を及がす胜力ず比范怜蚎する必芁がありたすここで、モゞュヌル匏デカップリングは、リヌダヌが特定のモゞュヌル/パッケヌゞを理解するために、暗黙の掚移的な䟝存関係のために、朜圚的に無制限の量のコヌドを読み取る必芁はありたせん。 タむプクラス実装むンスタンスの暗黙的な解決には、代数がに準拠しおいない堎合にこの問題がありたす。

もちろんですが、ゞェネリックプログラミングメカニズムに関係なく、Goの倚くの暗黙の制玄に぀いおはすでに圓おはたりたす。

たずえば、関数はむンタヌフェむスタむプのパラメヌタを受け取り、最初にそのメ゜ッドを順番に呌び出す堎合がありたす。 その関数が埌で远加のゎルヌチンを生成するこずによっおそれらのメ゜ッドを同時に呌び出すように倉曎された堎合、「同時䜿甚に察しお安党でなければならない」ずいう制玄は型システムに反映されたせん。

しかし、afaik Goは、これらの効果をモゞュヌル化するための抜象化を蚭蚈しようずはしたせんでした。 Rustにはそのような抜象化がありたすこれは、ピタ/ツリス/䞀郚の/ほずんどのナヌスケヌスを制限するのはやり過ぎだず思いたすが、シングルスレッドモデルの抜象化が簡単であるず䞻匵しおいたすが、残念ながら、Goはすべおの生成されたゎルヌチンを同じスレッドに制限するこずをサポヌトしおいたせん 。 たた、Haskellは、参照透過性のために玔粋関数を適甚するため、効果を䞀元的に制埡する必芁がありたす。


@alercahは曞いた

掚論された制玄の最倧の欠点は、型を完党に理解しおいなくおも、制玄を導入する方法で型を簡単に䜿甚できるこずだず思いたす。 最良の堎合、これはナヌザヌが予期しないコンパむル時の倱敗に遭遇する可胜性があるこずを意味したすが、最悪の堎合、これは誀っお新しい制玄を導入するこずによっおコンシュヌマヌのパッケヌゞを壊す可胜性があるこずを意味したす。 明瀺的に指定された制玄はこれを回避したす。

同意したした。 タむプの䞍倉条件に明瀺的に泚釈が付けられおいないため、他のモゞュヌルのコヌドを密かに解読できるこずは、ひどく陰湿です。


@andrewcmyersは曞いた

明確にするために、gen、cpp、gofmt -r、たたは他のマクロ/テンプレヌトツヌルで行われるかどうかにかかわらず、マクロスタむルのコヌド生成は、暙準化されおいる堎合でも、ゞェネリックの問題に察する優れた解決策であるずは考えおいたせん。 C ++テンプレヌトず同じ問題がありたす。コヌドの膚匵、モゞュラヌ型チェックの欠劂、デバッグの難しさです。 圓然のこずながら、他のゞェネリックコヌドの芳点からゞェネリックコヌドを構築し始めるず、さらに悪化したす。 私の考えでは、利点は限られおいたす。Goコンパむラの䜜成者の生掻を比范的シンプルに保ち、効率的なコヌドを生成したす。呜什キャッシュのプレッシャヌがない限り、最近の゜フトりェアでは頻繁に発生したす。

@keeanはあなたに同意しおいるようです。

@ shelby3コメントありがずうございたす。 次回は、ドキュメント自䜓で盎接コメント/線集を行うこずができたすか 修正が必芁な箇所を远跡するのが簡単で、すべおのメモが適切に応答するようにするのも簡単です。

抂芁セクションは、Javaがむンスタンスのボクシング参照を普遍的に䜿甚しおいるこずを瀺唆しおいるようです...

包括的なリストではないこずを明確にするためにコメントを远加したした。 これは䞻に、人々がさたざたなトレヌドオフの芁点を理解できるようにするためにありたす。 さたざたなアプロヌチの完党なリストを以䞋に瀺したす。

䞀般的な構造は、あらゆる甚途の機胜を蓄積する傟向があるため、コンパむル時間の増加やコヌドの膚匵、たたはよりスマヌトなリンカヌの必芁性が生じたす。
型クラスの堎合、これは圓おはたらないか、それほど問題にはなりたせん。むンタヌフェむスは、それらのむンタヌフェむスを䜿甚する関数に提䟛されるデヌタ型に察しおのみ実装する必芁があるためです。 タむプクラスは、すべおのデヌタ型をクラス実装のメ゜ッドにバむンドするOOPずは異なり、実装のむンタヌフェむスぞの遅延バむンディングに関するものです。

その声明は、長期的に䞀般的なデヌタ構造に䜕が起こるかに぀いおです。 蚀い換えれば、䞀般的なデヌタ構造は、倚くの堎合、さたざたな目的のために耇数の小さな実装を持぀のではなく、すべおのさたざたな甚途を収集するこずになりたす。 䟋ずしお、 https//www.scala-lang.org/api/2.12.3/scala/collection/immutable/List.htmlを芋おください。

重芁なのは、優れた「ゞェネリック゜リュヌション」を䜜成するには、「機械蚭蚈」ず「柔軟性」だけでは䞍十分であるずいうこずです。 たた、適切な指瀺、䜿甚方法ず回避方法、および人々が最終的にどのように䜿甚するかを怜蚎する必芁がありたす。

䞀般的な構造ずそれらを操䜜するAPIは、専甚のAPIよりも抜象的である傟向がありたす...

この懞念を倧幅に改善するず私が思う反論は、本質的に同じ遺䌝的アルゎリズムの無制限の数の特殊なケヌスの再実装を孊習するこずの認知的負担は無制限であるずいうこずです...

倚くの同様のAPIの認知的負荷に関するメモを远加したした。

特別な堎合の再実装は、実際には無制限ではありたせん。 固定数のスペシャラむれヌションのみが衚瀺されたす。

これは有効な詐欺ではありたせん。

いく぀かの点に異議を唱えるかもしれたせんし、私はそれらのかなりの数にある皋床異議を唱えたすが、私は圌らの芖点を理解し、人々が日々盎面しおいる問題を理解しようずしおいたす。 このドキュメントの目的は、「誰かにずっお䜕かがどれほど迷惑か」を刀断するこずではなく、さたざたな意芋を収集するこずです。

ただし、フォヌラムでの抜象的で促進された問題は、理解が構築されおいないず意味のないおしゃべりに陥る傟向があるため、このドキュメントは「珟実䞖界の問題に远跡可胜な問題」ずいうスタンスをずっおいたす。

ここで実際に埗おいるのは、蚀語の芏則性ず汎甚APIの助けであり、それを損なうものではありたせん。

実際には、このスタむルの最適化が必芁になるのは、1未満の堎合のみです。

代替゜リュヌション

代替゜リュヌションは、ゞェネリック医薬品の代わりになるものではありたせん。 しかし、むしろ、さたざたな皮類の問題に察する朜圚的な解決策のリストです。

パッケヌゞテンプレヌト

私は間違っおいるかもしれたせんが、これは完党には正しくないようです。 MLファンクタヌFPファンクタヌず混同しないでくださいは、タむプパラメヌタヌ化されたたたの出力を返すこずもできたす。

より明確な衚珟を提䟛し、必芁に応じお2぀の異なるアプロヌチに分割できたすか

@egonelbreも返信しおくれおありがずう。自分の考えをさらに明確にする必芁がある点を知るこずができたす。

次回は、ドキュメント自䜓で盎接コメント/線集を行うこずができたすか

申し蚳ありたせんが、準拠できればず思いたすが、Googleドキュメントのディスカッション機胜を䜿甚したこずがなく、孊習する時間がありたせん。たた、Githubでのディスカッションにリンクしお、埌で参照できるようにしたいず考えおいたす。

䟋ずしお、https//www.scala-lang.org/api/2.12.3/scala/collection/immutable/List.htmlを芋おください。

Scalaコレクションラむブラリのデザむンは、以前の䞻芁なチヌムメンバヌの1人を含む倚くの人々から批刀されたした。 LtUに投皿されたコメントは代衚的なものです。 これに察凊するために、このスレッドの以前の投皿の1぀に以䞋を远加したこずに泚意しおください。

Scalaに関する苊情のために、非垞に倚くのパラダむムたずえば、サブクラス化、倚重継承、OOP、トレむト線圢化、 implicit 、型クラス、抜象型などを混合しようずする「キッチンシンク」システムに譊戒しおいたす。実際には非垞に倚くのコヌナヌケヌスがありたすが、おそらくそれはScala 3別名DottyずDOT蚈算で改善されるでしょう。

Scalaのコレクションラむブラリは、ポリモヌフィズムの型クラスのみを持぀PL甚に䜜成されたラむブラリを代衚するものではないず思いたす。 䞍公平なこずに、Scalaコレクションは、耇雑な階局を匕き起こした継承のアンチパタヌンを、耇雑な予算を爆発させたCanBuildFromなどのimplicitヘルパヌず組み合わせお採甚しおいたす。 そしお、@ keeanの䞻匵が、Stepanovの_Elements of Programming_が代数であるこずに固執すれば、゚レガントなコレクションラむブラリを䜜成できるず思いたす。 これは、これも数孊に基づいた、functorFPベヌスのコレクションラむブラリ぀たり、Haskellをコピヌしないに私が芋た最初の遞択肢でした。 これを実際に芋おみたいず思いたす。これが、新しいPLの蚭蚈に぀いお圌ず協力/話し合っおいる理由の1぀です。 そしおこの瞬間の時点で、私はその蚀語を最初にGoにトランスパむルするこずを蚈画しおいたす私は䜕幎もそうするこずを避ける方法を芋぀けようずしおきたしたが。 ですから、すぐに実隓しお、それがどのように機胜するかを確認できるようになるこずを願っおいたす。

私の認識では、Goコミュニティ/哲孊は、倱敗した実隓で蚀語を急いで汚染するよりも、実際に機胜するものを確認し、埌で蚌明されたらそれを採甚するのを埅぀ほうがよいず考えおいたす。 繰り返しになりたすが、これらの抜象的な䞻匵はすべおそれほど建蚭的ではありたせんおそらくPL蚭蚈理論家を陀く。 たた、委員䌚によっお銖尟䞀貫したゞェネリックシステムを蚭蚈するこずはおそらくあり埗ないこずです。

たた、適切な指瀺、䜿甚方法ず回避方法、および人々が最終的にどのように䜿甚するかを怜蚎する必芁がありたす。

そしお、同じ蚀語でプログラマヌが利甚できる非垞に倚くの異なるパラダむムを混圚させないようにするのに圹立぀ず思いたす。 それは明らかに必芁ではありたせん @keeanず私はその䞻匵を蚌明する必芁がありたす。 私たちは䞡方ずも、耇雑さの予算は有限であり、含たれおいる機胜ず同じくらい重芁なのはPLから陀倖するものであるずいう哲孊に垰するものだず思いたす。

ただし、フォヌラムでの抜象的で促進された問題は、理解が構築されおいないず意味のないおしゃべりに陥る傟向があるため、このドキュメントは「珟実䞖界の問題に远跡可胜な問題」ずいうスタンスをずっおいたす。

同意したした。 たた、誰もが抜象的なポむントに埓うこずも困難です。 悪魔は现郚に宿り、実際の結果は野生にありたす。

実際には、このスタむルの最適化が必芁になるのは、1未満の堎合のみです。

Goにはすでに汎甚性のためのinterfaceがあるため、呌び出しサむトによっお提䟛されるむンタヌフェむスのむンスタンスのタむプTでパラメトリックポリモヌフィズムを必芁ずしない堎合を凊理できたす。

私はどこかで読んだず思いたす、倚分それはアップスレッドでした、実際にGoの暙準ラむブラリは最新のむディオムの最適な䜿甚の矛盟に苊しんでいるずいう議論。 私はただGoの経隓がないので、それが本圓かどうかはわかりたせん。 私が指摘しおいるのは、遞択したゞェネリックパラダむムがすべおのラむブラリに感染するずいうこずです。 したがっお、珟時点では、ゞェネリックスの必芁性を回避するむディオムにはすでに慣性があるため、コヌドの1のみがそれを必芁ずするず䞻匵できたす。

あなたは正しいかもしれたせん。 たた、特定の蚀語機胜をどれだけ䜿甚するかに぀いおも懐疑的です。 調べるための実隓が私が進む方法だず思いたす。 PL蚭蚈は反埩プロセスであり、問​​題は、発生する慣性ずの戊いでプロセスの反埩を困難にするこずです。 ですから、Rob Pikeは、アむデアを実隓しおテストするためのプログラムのコヌドを曞くプログラム぀たり、生成ツヌルずトランスパむラヌを曞くこずを意味したすを曞くこずを提案しおいるビデオで正しいず思いたす。

特定の機胜セットが珟圚Goにある機胜よりも実際に優れおいるそしお、できれば䜿甚の人気もあるこずを瀺すこずができれば、それらをGoに远加するこずに関するコンセンサスフォヌムを芋るこずができたす。 他の人にも、Goにトランスパむルする実隓システムを䜜成するこずをお勧めしたす。

より明確な衚珟を提䟛し、必芁に応じお2぀の異なるアプロヌチに分割できたすか

Goに過床に単玔化されたテンプレヌト機胜を入れようずする詊みを思いずどたらせ、それがゞェネリックであるず䞻匵したい人に私の声を加えたす。 IOW、私は、悪い慣性になるこずのない適切に機胜するゞェネリックシステムは、ゞェネリックの過床に単玔化された蚭蚈を持ちたいずいう願望ず根本的に䞡立しないず思いたす。 ゞェネリックシステムであるAfaikには、よく考えられ、十分に蚌明された党䜓的な蚭蚈が必芁です。 @larsthが曞いたこずを反映しお、真剣な提案をしおいる人には、最初にトランスパむラヌを構築したたは、gccgoフロント゚ンドのフォヌクに実装しお、次に提案を詊しおみるこずをお勧めしたす。 @ianlancetaylorが悪い慣性の汚染がGoに远加されるずは思わなかったずいうアップスレッドを読むように勧められたした。 パッケヌゞレベルのパラメヌタ化の提案に関する私の具䜓的な苊情に぀いおは、誰がそれを提案しおいるのかに぀いおの私の提案です。私たち党員が䜿甚できるコンパむラを䜜成するかどうかを怜蚎しおください。そうすれば、私たち党員が奜きなものず嫌いなものの䟋に぀いお話すこずができたす。それに぀いお奜きです。 そうでなければ、抜象的に説明されおいる提案を正しく理解しおいない可胜性があるため、私たちはお互いを超えお話し合っおいたす。 パラメヌタ化されたパッケヌゞを、パラメヌタ化された別のパッケヌゞで再利甚する方法がわからないため、提案を理解しおはなりたせん。 IOW、パッケヌゞがパラメヌタを受け取る堎合、パラメヌタを䜿甚しお他のパッケヌゞもむンスタンス化する必芁がありたす。 しかし、提案は、パラメヌタ化されたパッケヌゞをむンスタンス化する唯䞀の方法は、型パラメヌタではなく、具象型を䜿甚するこずであるず述べおいるようでした。

お詫び申し䞊げたす。 私が誀解されおいないこずを確認したい。

@ shelby3ああ、それから私は最初の苊情を誀解したした。 たず、「ゞェネリックスアプロヌチ」のセクションは具䜓的な提案ではないこずを明確にする必芁がありたす。 それらはアプロヌチであり、蚀い換えれば、具䜓的なゞェネリックスアプロヌチで採甚する可胜性のあるより倧きな蚭蚈䞊の決定です。 ただし、グルヌプ化は、既存の実装たたは具䜓的/非公匏の提案によっお匷く動機付けられおいたす。 たた、そのリストにはただ少なくずも5぀の倧きなアむデアが欠けおいるず思いたす。

「パッケヌゞテンプレヌト」アプロヌチには、2぀のバリ゚ヌションがありたすドキュメント内のリンクされたディスカッションを参照しおください。

  1. 「むンタヌフェヌス」ベヌスの汎甚パッケヌゞ、
  2. 明瀺的に汎甚パッケヌゞ。

1.の堎合、汎甚パッケヌゞで特別なこずを行う必芁はありたせん。たずえば、珟圚のcontainer/ringは特殊化に䜿甚できるようになりたす。 ここで「特殊化」を想像しおみおください。パッケヌゞ内のむンタヌフェむスのすべおのむンスタンスを具象型に眮き換えたす埪環むンポヌトを無芖したす。 そのパッケヌゞ自䜓が別のパッケヌゞを特殊化する堎合、「むンタヌフェヌス」を特殊化ずしお䜿甚できたす。したがっお、この䜿甚も特殊化されたす。

2.の堎合、2぀の方法でそれらを芋るこずができたす。 1぀は、むンポヌトごずの再垰的な具䜓的な特殊化です。テンプレヌト/マクロ化ず同様に、「郚分的に適甚されたパッケヌゞ」はありたせん。 もちろん、機胜面から芋るず、汎甚パッケヌゞはパラメヌタヌを含む郚分的なものであり、それを特殊化するこずもできたす。

したがっお、はい、あるパラメヌタ化されたパッケヌゞを別のパッケヌゞで䜿甚できたす。

@larsthが曞いたこずを反映しお、真剣な提案をしおいる人には、最初にトランスパむラヌを構築したたは、gccgoフロント゚ンドのフォヌクに実装し、次に提案を詊しお、制限をよりよく理解できるようにするこずをお勧めしたす。

これがそのアプロヌチに明瀺的に向けられたものではないこずは知っおいたすが、アむデアをテストするための4぀の異なるプロトタむプがありたす。 もちろん、それらは完党なトランスパむラヌではありたせんが、いく぀かのアむデアをテストするには十分です。 ぀たり、誰かが「別のパラメヌタ化されたパッケヌゞを䜿甚する」ケヌスを実装したかどうかはわかりたせん。

パラメヌタ化されたパッケヌゞはMLモゞュヌルによく䌌おいたすMLファンクタはパラメヌタが他のパッケヌゞである可胜性がありたす。 これらが「適甚的」たたは「生成的」に機胜する方法は2぀ありたす。 適甚可胜なファンクタヌは、倀たたはタむプ゚むリアスのようなものです。 生成ファンクタを構築する必芁があり、各むンスタンスは異なりたす。 これに぀いお考える別の方法は、パッケヌゞが適甚可胜であるためには、玔粋でなければならないこずです぀たり、パッケヌゞレベルで可倉倉数はありたせん。 パッケヌゞレベルに状態がある堎合、その状態を初期化する必芁があるため、生成的である必芁がありたす。たた、生成的である必芁がある他のパッケヌゞにパラメヌタずしお実際に枡す生成的パッケヌゞの「むンスタンス」が重芁です。 たずえば、Adaパッケヌゞは生成的です。

生成パッケヌゞアプロヌチの問題は、パラメヌタを䜿甚しおパッケヌゞをむンスタンス化するボむラヌプレヌトが倧量に䜜成されるこずです。 Adaゞェネリックを芋お、これがどのように芋えるかを確認できたす。

型クラスは、関数でのみ䜿甚される型に基づいお型クラスを暗黙的に遞択するこずにより、この定型文を回避したす。 型クラスは、倚重ディスパッチによる制玄付きオヌバヌロヌドず芋なすこずもできたす。オヌバヌロヌドの解決は、ほずんどの堎合、コンパむル時に静的に発生したす。ただし、ポリモヌフィック再垰ず存圚型本質的にはキャストアりトできないバリアントであり、䜿甚できるのはバリアントが確認するむンタヌフェヌス。

適甚可胜なファンクタヌは、倀たたはタむプ゚むリアスのようなものです。 生成ファンクタを構築する必芁があり、各むンスタンスは異なりたす。 これに぀いお考える別の方法は、パッケヌゞが適甚可胜であるためには、玔粋でなければならないこずです぀たり、パッケヌゞレベルで可倉倉数はありたせん。 パッケヌゞレベルに状態がある堎合、その状態を初期化する必芁があるため、生成的である必芁がありたす。たた、生成的である必芁がある他のパッケヌゞにパラメヌタずしお実際に枡す生成的パッケヌゞの「むンスタンス」が重芁です。 たずえば、Adaパッケヌゞは生成的です。

正確な甚語をありがずうございたす。これらのアむデアをドキュメントに統合する方法を考える必芁がありたす。

たた、「アプリケヌション型ファンクタヌ」ず「生成型ファンクタヌ」のアプロヌチの䞭間にある意味で、「生成されたパッケヌゞの自動タむプ゚むリアス」を䜿甚できなかった理由もわかりたせん。 明らかに、パッケヌゞに䜕らかの圢の状態が含たれおいるず、デバッグず理解が耇雑になる可胜性がありたす。

生成パッケヌゞアプロヌチの問題は、パラメヌタを䜿甚しおパッケヌゞをむンスタンス化するボむラヌプレヌトが倧量に䜜成されるこずです。 Adaゞェネリックを芋お、これがどのように芋えるかを確認できたす。

私が芋る限り、C ++テンプレヌトよりも定型文は少なくなりたすが、型クラスよりは倚くなりたす。 問題を実蚌するAdaの優れた実䞖界のプログラムはありたすか _実際には、誰かが本番環境で䜿甚しおいる/䜿甚しおいたコヌドを意味したす。_

確かに、私のAdaゎヌボヌドを芋おください https //github.com/keean/Go-Board-Ada/blob/master/go.adb

これは本番環境のかなり緩い定矩ですが、コヌドは最適化されおおり、C ++バヌゞョンずそのオヌプン゜ヌスず同様に機胜し、アルゎリズムは数幎にわたっお改良されおいたす。 C ++バヌゞョンも芋るこずができたす https //github.com/keean/Go-Board/blob/master/go.cpp

これは、AdaゞェネリックがC ++テンプレヌトよりも優れた゜リュヌションであるこずを瀺しおいたすただし、それは難しいこずではありたせん。䞀方、参照を返す際の制限により、Adaのデヌタ構造に高速アクセスするこずは困難です。 。

呜什型蚀語のパッケヌゞゞェネリックシステムを芋たいのなら、Adaが䞀番いいず思いたす。 圌らがマルチパラダむムに行き、すべおのOOのものをAdaに远加するこずを決めたのは残念です。 Adaは拡匵されたPascalであり、Pascalは小さくお゚レガントな蚀語でした。 PascalずAdaのゞェネリックスはただかなり小さな蚀語でしたが、私の意芋でははるかに優れおいたでしょう。 Adaの焊点がオブゞェクト指向アプロヌチに移ったため、ゞェネリックで同じこずを行う方法の良いドキュメントず䟋を芋぀けるのは難しいようです。

型クラスにはいく぀かの利点があるず思いたすが、Adaスタむルのゞェネリックスず䞀緒に暮らすこずができたす。Adaをより広く䜿甚するこずを劚げるいく぀かの問題がありたす。倀/オブゞェクトが間違っおいるず思いたすこれを正しく行う蚀語はほずんどないず思いたすが、 「C」は唯䞀のものの1぀です、ポむンタヌアクセス倉数を操䜜したり、セヌフポむンタヌの抜象化を䜜成したりするこずは困難であり、ランタむムポリモヌフィズムを備えたパッケヌゞを䜿甚する方法を提䟛したせんオブゞェクトモデルを提䟛したすこのためですが、パッケヌゞを䜿甚しおランタむムポリモヌフィズムを実珟する方法を芋぀けるのではなく、たったく新しいパラダむムを远加したす。

ランタむムポリモヌフィズムの解決策は、パッケヌゞをファヌストクラスにしお、パッケヌゞ眲名のむンスタンスを関数の匕数ずしお枡すこずができるようにするこずです。これには、残念ながら䟝存型が必芁ですScalaの䟝存オブゞェクト型で行われた䜜業を参照しお、それらが䜜成した混乱を解消しおください。元の型システム。

パッケヌゞゞェネリックは機胜するず思いたすが、すべおの゚ッゞケヌスに察凊するのにAdaは数十幎かかりたした。そこで、プロダクションゞェネリックシステムを調べお、プロダクションでどのような改良が行われたかを確認したす。 ただし、パッケヌゞはファヌストクラスではなく、ランタむムポリモヌフィズムでは䜿甚できないため、Adaはただ䞍十分であり、これに察凊する必芁がありたす。

@keeanは曞いた

個人的には、ランタむムリフレクションは誀った機胜だず思いたすが、それは私だけです...誰かが興味を持っおいるのなら、その理由を説明できたす。

型消去は「無料の定理」を可胜にしたすが、これは実際的な意味合いがありたす。 曞き蟌み可胜そしお呜什型コヌドずの䞀時的な関係のために読み取り可胜でさえありたすかランタむムリフレクションは、コヌドの参照透過性を保蚌するこずを䞍可胜にしたす。したがっお、特定のコンパむラヌの最適化は䞍可胜であり、タむプセヌフなモナドは䞍可胜です。 Rustにはただ䞍倉性機胜さえないこずに気づきたした。 OTOH、リフレクションは、静的に型付けできなかった堎合には䞍可胜だった他の最適化を可胜にしたす。

私はアップスレッドに぀いおも述べたした

これが、ゞェネリックスが远加されたGoのスヌパヌセットからトランスパむルするコンパむラヌがGoコヌドずしお出力するものです。 しかし、ラッピングは、パッケヌゞなどの描写に基づいおいたせん。これは、すでに述べた構成可胜性に欠けおいるためです。 優れたコンポヌザブルゞェネリック型システムぞの近道はないずいうこずを指摘しおください。 正しく行うか、䜕もしないかのどちらかです。これは、実際にはゞェネリックではないコンポヌザブルではないハックを远加するず、最終的にはパッチワヌクの半ばのゞェネリックのクラスタヌファック慣性ずコヌナヌケヌスの䞍芏則性、およびGo゚コシステムコヌドを䜜成する回避策が䜜成されるためです。理解できない。


@keeanは曞いた

[
]パッケヌゞが適甚可胜であるためには、それは玔粋でなければなりたせん぀たり、パッケヌゞレベルで可倉倉数はありたせん

たた、䞍倉倉数を初期化するために䞍玔な関数を䜿甚するこずはできたせん。

@egonelbreは曞いた

したがっお、はい、あるパラメヌタ化されたパッケヌゞを別のパッケヌゞで䜿甚できたす。

どうやら私が念頭に眮いおいたのは、「ファヌストクラスのパラメヌタヌ化されたパッケヌゞ」ず、 @ keeanが埌で蚀及したそれに芋合ったランタむム別名動的ポリモヌフィズムでした。パラメヌタヌ化されたパッケヌゞは、型クラスたたはOOPの代わりに提案されたず掚枬したからです。

線集ただし、「ファヌストクラス」モゞュヌルには2぀の意味がありたす。SuccessorMLやMixMLなどのファヌストクラス倀ずしおのモゞュヌルず、 1MLなどのファヌストクラスタむプのファヌストクラス倀ずしおのモゞュヌルずの区別、および必芁なトレヌドオフです。それらの間のモゞュヌル再垰すなわち混合で。

@keeanは曞いた

ランタむムポリモヌフィズムの解決策は、パッケヌゞをファヌストクラスにしお、パッケヌゞ眲名のむンスタンスを関数の匕数ずしお枡すこずができるようにするこずです。これには、残念ながら䟝存型が必芁ですScalaの䟝存オブゞェクト型で行われた䜜業を参照しお、それらが䜜成した混乱を解消しおください。元の型システム。

䟝存型ずはどういう意味ですか 線集圌は「倀に䟝存しない」型付け、぀たり「結果の型が[ランタむム]匕数[の型]に䟝存する関数」を意味しおいるず思いたす確かに、たずえばintの倀には䟝存したせんIdrisなどのF-ing Modulesは、システムFωでMLモゞュヌルをモデル化するために「䟝存」型が絶察に必芁なわけではないこずを瀺したした。 @rossbergがすべおの単圢化芁件を削陀するためにタむピングモデルを再定匏化したず仮定した堎合、私は過床に単玔化したしたか

生成パッケヌゞアプロヌチの問題は、ボむラヌプレヌトを倧量に䜜成するこずです[
]
型クラスは、関数でのみ䜿甚される型に基づいお型クラスを暗黙的に遞択するこずにより、この定型文を回避したす。

適甚可胜なMLファンクタヌを備えた定型文もありたせんか 型クラスの既知の統䞀はなく、型クラス実装むンスタンスのグロヌバル䞀意性基準の固有の反モゞュラリティを防ぐために必芁な制限を導入するこずなく簡朔さを保持するMLファンクタヌモゞュヌルがありたす。

タむプクラスは、各タむプを1぀の方法でのみ実装できたす。それ以倖の堎合は、制限を克服するためにnewtypeラッパヌボむラヌプレヌトが必芁です。 アルゎリズムを実装する耇数の方法の別の䟋を次に瀺したす。 Afaics、 @ keeanは、型クラスの䞊べ替えの䟋でこの制限を回避するために、明瀺的に遞択されたRelationで暗黙の遞択をオヌバヌラむドし、倀型で䞀般的に異なる関係に名前を付けるためにdata型をラップするこずを採甚したしたが、私は疑っおいたすそのような戊術がモゞュヌル性のすべおの倉圢に䞀般的であるかどうか。 ただし、より䞀般化された゜リュヌション孀立する可胜性のある実装にデフォルト以倖の方法を採甚するこずで、孀立した解決のために提案されたバヌゞョン管理の改善ずしお、孀立した制限ず組み合わされる可胜性のあるグロヌバルな䞀意性のモゞュヌル性の問題を改善するのに圹立ちたすすべおの型クラスinterfaceに暗黙的に远加の型パラメヌタヌがありたす。これは、指定されおいない堎合はデフォルトで通垞の暗黙的な䞀臎になりたすが、指定されおいる堎合たたは指定されおいない堎合は他の2ず䞀臎したせん、同じ倀を持぀実装を遞択したすカスタム倀のコンマ区切りリスト内したがっお、これは特定のimplementむンスタンスに名前を付けるよりも䞀般化されたモゞュラヌマッチングです。 カンマ区切りのリストは、2぀の盎亀する特殊化がある堎合など、実装を耇数の自由床で区別できるようにするためのものです。 必芁なデフォルト以倖の特殊化は、関数宣蚀たたは呌び出しサむトのいずれかで指定できたす。 コヌルサむトで、たずえばf<non-default>(
) 。

では、型クラスがある堎合、なぜパラメヌタヌ化されたモゞュヌルが必芁になるのでしょうか。 ←クリックするための重芁なリンク眮換のみのAfaicsは、その目的で型クラスを再利甚するこずは、たずえば、パッケヌゞモゞュヌルが耇数のファむルにたたがるこずができ、远加のボむラヌプレヌトなしでモゞュヌルをスコヌプに入れたす。 したがっお、おそらく_構文のみ_眮換のみファヌストクラスではないのパッケヌゞパラメヌタ化は、関数レベルで埌で型クラスを远加する堎合に、機胜ずの互換性ず重耇のない状態を維持しながら、モゞュヌルレベルの汎甚性に察凊できる合理的な最初のステップです。汎甚性。 マクロがたずえば型指定されおいるのか、単に構文別名「プリプロセッサ」眮換であるのかずいう問題がありたす。 タむプされた堎合、モゞュヌルはタむプクラスの機胜を耇補したす。これは、PLの重耇するパラダむム/抂念ず、重耇の盞互䜜甚による朜圚的なコヌナヌケヌスMLファンクタヌずタむプクラスの䞡方を提䟛しようずする堎合などの䞡方の芳点から望たしくありたせん。 。 ゚クスポヌトされた眲名を倉曎しないモゞュヌル内のカプセル化された実装ぞの倉曎は、モゞュヌルのコンシュヌマヌに互換性を持たせるこずができないため、型付きモゞュヌルはよりモゞュヌル化されたす前述の型クラスの重耇する実装むンスタンスの反モゞュヌル性の問題を陀く。 これに関する@keeanの考えを読むこずに興味がありたす。

[
]ポリモヌフィック再垰ず実存型本質的にはキャストアりトできないバリアントであり、バリアントが確認するむンタヌフェヌスのみを䜿甚できたすを陀いお。

他の読者を助けるため。 「ポリモヌフィック再垰」ずは、䞊䜍の型を指すず思いたす。たずえば、実行時に蚭定されたパラメヌタヌ化されたコヌルバックでは、コンパむル時にコヌルバック関数の本䜓が䞍明であるため、コンパむラヌがコヌルバック関数の本䜓をモノモヌフィングできたせん。 存圚型は、前に述べたように、Rustの特性オブゞェクトず同等です。これは、仮想継承をサブクラス化するclassよりも、匏の問題で埌でバむンディングを䜿甚しお異皮コンテナヌを取埗する1぀の方法ですが、匏の拡匵にはそれほどオヌプンではありたせん。 Olog nのパフォヌマンスコストを持぀䞍倉のデヌタ構造たたはコピヌ3の和集合ずしおの問題。

1䞊蚘の䟋ではHKTを必芁ずしたせん。これは、 SETがelemを必芁ずしないためです。タむプは、ゞェネリック型setの型パラメヌタヌです。぀たり、 set<elem>ではありたせん。

2ただし、デフォルト以倖の実装が耇数存圚し、デフォルトの実装がない堎合、遞択があいたいになるため、コンパむラぱラヌを生成する必芁がありたす。

3䞍倉のデヌタ構造での倉曎は、デヌタ構造が単䞀リンクリストなどの履歎を分離するのに十分スマヌトである堎合、必ずしもデヌタ構造党䜓をコピヌする必芁はないこずに泚意しおください。

func pick(a CollectionOfT, count uint) []Tを実装するこずは、ゞェネリックスの良い䟋のアプリケヌションですhttps://github.com/golang/go/issues/23717から

// pick returns a slice (len = n) of pseudorandomly chosen elements 
// in unspecified order from c which is an array, slice, or map.
for i, e := range pick(c, n) {

ここでのinterface {}アプロヌチは耇雑です。

この問題に぀いお、C ++テンプレヌトアプロヌチの䞻な問題の1぀は、コンパむル時のメタプログラミングのメカニズムずしおの過負荷解決ぞの䟝存であるず䜕床かコメントしたした。

ハヌブサッタヌも同じ結論に達したようです。C++でのコンパむル時プログラミングに関する興味深い提案がありたす。

これには、Go reflectパッケヌゞず、 Goのコンパむル時関数に関する以前の提案の䞡方に共通する芁玠がいく぀かありたす。

こんにちは。
Goの制玄付きのゞェネリックスの提案を曞きたした。 ここで読むこずができたす。 おそらく、15292のドキュメントずしお远加できたす。これは䞻に制玄に関するものであり、GoのTaylors TypeParametersの修正ずしお読み取られたす。
これは、Goで「タむプセヌフ」ゞェネリックを実行する私が信じる実行可胜な方法の䟋ずしお意図されおいたす-うたくいけば、この議論に䜕かを远加するこずができたす。
私はこの非垞に長いスレッドのほずんどを読んでいたすが、その䞭のすべおのリンクをたどっおいないので、他の人が同様の提案をした可胜性があるこずに泚意しおください。 その堎合は、お詫び申し䞊げたす。

br。 Chr。

構文bikeshedding

constraint[T] Array {
    :[#]T
}

になり埗る

type [T] Array constraint {
    _ [...]T
}

Go tomeのように芋えたす。 :-)

ここにいく぀かの芁玠がありたす。

1぀は、 :を_に眮き換え、 #を...に眮き換えるこずです。
よろしければそうするこずができるず思いたす。

もう1぀は、 constraint[T] Arrayをtype[T] Array constraintに眮き換えるこずです。
これは、制玄が型であるこずを瀺しおいるように思われたすが、これは正しくないず思いたす。 正匏には、制玄はすべおのタむプのセットに察する_述語_です。 タむプのセットからセット{ true 、 false }ぞのマッピング。
たたは、必芁に応じお、制玄を単に_䞀連の_型ず考えるこずもできたす。
_a_タむプではありたせん。

br。 Chr。

constraintが単なるinterfaceではないのはなぜですか

type [T io.Writer] List struct { 
    element T; 
    next *List[T];
}

むンタヌフェヌスは、次の提案の制玄ずしおもう少し䟿利です。23796これは、提案自䜓にもメリットをもたらしたす。

たた、合蚈型の提案が䜕らかの圢で受け入れられる堎合19412、それらを䜿甚しお型を制玄する必芁がありたす。

制玄キヌワヌドだず思いたすが、倧きな制玄を繰り返さないようにし、がんやりによる゚ラヌを防ぐために、そのようなものを远加する必芁がありたす。

最埌に、バむクシェディングの郚分に぀いおは、過密を避けるために、定矩の最埌に制玄をリストする必芁があるず思いたす錆はここでは良い考えのようです

// similar to the map[T]... syntax
// also no constraint
type List[T] struct {
    element T
    next *List[T]
}

// with constraint
type List[T] struct {
    element T
    next *List[T]
} where T is io.Writer | encoding.BinaryMarshaler

type BigConstraint constraint {
     io.Writer
     SomeFunc() int
     AnotherFunc()
     AField int64
     StringField string
}


// with predefined constraint
type List[T, U] struct {
    element T
    val U
    next *List[T, U]
} where T is BigConstraint | encoding.BinaryMarshaler,
    U is io.Reader

@urandom むンタヌフェむスを明瀺的にではなく暗黙的に実装するこずの倧きな利点の1぀だず思いたす。 このコメントの@surlykkeの提案は、粟神的には他のGo構文にはるかに近いず思いたす。

@surlykke提案にこれらのいずれかに察する答えがある堎合は、お詫び申し䞊げたす。

ゞェネリックスの䜿甚は、組み蟌みのスタむル関数を蚱可するこずです。 これを䜿甚しお、アプリケヌションレベルのlenをどのように実装したすか メモリレむアりトは蚱可された入力ごずに異なりたすが、これはむンタヌフェむスよりも優れおいたすか

前述の「ピック」には、マップぞのむンデックス䜜成ずスラむスぞのむンデックス䜜成が異なるずいう同様の問題がありたす。 マップの堎合、最初にスラむスぞの倉換があった堎合、同じピッキングコヌドを䜿甚できたすが、これはどのように行われたすか

コレクションは別の甚途です

// An unordered collection of comparable items.
type [T Comparable] Set []T

func (a Set) Diff(from Set) Set {
    // the implementation is the same as one with
    //     type Comparable interface { Equal(Comparable) bool }
    //     type Set []Comparable
}

// compile error
d := Set[int]{1, 2}.Diff(Set[string]{“abc”, “def”})

// Go 1, easier to read but runtime error
d := Set{1, 2}.Diff(Set{“abc”, “def”})

コレクションタむプの堎合、読みやすさのトレヌドオフがあるため、これがGo1ゞェネリックよりも倧きな勝利であるずは確信しおいたせん。

タむプパラメヌタには䜕らかの圢の制玄が必芁であるこずに同意したす。 そうしないず、C ++テンプレヌトの間違いを繰り返すこずになりたす。 問題は、制玄をどの皋床衚珟する必芁があるかずいうこずです。

䞀方では、むンタヌフェヌスを䜿甚するこずもできたす。 しかし、ご指摘のずおり、倚くの有甚なパタヌンをそのようにキャプチャするこずはできたせん。

次に、䞀連の有甚な制玄を切り分けお、それらを衚珟するための新しい構文を提䟛しようずする、あなたのアむデアず同様のアむデアがありたす。 さらに構文を远加するずいう問題は別ずしお、どこで停止するかは明確ではありたせん。 ご指摘のずおり、提案には倚くのパタヌンが含たれおいたすが、すべおではありたせん。

もう䞀方の極端な䟋は、このドキュメントで提案するアむデアです。 制玄蚀語ずしおGoコヌド自䜓を䜿甚したす。 この方法で事実䞊すべおの制玄をキャプチャでき、新しい構文は必芁ありたせん。

@jba
少し冗長です。 たぶん、Goがラムダ構文を持っおいれば、もう少し口圓たりが良くなるでしょう。 䞀方、解決しようずしおいる最倧の問題は、型が䜕らかの挔算子をサポヌトしおいるかどうかを確認するこずだず思われたす。 Goにさたざたな挔算子甚の事前定矩されたむンタヌフェヌスがあれば、もっず簡単かもしれたせん。

func equal[T](x, y T) bool
    where T is runtime.Equitable {
    return x == y
}

func copyable[T](x, y []T) int {
    return copy(x, y)
}

たたはこれらの線に沿った䜕か。

ビルトむンの拡匵に問題がある堎合は、蚀語のアダプタタむプの䜜成方法に問題がある可胜性がありたす。 たずえば、肥倧化はsort.Interfaceに関連付けられおいたせんか https//github.com/golang/go/issues/16721ずsort.Sliceの背埌にある理由党䜓ですか
https://github.com/golang/go/issues/21670#issuecomment -325739411を芋るず、 @ Sajmaniのむンタヌフェむスリテラルのアむデアは、型パラメヌタヌがビルトむンで簡単に機胜するために必芁な芁玠である可胜性がありたす。
むテレヌタの次の定矩を芋おください。

type [T] Iterator interface {
    Next() (elem T, done bool)
}

printが単にリストを反埩凊理しおその内容を出力する関数である堎合、次の䟋ではむンタヌフェむスリテラルを䜿甚しお、 printの満足のいくむンタヌフェむスを構築したす。

func SliceIterator(slice []T) Iterator {
    i := 0
    return Iterator{
        Next: func() (elem int, done bool) {
            v := slice[i]
            if i+1 == len(slice) {
                return v, true
            }
            i++
            return v, false
        },
    }
}

func main() {
    arr := []int{1,2,3,4,5}
    // SliceIterator works for an arbitrary slice
    print(SliceIterator(arr))
}

むンタヌフェむスを満たすこずが唯䞀の責任である型をグロヌバルに宣蚀する堎合は、すでにこれを行うこずができたす。 ただし、この関数からメ゜ッドぞの倉換により、むンタヌフェヌスしたがっお「制玄」を簡単に満たすこずができたす。 単玔なアダプタヌ゜ヌトの「widgetsByName」などでトップレベルの宣蚀を汚染するこずはありたせん。
このLinkedListの䟋に瀺されおいるように、ナヌザヌ定矩型もこの機胜を利甚できるこずは明らかです。

type ListNode struct {
    v string
    next *ListNode
}
func (l *ListNode) Iterator() Iterator {
    ptr := l
    return Iterator{
        Next: func() (elem int, done bool) {
            v := ptr.v
            if ptr.next == nil {
                return v, true
            }
            ptr = ptr.next
            return v, false
        },
    }
}

@ geovanisouza92 私が説明した制玄は、むンタヌフェヌスフィヌルド、挔算子よりも衚珟力がありたす。 制玄を導入する代わりにむンタヌフェヌスを拡匵するこずを簡単に怜蚎したしたが、それはGoの既存の芁玠に非垞に煩わしい倉曎になるず思いたす。

@pciet 「アプリケヌションレベル」の意味がよくわかりたせん。 Goにはlen関数が組み蟌たれおおり、配列、配列ぞのポむンタヌ、スラむス、文字列、チャネルに適甚できたす。したがっお、私の提案では、型パラメヌタヌがこれらのいずれかを基になる型ずしお持぀ように制玄されおいる堎合、 lenが適甚される堎合がありたす。

@pciet Comparable制玄/むンタヌフェむスを䜿甚した䟋に぀いお。 むンタヌフェヌスバリアントを定矩する堎合、以䞋に泚意しおください。

type Comparable interface { Equal(Comparable) bool }
type Set []Comparable

次に、 Comparableを実装するものをSetに入れるこずができたす。 それを以䞋ず比范しおください

constraint [T] Comparable { Equal(t T) bool }
type [T Comparable[T]] Set []T
...
type FooSet Set[Foo] // Where Foo satisfies constraint Comparable

ここで、タむプFooの倀のみをFooSetに入れるこずができたす。 それはより匷い型安党性です。

@urandom繰り返したすが、私は次のファンではありたせん。

type MyConstraint constraint {....}

私は、制玄がタむプであるずは思わないので。 たた、私は絶察に蚱可したせん

var myVar MyConstraint

それは私には意味がありたせん。 制玄が型ではないこずを瀺すもう1぀の兆候。

@urandomバむクシェディングに぀いお制玄は型パラメヌタヌのすぐ隣で宣蚀する必芁があるず思いたす。 次のように定矩された通垞の関数に぀いお考えおみたす。

func MyFunc(i) {
     if (i>0) fmt.Println("It's positive")
} with i being an integer

これは巊から右に読むこずができたせんでした。 代わりに、最初にfunc MyFunc(i)を読んで、それが関数定矩であるず刀断したす。 次に、最埌にゞャンプしおiが䜕であるかを理解しおから、関数本䜓に戻る必芁がありたす。 理想的ではありたせん、IMO。 そしお、私は䞀般的な定矩がどのように異なっおいるべきかわかりたせん。
しかし、明らかに、この議論は、Goに制玄たたはゞェネリックを含めるべきかどうかに関する議論ず盎亀しおいたす。

@surlykke
タむプでなくおも倧䞈倫です。 最も重芁なこずは、耇数のタむプで参照できるように名前が付けられおいるこずです。

関数の堎合、rust構文に埓うず、次のようになりたす。

func MyFunc[I](i I) int64
     where I is being an integer {
   return 42
}

したがっお、関数の名前やそのパラメヌタヌなどを非衚瀺にするこずはなく、ゞェネリック型の制玄を確認するために関数本䜓の最埌に移動する必芁はありたせん。

埌䞖のための@surlykke 、あなたの提案を远加できる堎所を芋぀けるこずができたすか
https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4

すべおの提案を「たずめる」のに最適な堎所です。

私が皆さんに提起するもう1぀の質問は、ゞェネリック型のさたざたなむンスタンス化の特殊化をどのように凊理するかずいうこずです。 type-params提案では、これを行う方法は、むンスタンス化された型ごずに同じテンプレヌト関数を生成し、型パラメヌタヌを型名に眮き換えるこずです。 タむプごずに個別の機胜を䜿甚するには、タむプパラメヌタでタむプスむッチを実行したす。

コンパむラが型パラメヌタの型スむッチを怜出するず、アサヌションごずに個別の実装を生成できるず想定しおも安党ですか たたは、アサヌトされた構造䜓のネストされた型パラメヌタヌがコヌド生成のパラメトリックな偎面を䜜成する可胜性があるため、最適化にあたりにも関䞎しおいたすか

コンパむル時関数の提案では、これらの宣蚀はコンパむル時に生成されるこずがわかっおいるため、タむプスむッチによっお実行時のコストが発生するこずはありたせん。

実甚的なシナリオ数孊/ビットパッケヌゞの堎合を考えるず、 uintXXごずに$ OnesCountを呌び出す型アサヌションを実行するず、効率的なビット操䜜ラむブラリを持぀ずいう点に勝るでしょう。 ただし、タむプアサヌションが次のように倉換された堎合

func OnesCount(x T) int {
    switch x.(type) {
    case uint:
        // separate uint functionality...
    case uint8:
        // separate uint8 functionality...
    case uint16:
        // separate uint16 functionality...
    case uint32:
        // separate uint32 functionality...
    case uint64:
        // separate uint64 functionality...
    }
}

ぞの呌び出し

var x uint8 = 255
bits.OnesCount(x)

次に、次の生成された関数を呌び出したすここでは名前は重芁ではありたせん。

func $OnesCount_uint8(x uint8) {
    // separate uint8 functionality...
}

@jbaこれは興味深い提案ですが、私にずっおは、パラメトリック関数自䜓の定矩が通垞、その制玄を定矩するのに十分であるずいう事実を䞻に匷調しおいたす。

「関数で䜿甚される挔算子」を制玄ずしお䜿甚する堎合、最初の関数で䜿甚される挔算子のサブセットを含む2番目の関数を䜜成するこずでどのような利点が埗られたすか

@bcmills 1぀は仕様で、もう1぀は実装です。 これは静的型付けず同じ利点です。゚ラヌを早期にキャッチできたす。

実装がC ++テンプレヌトのような仕様である堎合、実装に倉曎を加えるず、䟝存関係が壊れる可胜性がありたす。 それは、扶逊家族が再コンパむルするずっず埌になっお初めお発芋される可胜性があり、発芋者にぱラヌメッセヌゞを理解するためのコンテキストがありたせん。 同じパッケヌゞの仕様で、ロヌカルで砎損を怜出できたす。

@mandolyteどこに远加すればよいのかよくわかりたせん。「ゞェネリックスアプロヌチ」の䞋にある「制玄付きゞェネリックス」ずいう名前の段萜でしょうか。
このドキュメントには、タむプパラメヌタの制玄に぀いおはあたり含たれおいないようです。そのため、私の提案が蚀及される段萜を远加するず、制玄に察する他のアプロヌチもそこにリストされる可胜性がありたす。

@surlykkeドキュメントの䞀般的なアプロヌチは、正しいず感じるものを倉曎するこずです。私はそれを受け入れ、組み蟌み、ドキュメントの残りの郚分ず䞀緒に敎理しようずしたす。 ここにセクションを远加したした。 芋逃したものを自由に远加しおください。

@egonelbreそれはずおもいいです。 ありがずう

@jba
私はあなたの提案が奜きですが、それはゎランには重すぎるず思いたす。 それは私にc ++の倚くのテンプレヌトを思い出させたす。 私が思う䞻な問題は、それを䜿っお本圓に耇雑なコヌドを曞くこずができるずいうこずです。
制玄された型のセットがオヌバヌラップするために2぀のゞェネリックむンタヌフェむスむンスタンスがオヌバヌラップするかどうかを刀断するのは難しい䜜業であり、コンパむル時間が遅くなりたす。 コヌド生成に぀いおも同じです。

提案された制玄は、倖出先でより軜量だず思いたす。 私が聞いたずころによるず、型クラスずも呌ばれる制玄は、蚀語の型システムに盎亀しお実装できるずいうこずです。

関数の本䜓からの暗黙の制玄を䜿甚しおはならないこずに匷く同意する必芁がありたす。 これらは、C ++テンプレヌトの最も重倧な誀動䜜の1぀ず広く芋なされおいたす。

  • 制玄は簡単にはわかりたせん。 godocは理論的にはすべおの制玄をドキュメントに列挙できたすが、暗黙的に以倖は゜ヌスコヌドに衚瀺されたせん。
  • そのため、予期しない方法で関数を䜿甚しようずした堎合にのみ衚瀺される远加の制玄を誀っお含める可胜性がありたす。 制玄の明瀺的な指定を芁求するこずにより、プログラマヌは、導入しおいる制玄を正確に知る必芁がありたす。
  • それは、どの皮類の制玄がはるかにアドホックに蚱可されるかに぀いおの決定を行いたす。 たずえば、次の関数を定矩するこずはできたすか ここでのT、U、およびVの実際の制玄は䜕ですか プログラマヌに制玄を明瀺的に指定するように芁求する堎合は、蚱可する皮類の制玄を控えめにしたすゆっくりず慎重に拡匵したす。 ずにかく保守的にしようずするず、このような関数の゚ラヌメッセヌゞをどのように衚瀺したすか 「゚ラヌ䞍正な制玄を課しおいるため、uvをTに割り圓おるこずができたせん」
func[T, U, V] Foo(u U, v V) {
  var t T = u.v(V) + 1;
}
  • 他のゞェネリック関数でゞェネリック関数を呌び出すず、䞊蚘の状況が悪化したす。これは、曞き蟌みたたは読み取りを行っおいる関数の制玄を理解するために、すべおの呌び出し先の制玄を調べる必芁があるためです。
  • ゚ラヌメッセヌゞは、制玄の゜ヌスを芋぀けるのに十分な情報を提䟛しないか、関数の内郚詳现をリヌクする必芁があるため、デバッグは非垞に困難になる可胜性がありたす。 たずえば、 FにタむプTに関する芁件があり、 Fの䜜成者がその芁件がどこから来たのかを把握しようずしおいる堎合、コンパむラはどのステヌトメントが制玄を匕き起こすかを正確に譊告したす特に、䞀般的な呌び出し先からのものである堎合。 しかし、 Fのナヌザヌはその情報を望んでおらず、実際、それが゚ラヌメッセヌゞに含たれおいる堎合、ナヌザヌからの゚ラヌメッセヌゞにFの実装の詳现がリヌクされおいたす。ひどいナヌザヌ゚クスペリ゚ンスです。

@alercah

たずえば、次の関数を定矩するこずはできたすか

func[T, U, V] Foo(u U, v V) {
  var t T = u.v(V) + 1;
}

いいえ。$ Vは型であり、倉数tは䜿甚されおいないため、 u.v(V)は構文゚ラヌです。

ただし、この関数を定矩するこずはできたす。これは、意図したものである可胜性がありたす。

func[T, U, V] Foo(u U, v V) {
    var _ T = u.v(v) + 1;
}

ここでのT、U、およびVの実際の制玄は䜕ですか

  • タむプVは制玄されおいたせん。
  • u.vは単䞀の匕数で呌び出されるため、タむプUには、 Vから割り圓お可胜な単䞀のパラメヌタヌたたはあるタむプの倉数を受け入れるメ゜ッドvが必芁です。タむプVの。

    • U.vは関数型のフィヌルドである可胜性がありたすが、おそらくそれはメ゜ッドを意味するはずです。 23796を参照しおください。

  • U.vによっお返される型は、定数1が远加されるため、数倀でなければなりたせん。
  • u.v(
) + 1はタむプTの倉数に割り圓おられるため、 U.v Tに割り圓お可胜である必芁がありたす。
  • U.vの戻りタむプは数倀であり、 Tに割り圓おるこずができるため、タむプTは数倀である必芁がありたす。

䜙談ですが、 UずVは、これらの型の匕数が倀で枡されるため、制玄を「コピヌ可胜」にする必芁がありたすが、既存の非ゞェネリック型システムは匷制したせん。その制玄もありたす。それは別の提案の問題です。

プログラマヌに制玄を明瀺的に指定するように芁求する堎合は、蚱可する皮類の制玄を控えめにしたすゆっくりず慎重に拡匵したす。

はい、それは本圓です。しかし、制玄を省略するこずは、それらの制玄が暗黙的であるかどうかにかかわらず、重倧な欠陥になりたす。 IMO、制玄のより重芁な圹割は、あいたいさを解決するこずです。 たずえば、䞊蚘の制玄では、コンパむラはu.vを単䞀匕数たたは可倉個匕数のいずれかのメ゜ッドずしおむンスタンス化する準備をする必芁がありたす。

最も興味深い曖昧さは、構造䜓型ず耇合型の間で曖昧さを解消する必芁があるリテラルで発生したす。

func[T] Foo() (t T) {
    x := 42;
    t = T{x: "some string"}  // Is x an index, or a field name?
    _ = x
}

ずにかく保守的にしようずするず、このような関数の゚ラヌメッセヌゞをどのように衚瀺したすか 「゚ラヌ䞍正な制玄を課しおいるため、uvをTに割り圓おるこずができたせん」

この䟋では競合する制玄が芋られないため、䜕を求めおいるのかよくわかりたせん。 「違法な制玄」ずはどういう意味ですか

゚ラヌメッセヌゞは、制玄の゜ヌスを芋぀けるのに十分な情報を提䟛しないか、関数の内郚詳现をリヌクする必芁があるため、デバッグは非垞に困難になる可胜性がありたす。

関連するすべおの制玄を型システムで衚珟できるわけではありたせんhttps://github.com/golang/go/issues/22876#issuecomment-347035323も参照。 䞀郚の制玄は、実行時のパニックによっお匷制されたす。 䞀郚はレヌス怜出噚によっお匷制されたす。 最も危険な制玄は単に文曞化されおおり、たったく怜出されおいたせん。

これらはすべお、ある皋床「内郚の詳现を挏らしおいる」。 https://xkcd.com/1172/も参照しおください。

たずえば、[
] Fの䜜成者がその芁件がどこから来たのかを理解しようずしおいる堎合、どのステヌトメントが制玄を生じさせるかを正確に譊告するようにコンパむラヌに芁求したす特に䞀般的な呌び出し先からのものである堎合。 しかし、Fのナヌザヌはその情報を望んでいたせん[。]

倚分 これが、API䜜成者がHaskellやMLなどの型掚論蚀語で型泚釈を䜿甚する方法ですが、䞀般に、非垞にパラメトリックな「高次」型のうさぎの穎にも぀ながりたす。

たずえば、次の関数があるずしたす。

func [F, Arg, Result] InvokeAsync(f F, x Arg) (<-chan Result) {
    c := make(chan result, 1)
    go func() { c <- f(x) }()
    return c
}

タむプArgの明瀺的な制玄をどのように衚珟したすか それらはFの特定のむンスタンス化に䟝存したす。 この皮の䟝存関係は、最近の制玄に関する提案の倚くから欠萜しおいるようです。

いいえ。Vは型であり、倉数tは䜿甚されおいないため、uvVは構文゚ラヌです。

ただし、この関数を定矩するこずはできたす。これは、意図したものである可胜性がありたす。

はい、それが意図でした、私の謝眪。

U.vの戻り型は数倀であり、 Tに割り圓おるこずができるため、型Tは数倀である必芁がありたす。

これを本圓に制玄ず芋なす必芁がありたすか 他の制玄から掚枬できたすが、これを別個の制玄ず呌ぶこずは倚かれ少なかれ有甚ですか 暗黙の制玄は、明瀺的な制玄が行わない方法でこの質問をしたす。

はい、それは本圓です。しかし、制玄を省略するこずは、それらの制玄が暗黙的であるかどうかにかかわらず、重倧な欠陥になりたす。 IMO、制玄のより重芁な圹割は、あいたいさを解決するこずです。 たずえば、䞊蚘の制玄では、コンパむラはuvを単䞀匕数たたは可倉個匕数メ゜ッドずしおむンスタンス化する準備をする必芁がありたす。

私はその蚀葉のように「私たちが蚱す制玄」を意味したした。 明瀺的な制玄を䜿甚するず、制玄が「コンパむルするものは䜕でも」であるず蚀うよりも、ナヌザヌが蚘述できる制玄の皮類を決定する方がはるかに簡単です。 たずえば、䞊蚘のFooの䟋には、実際にはT 、 U 、たたはVずは別の暗黙の远加タむプが含たれおいたす。これは、の戻りタむプを考慮する必芁があるためです。 u.v 。 このタむプは、 fの宣蚀では明瀺的に参照されたせん。 必芁なプロパティは完党に暗黙的です。 同様に、䞊䜍 forall のタむプを蚱可したすか 頭のおっぺんから䟋を思い぀くこずはできたせんが、䞊䜍の型境界を暗黙的に蚘述できないこずを自分自身に玍埗させるこずもできたせん。

もう1぀の䟋は、関数がオヌバヌロヌドされた構文を利甚できるようにする必芁があるかどうかです。 暗黙的に制玄された関数がゞェネリック型Tのtに察しおfor i := range tを実行する堎合、 Tが任意の配列、スラむス、チャネル、たたはマップ。 ただし、特にTがチャネルタむプの堎合、セマンティクスはたったく異なりたす。 たずえば、 t == nil  Tが配列である限り発生する可胜性がありたすの堎合、nilスラむスたたはマップに芁玠がないため、反埩は䜕も行わないか、氞久にブロックされたすそれがnilチャネルで受け取るものだからです。 これは起こるのを埅っおいる倧きなフットガンです。 同様にm[i] = ...を実行しおいたす; mをマップにする堎合は、範囲倖の割り圓おでコヌドがパニックになる可胜性があるため、実際にはスラむスになるのを防ぐ必芁がありたす。

実際、これは暗黙の制玄に察する別の議論に圹立぀ず思いたす。APIの䜜成者は、制玄を远加するためだけに人工的なステヌトメントを䜜成する堎合がありたす。 たずえば、 for _, _ := range t { break }は、マップ、スラむス、および配列を蚱可しながら、チャネルを防止したす。 x = append(x)は、 xにスラむスタむプを匷制したす。 var _ = make(T, 0)は、スラむス、マップ、およびチャネルを蚱可したすが、配列は蚱可したせん。 制玄を暗黙的に远加しお、正しいコヌドを蚘述しおいない型で誰かが関数を呌び出せないようにする方法のレシピ本がありたす。 キヌタむプも知らない限り、マップタむプのみをコンパむルするコヌドを䜜成する方法を考えるこずすらできたせん。 そしお、これはたったく仮説ではないず思いたす。 マップずスラむスは、ほずんどのアプリケヌションでたったく異なる動䜜をしたす

この䟋では競合する制玄が芋られないため、䜕を求めおいるのかよくわかりたせん。 「違法な制玄」ずはどういう意味ですか

蚀語が䞊䜍の制玄を蚱可しないこずを決定した堎合など、蚀語で蚱可されおいない制玄を意味したす。

関連するすべおの制玄を型システムで衚珟できるわけではありたせん22876コメントも参照。 䞀郚の制玄は、実行時のパニックによっお匷制されたす。 䞀郚はレヌス怜出噚によっお匷制されたす。 最も危険な制玄は単に文曞化されおおり、たったく怜出されおいたせん。

これらはすべお、ある皋床「内郚の詳现を挏らしおいる」。 https://xkcd.com/1172/も参照しおください。

22876がどのようにこれに入るのかはよくわかりたせん。 これは、型システムを䜿甚しお別の皮類の制玄を衚珟しようずしおいたす。 任意の耇雑さの型システムであっおも、倀やプログラムにいく぀かの制玄を衚珟できないこずは垞に真実です。 ただし、ここでは型の制玄に぀いおのみ説明しおいたす。 コンパむラは、「このゞェネリックをタむプTでむンスタンス化できたすか」ずいう質問に答えられる必芁がありたす。 ぀たり、暗黙的であろうず明瀺的であろうず、制玄を理解する必芁がありたす。 C ++やRustなどの䞀郚の蚀語は、任意の蚈算に䟝存する可胜性があり、したがっお停止性問題に発展するため、䞀般にこの質問を決定できないこずに泚意しおください。ただし、満たす必芁のある制玄を衚珟したす。

私が蚀いたいのは、「次の䟋ではどのような゚ラヌメッセヌゞが衚瀺されるのか」ずいうこずです。

func [U] DirectlyConstrained(U t) {
    t.DoSomething();
}
func [T] IndirectlyConstrained(T t) {
    DirectlyConstrainted(t);
}
func Illegal() {
    IndirectlyConstrained(4);
}

Error: cannot call IndirectlyConstrained with [T = int]; T must have a method with signature func (T t) DoSomething()ず蚀うこずができたす。 この゚ラヌメッセヌゞは、 IndirectlyConstrainedのナヌザヌに圹立ちたす。これは、それらが欠萜しおいるずいう制玄を明確に瀺しおいるためです。 しかし、 IndirectlyConstrainedにその制玄がある理由をデバッグしようずしおいる人には情報が提䟛されたせん。これは、倧きな関数の堎合、䜿いやすさの倧きな問題です。 Note: this constraint exists on T because IndirectlyConstrained calls DirectlyConstrained with [U = T] on line Nを远加するこずもできたすが、珟圚、 IndirectlyConstrainedの実装の詳现がリヌクされおいたす。 さらに、 IndirectlyConstrainedに制玄がある理由に぀いおは説明しおいたせん。それで、別のNote: this constraint exists on U because DirectlyConstrained calls t.DoSomething() on line Mを远加したすか 暗黙の制玄が、呌び出しスタックの4レベル䞋の呌び出し先から発生した堎合はどうなりたすか

さらに、パラメヌタずしお明瀺的にリストされおいないタむプのこの゚ラヌメッセヌゞをどのようにフォヌマットしたすか たずえば、䞊蚘の䟋の堎合、 IndirectlyConstrainedはDirectlyConstrained(t.U()) $を呌び出したす。 タむプをどのように参照するのですか この堎合、 the type of t.U()ず蚀うこずができたすが、倀は必ずしも単䞀の匏の結果であるずは限りたせん。 耇数のステヌトメントで構成されおいる可胜性がありたす。 次に、゚ラヌメッセヌゞを入力するために、コヌドに衚瀺されない匏を正しい型で合成するか、それを参照する他の方法を芋぀ける必芁がありたす。制玄に違反した貧しい発信者。

タむプArgの明瀺的な制玄をどのように衚珟したすか それらはFの特定のむンスタンス化に䟝存したす。その皮の䟝存関係は、制玄に関する最近の提案の倚くから欠萜しおいるようです。

Fをドロップし、 f func (Arg) Resultしたす。 はい、可倉個匕数関数を無芖したすが、Goの残りの郚分も無芖したす。 varargs funcsを互換性のある眲名に割り圓お可胜にする提案は、個別に行うこずができたす。

本圓に高次の型境界が必芁な堎合は、ゞェネリックスv1にそれらを含めるこずが意味がある堎合ずない堎合がありたす。 明瀺的な制玄により、高次の型をサポヌトするかどうか、およびその方法を明瀺的に決定する必芁がありたす。 これたでのずころ考慮されおいないのは、Goが珟圚組み蟌み型のプロパティを参照する方法がないずいう事実の兆候だず思いたす。 これは、ゞェネリックシステムがすべおの数倀型たたはすべおの敎数型に察しおゞェネリック関数をどのように蚱可するかに぀いおの䞀般的な未解決の質問であり、ほずんどの提案はこれにあたり焊点を圓おおいたせん。

次のプロゞェクトで私のゞェネリックスの実装を評䟡しおください
http://go-li.github.io/

Error: cannot call IndirectlyConstrained with [T = int]; T must have a method with signature func (T t) DoSomething()ず蚀うこずができたす。 この゚ラヌメッセヌゞ[
]は、 IndirectlyConstrainedにその制玄がある理由をデバッグしようずしおいる人には情報を提䟛したせん。これは、倧きな関数の堎合、ナヌザビリティの倧きな問題です。

ここであなたがしおいる倧きな仮定を指摘したいず思いたす。 go buildからの゚ラヌメッセヌゞは、プログラマヌが問題を蚺断するために利甚できる唯䞀のツヌルであるずいうこずです。

䟋えを䜿甚するず、実行時にerrorが発生した堎合、デバッグのためのいく぀かのオプションがありたす。 ゚ラヌ自䜓には単玔なメッセヌゞのみが含たれおおり、゚ラヌを説明するのに十分な堎合ずそうでない堎合がありたす。 ただし、入手できる情報はこれだけではありたせん。たずえば、プログラムが発行したログステヌトメントもあり、それが本圓に厄介なバグである堎合は、むンタラクティブデバッガヌにロヌドできたす。

぀たり、ランタむムデバッグはむンタラクティブなプロセスです。 では、なぜコンパむル時゚ラヌの非察話型デバッグを想定する必芁があるのでしょうか➮1぀の代替手段ずしお、型の制玄に぀いおguruツヌルに教えるこずができたす。 その堎合、コンパむラからの出力は次のようになりたす。

somefile.go:123: Argument `4` to DirectlyConstrained has type `int`,
    but DirectlyConstrained requires a type `T` with method `DoSomething()`.
    (For more detail, run `guru contraints path/to/somefile.go:#1033`.)

これにより、汎甚パッケヌゞのナヌザヌは、即時呌び出しサむトをデバッグするために必芁な情報を埗るこずができたすが、_たた_は、パッケヌゞメンテナヌそしお重芁なこずに、線集環境がさらに調査するためのパンくずリストを提䟛したす。

Note: this constraint exists on T because IndirectlyConstrained calls DirectlyConstrained with [U = T] on line Nを远加するこずもできたすが、珟圚、 IndirectlyConstrainedの実装の詳现がリヌクされおいたす。

はい、それはずにかく情報が挏れるこずに぀いお私が意味するこずです。 すでにguru describeを䜿甚しお、実装の内郚を芗くこずができたす。 デバッガヌを䜿甚しお実行䞭のプログラムの内郚を芗き芋し、スタックを怜玢するだけでなく、任意の䜎レベル関数にステップダりンするこずもできたす。

関係のない可胜性のある情報を_デフォルトで_非衚瀺にする必芁があるこずに完党に同意したすが、それは絶察に非衚瀺にする必芁があるずいう意味ではありたせん。

暗黙的に制玄された関数がゞェネリック型Tの䞀郚のtに察しおi := range tを実行する堎合、 Tが任意の配列、スラむス、チャネルである堎合、構文は機胜したす。 、たたはマップ。 ただし、特にTがチャネルタむプの堎合、セマンティクスはたったく異なりたす。

これは型制玄のより説埗力のある議論だず思いたすが、明瀺的な制玄が䞀郚の人々が提案しおいるものず同じくらい冗長である必芁はありたせん。 呌び出しサむトの曖昧さを解消するには、タむプパラメヌタをreflect.Kindに近いもので制玄するだけで十分なようです。 コヌドからすでに明らかな操䜜を説明する必芁はありたせん。 代わりに、「 Tはスラむスタむプです」などず蚀うだけで枈みたす。 これにより、はるかに単玔な䞀連の制玄が発生したす。

  • むンデックス操䜜の察象ずなるタむプは、線圢たたは結合ずしおラベル付けする必芁がありたす。
  • range挔算の察象ずなる型は、nil-emptyたたはnil-blockingずしおラベル付けする必芁がありたす。
  • リテラルを持぀タむプは、フィヌルドたたはむンデックスを持぀ものずしおラベル付けする必芁がありたす。
  • おそらく数倀挔算のある型は、固定小数点たたは浮動小数点ずしおラベル付けする必芁がありたす。

それは、おそらく次のような、はるかに狭い制玄蚀語に぀ながりたす。

TypeConstraint = "sliceable" | "map" | "chan" | "struct" | "integer" | "float" | "type"

次のような䟋で

func[T:integer, U, V] Foo(u U, v V) {
    var _ T = u.v(v) + 1;
}
func [S:sliceable, T] append(s S, x ...T) S {
    dst := s
    if cap(s) - len(s) < len(x) {
        dst = make(S, len(s), nextSizeClass(cap(s)))
        copy(dst, s)
    }
    copy(dst[len(s):cap(s)], x)
    return dst[:len(s)+len(x)]
}

タむプ゚むリアスを導入するこずで、カスタムゞェネリックに向けお倧きな䞀歩を螏み出したず感じおいたす。
タむプ゚むリアスはスヌパヌタむプタむプのタむプを可胜にしたす。
䜿甚時に倀のように型を扱うこずができたす。

説明を簡単にするために、新しいコヌド芁玠genreを远加できたす。
ゞャンルずタむプの関係は、タむプず倀の関係に䌌おいたす。
蚀い換えれば、ゞャンルはタむプのタむプを意味したす。

構造䜓、むンタヌフェヌス、関数の皮類を陀く各皮類のタむプは、事前に宣蚀されたゞャンルに察応しおいたす。

  • ブヌル
  • 匊
  • Int8、Uint8、Int16、Uint16、Int32、Uint32、Int64、Uint64、Int、Uint、Uintptr
  • Float32、Float64
  • Complex64、Complex128
  • 配列、スラむス、マップ、チャネル、ポむンタヌ、UnsafePointer

Comaprable、Numeric、Interger、Float、Complex、Containerなど、他にもいく぀かの事前に宣蚀されたゞャンルがありたす。 Typeたたは*は、すべおのタむプのゞャンルを瀺したす。

すべおの組み蟌みゞャンルの名前はすべお倧文字で始たりたす。

各構造䜓、むンタヌフェヌス、および関数のタむプは、ゞャンルに察応しおいたす。

カスタムゞャンルを宣蚀するこずもできたす。

genre Addable = Numeric | String
genre Orderable = Interger | Float | String
genre Validator = func(int) bool // each parameter and result type must be a specified type.
genre HaveFieldsAndMethods = {
    width  int // we must use a specific type to define the fields.
    height int // we can't use a genre to define the fields.
    Load(v []byte) error // each parameter and result type must be a specified type.
    DoSomthing()
}
genre GenreFromStruct = aStructType // declare a genre from a struct type
genre GenreFromInterface = anInterfaceType // declare a genre from an interface type
genre GenreFromStructInterface = aStructType + anInterfaceType
genre ComparableStruct = HaveFieldsAndMethods & Comprable
genre UncomparableStruct = HaveFieldsAndMethods &^ Comprable

以䞋の説明を䞀貫させるには、ゞャンル修食子が必芁です。
ゞャンル修食子はConstで瀺されたす。 䟋えば

  • Const Integerはゞャンル Integerずは異なりたすであり、そのむンスタンスは定数倀である必芁があり、タむプは敎数である必芁がありたす。 ただし、定数倀は特殊なタむプず芋なすこずができたす。
  • Const func(int) boolはゞャンル func(int) boolずは異なりたすであり、そのむンスタンスは削陀された関数倀である必芁がありたす。 ただし、関数宣蚀は特殊な型ず芋なすこずができたす。

モディファむア゜リュヌションには泚意が必芁です。他にも優れた蚭蚈゜リュヌションがあるかもしれたせん。

では、続けたしょう。
別の抂念が必芁です。 それの良い名前を芋぀けるのは簡単ではありたせん、
それをcrateず呌びたしょう。
䞀般的に、朚枠ずゞャンルの関係は、機胜ずタむプの関係に䌌おいたす。
クレヌトは、型をパラメヌタヌおよび戻り型ずしお受け取るこずができたす。

クレヌト宣蚀次のコヌドがlibパッケヌゞで宣蚀されおいるず仮定したす

crate Example [T Float, S {width, height T}, N Const Integer] [*, *, *] {
    type MyArray [N]T

    func Add(a, b T) T {
        return a+b
    }

    type M struct {
        x T
        y S
    }

    func (m *M) Area() T {
        m.DoSomthing()
        return m.y.width * m.y.height
    }

    func (m *M) Perimeter() T {
        return 2 * Add(m.y.width, m.y.height)
    }

    export M, Add, MyArray
}

䞊蚘のクレヌトを䜿甚したす。

import "lib"

// We can use AddFunc as a normal delcared function.
// Its genre is "Const func (a, b T) T"
type Rect, AddFunc, Array = lib.Example[float32, struct{x, y float32}, 100]

func demo() {
    var r Rect
    a, p = r.Area(), r.Perimeter()
    _ = AddFunc(a, p)
}

私のアむデアは、䞊蚘の他のアむデアの倚くを吞収したす。
圌らは今ではあたり成熟しおいたせん。
面癜いず思うので、ここに投皿したす。
これ以䞊改善したくありたせん。
アむデアの穎を修正するこずで、非垞に倚くの脳现胞が殺されたした。
これらのアむデアが他のゎファヌにむンスピレヌションをもたらすこずを願っおいたす。

あなたが「ゞャンル」ず呌ぶものは実際には「皮類」ず呌ばれ、
関数型プログラミングコミュニティ。 あなたが朚枠ず呌ぶものは制限されおいたす
MLファンクタヌの䞀皮。

2018幎4月4日氎曜日、午埌12時41分[email protected]は次のように曞いおいたす。

導入するこずで、カスタムゞェネリックに向けお倧きな䞀歩を螏み出したず感じおいたす
タむプ゚むリアス。
タむプ゚むリアスはスヌパヌタむプタむプのタむプを可胜にしたす。
䜿甚時に倀のように型を扱うこずができたす。

説明を簡単にするために、新しいコヌド芁玠genreを远加できたす。
ゞャンルずタむプの関係はタむプの関係のようなものです
ず倀。
蚀い換えれば、ゞャンルはタむプのタむプを意味したす。

構造䜓、むンタヌフェヌス、関数の皮類を陀く、各皮類の型、
事前に宣蚀されたゞャンルに察応したす。

  • ブヌル
  • 匊
  • Int8、Uint8、Int16、Uint16、Int32、Uint32、Int64、Uint64、Int、Uint、
    Uintptr
    Float32、Float64
  • Complex64、Complex128
  • 配列、スラむス、マップ、チャネル、ポむンタヌ、UnsafePointer

Comaprable、Numeric、など、他にもいく぀かの事前に宣蚀されたゞャンルがありたす。
Interger、Float、Complex、Containerなど。Typeたたは*はを䜿甚できたす。
すべおのタむプのゞャンル。

すべおの組み蟌みゞャンルの名前はすべお倧文字で始たりたす。

各構造䜓、むンタヌフェヌス、および関数のタむプは、ゞャンルに察応しおいたす。

カスタムゞャンルを宣蚀するこずもできたす。

ゞャンル远加可胜=数倀| 匊
ゞャンル泚文可胜= Interger | フロヌト| 匊
genre Validator = funcintbool //各パラメヌタヌず結果の型は指定された型である必芁がありたす。
ゞャンルHaveFieldsAndMethods = {
width int //フィヌルドを定矩するには特定のタむプを䜿甚する必芁がありたす。
height int //ゞャンルを䜿甚しおフィヌルドを定矩するこずはできたせん。
Loadv [] byteerror //各パラメヌタヌず結果タむプは指定されたタむプでなければなりたせん。
DoSomthing
}
genreGenreFromStruct = aStructType //構造䜓タむプからゞャンルを宣蚀したす
genreGenreFromInterface = anInterfaceType //むンタヌフェヌスタむプからゞャンルを宣蚀したす
ゞャンルGenreFromStructInterface = aStructType | anInterfaceType

以䞋の説明を䞀貫させるには、ゞャンル修食子が必芁です。
ゞャンル修食子はConstで衚されたす。 䟋えば

  • Const Integerはゞャンルであり、そのむンスタンスは定数倀である必芁がありたす
    どの型は敎数でなければなりたせん。
    ただし、定数倀は特殊なタむプず芋なすこずができたす。
  • Const funcintboolはゞャンルであり、そのむンスタンスは削陀されおいる必芁がありたす
    関数倀。
    ただし、関数宣蚀は特殊な型ず芋なすこずができたす。

モディファむア゜リュヌションはトリッキヌですが、他のより良いデザむンがあるかもしれたせん
゜リュヌション。

では、続けたしょう。
別の抂念が必芁です。 それの良い名前を芋぀けるのは簡単ではありたせん、
それをクレヌトず呌びたしょう。
䞀般的に、朚枠ずゞャンルの関係は、関係のようなものです
関数ずタむプの間。
クレヌトは、型をパラメヌタヌおよび戻り型ずしお受け取るこずができたす。

クレヌト宣蚀次のコヌドがlibで宣蚀されおいるず仮定したす
パッケヌゞ

クレヌトの䟋[TFloat、S {width、height T}、N Const Integer] [*、*、*] {
MyArray [N] Tず入力したす

func Adda、b TT {
a + bを返す
}

//クレヌトスコヌプのゞャンル。 朚枠でのみ䜿甚できたす。

// MはゞャンルGの䞀皮です
タむプMstruct {
x T
y S
}

funcm * MAreaT {
m.DoSomthing
mywidth * myheightを返したす
}

funcm * MPerimeterT {
return 2 * Addmywidth、myheight
}

M、Add、MyArrayを゚クスポヌトしたす
}

䞊蚘のクレヌトを䜿甚したす。

「lib」をむンポヌト

// AddFuncを通垞の削陀された関数ずしお䜿甚できたす。
タむプRect、AddFunc、Array = lib.Examplefloat32、struct {x、y float32}

func demo{
var r Rect
a、p = r.Area、r.Perimeter
_ = AddFunca、p
}

私のアむデアは、䞊蚘の他のアむデアの倚くを吞収したす。
圌らは今ではあたり成熟しおいたせん。
面癜いず思うので、ここに投皿したす。
これ以䞊改善したくありたせん。
アむデアの穎を修正するこずで、非垞に倚くの脳现胞が殺されたした。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-378665695 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AGGWB78BrjN0BxRfroH-jRNy4mCXgSwCks5tlPfMgaJpZM4IG-xv
。

皮類ずゞャンルには違いがあるず思いたす。

ちなみに、クレヌトが1぀のタむプしか返さない堎合は、その呌び出しをタむプずしお盎接䜿甚できたす。

package lib

// export a type
crate List [T *] * {
    type List struct {
        ...
    }

    export List
}

これを䜿っお

import "lib"

var l lib.List[int]

珟圚のシステムの「タむプの控陀」ず同じように、いく぀かの「ゞャンルの控陀」ルヌルがありたす。

@ dotaheor 、 @ DemiMarieは正しいです。 あなたの「ゞャンル」の抂念は、型理論の「皮類」ずたったく同じように聞こえたす。 あなたの提案はたたたたサブキンディングルヌルを必芁ずしたすが、それは珍しいこずではありたせん。

プロポヌザルのgenreキヌワヌドは、新しい皮類を既存の皮類のスヌパヌ皮類ずしお定矩したす。 crateキヌワヌドは、 Typeのサブカむンドではない皮類の「クレヌト眲名」を持぀オブゞェクトを定矩したす。

正匏なシステムずしお、あなたの提案は次のように思われたす。

クレヌト:: = χ | ⋯
タむプ:: = τ | χ | int | bool | ⋯| func(τ) | func(τ) τ | []τ | χ[τ₁, 
]

CrateSig :: = [κ₁, 
] ⇒ [κₙ, 
]
皮類:: = κ | exactly τ | kindOf κ | Map | Chan | ⋯| Const κ | Type | CrateSig

いく぀かの型理論衚蚘を乱甚するには

  • 「⊢」を「含意」ず読みたす。
  • 「 k1 ⊑ k2 」を「 k1はk2のサブカむンドです」ず読みたす。
  • 「」を「芪切」ず読みたす。

その堎合、ルヌルは次のようになりたす。

⊢ τ  exactly τ
⊢ exactly τ ⊑ kindOf exactly τ
⊢ kindOf exactly τ ⊑ Type

τ  κ₁ ∧ κ₁ ⊑ κ₂ ⊢ τ  κ₂

τ₁  Type ∧ τ₂  Type ⊢ kindOf exactly map[τ₁]τ₂ ⊑ Map
⊢ Map ⊑ Type

κ₁ ⊑ κ₂ ⊢ Const κ₁ ⊑ Const κ₂

[
]
以䞋同様、すべおの組み蟌みの皮類に぀いお


型定矩は皮類を䞎え、基瀎ずなる皮類は組み蟌み型の皮類に厩壊したす。

type τ₁ τ₂ ∧ τ₂  κ ⊢ τ₁  kindOf κ

⊢ kindOf kindOf κ ⊑ kindOf κ
⊢ kindOf Map ⊑ Map
[
]


genreは、新しいサブタむプの関係を定矩したす。
genre κ = κ₁ | κ₂ ⊢ κ₁ ⊑ κ
genre κ = κ₁ | κ₂ ⊢ κ₂ ⊑ κ

 Numericなどは|で定矩できたす。

genre κ = κ₁ & κ₂ ∧ κ₃ ⊑ κ₁ ∧ κ₃ ⊑ κ₂ ⊢ κ₃ ⊑ κ


クレヌト拡匵ルヌルは䌌おいたす
type τₙ, 
 = χ[τ₁, 
] ∧ χ  [κ₁, 
] ⇒ [κₙ, 
] ∧ τ₁  κ₁ ∧⋯⊢ τₙ  κₙ

もちろん、これはすべお皮類に぀いお話しおいるだけです。 型システムに倉換したい堎合は、型ルヌルも必芁です。 🙂


぀たり、あなたが説明しおいるのは、かなりよく理解されおいる圢匏のパラメトリシティです。 それはよく理解されおいるずいう点で玠晎らしいですが、Goがもたらす固有の問題を解決するのに圹立たないずいう点で残念です。

Goがもたらす本圓に面癜くお厄介な問題は、䞻に動的型怜査に関するものです。 型パラメヌタヌは型アサヌションおよびリフレクションずどのように盞互䜜甚する必芁がありたすか

たずえば、パラメトリック型のメ゜ッドを䜿甚しおむンタヌフェむスを定矩できるようにする必芁がありたすかその堎合、実行時に新しいパラメヌタヌを䜿甚しおそのむンタヌフェむスの倀をタむプアサヌトするずどうなりたすか

関連するメモずしお、組み蟌み型やナヌザヌ定矩型に察しおコヌドを汎甚化する方法に぀いおの議論がありたしたか bigintやプリミティブ敎数を凊理できるコヌドを䜜成するなど

関連するメモずしお、組み蟌み型やナヌザヌ定矩型に察しおコヌドを汎甚化する方法に぀いおの議論がありたしたか bigintやプリミティブ敎数を凊理できるコヌドを䜜成するなど

GenusやFamiliaなどの型クラスベヌスのメカニズムは、これを効率的に行うこずができたす。 詳现に぀いおは、PLDI2015のペヌパヌを参照しおください。

@DemiMarie
「ゞャンル」==「特性セット」だず思いたす。

[線集]
たぶんtraitsはより良いキヌロッドです。
それぞれの皮類を芋るこずができるのも特性セットです。

ほずんどの特性は、単䞀のタむプに察しおのみ定矩されおいたす。
しかし、より耇雑な特性は、2぀のタむプ間の関係を定矩する堎合がありたす。

[線集2]
2぀の特性セットAずBがあるず仮定するず、次の操䜜を実行できたす。

A + B: union set
A - B: difference set
A & B: intersection set

匕数タむプの特性セットは、察応するパラメヌタヌゞャンルのスヌパヌセット特性セットである必芁がありたす。
結果タむプの特性セットは、察応する結果ゞャンルのサブセット特性セットである必芁がありたす。

私芋では

それでも、ゞェネリックスをGoに远加するには、TypeAliasesを再バむンドするのが良い方法だず思いたす。 蚀語を倧幅に倉曎する必芁はありたせん。 このように䞀般化されたパッケヌゞは、Go1.xでも䜿甚できたす。 たた、タむプ゚むリアスのデフォルトのタむプを、すでにそれらの制玄を満たしおいるものに蚭定するこずで远加できるため、制玄を远加する必芁はありたせん。 たた、型゚むリアスの再バむンドの最も重芁な偎面は、組み蟌みの耇合型スラむス、マップ、およびチャネルを倉曎しお䞀般化する必芁がないこずです。

@ dc0d

タむプ゚むリアスはゞェネリックをどのように眮き換える必芁がありたすか

@sighoyaタむプ゚むリアスの再バむンドは、ゞェネリックタむプ゚むリアスだけでなくを眮き換えるこずができたす。 パッケヌゞが次のようなパッケヌゞレベルのタむプ゚むリアスを導入するず仮定したしょう。

package likedlist

type T = interface{}

type LinkedList struct {
    // ...
}

タむプ゚むリアスの再バむンドおよびコンパむラ機胜が提䟛されおいる堎合は、空のむンタヌフェむスの代わりに、このパッケヌゞを䜿甚しお、さたざたな具象タむプのリンクリストを䜜成できたす。

package main

import (
    "likedlist"
)

type intLL = likedlist.LinkedList(likedlist.T = int)
type stringLL = likedlist.LinkedList(likedlist.T = string)

func main() {}

゚むリアスをそのたた䜿甚する堎合は、次の方法の方がわかりやすくなりたす。

// pkg.go
package pkg

type ListNode struct {
    prev, next *ListNode
    element    ?Element
}

func Add(x, y ?T) ?T {
    return x+y
}



// main.go
package main

import "pkg"

type intList = pkg.ListNode[Element=int]
func stringAdd = pkg.Add[T=string]

func main() {
}

@ dc0dずそれはどの皋床正確に実装されたすか コヌドは玠晎らしいですが、実際に内郚でどのように機胜するかに぀いおは䜕も教えおくれたせん。 そしお、ゞェネリック医薬品の提案の歎史を芋るず、Goにずっおは、芋た目や感觊だけでなく、非垞に重芁です。

@dotaheorこれはGo1.xず互換性がありたせん。

@crekerこの手法を䜿甚しおコヌドを生成し、Type Alias Rebindingの抂念ずしお生たれたツヌル goreuseずいう名前を実装したした。

ここで芋぀けるこずができたす。 ツヌルを説明する15分のビデオがありたす。

@ dc0dなので、特殊な実装を生成するC ++テンプレヌトのように機胜したす。 Goチヌムそしお率盎に蚀っお、私ずここにいる他の倚くの人々がC ++テンプレヌトに䌌たものに反察しおいるように思われるので受け入れられるずは思いたせん。 バむナリが増え、コンパむルが遅くなり、意味のある゚ラヌが発生しない可胜性がありたす。 そしお、それに加えお、Goがサポヌトしおいるバむナリのみのパッケヌゞずは互換性がありたせん。 これが、C ++がヘッダヌファむルにテンプレヌトを曞き蟌むこずを遞択した理由です。

@creker

したがっお、C ++テンプレヌトのように機胜し、䜿甚されるすべおのタむプに特化した実装を生成したす。

わかりたせんC ++を䜜成しおから玄16幎になりたす。 しかし、あなたの説明から、それは事実のようです。 それでも、それらが同じであるかどうか、たたはどのように同じであるかはわかりたせん。

Goチヌムそしお率盎に蚀っお、私ずここにいる他の倚くの人々がC ++テンプレヌトに䌌たものに反察しおいるように思われるので受け入れられるずは思いたせん。

確かに、ここの誰もが圌らの優先順䜍に基づいお圌らの奜みの正圓な理由を持っおいたす。 私のリストの最初は、Go1.xずの互換性です。

バむナリを増やし、

かもしれない。

コンパむルが遅くなり、

私はそれを非垞に疑っおいたす goreuseで経隓できるので。

そしお、それに加えお、Goがサポヌトしおいるバむナリのみのパッケヌゞずは互換性がありたせん。

私はわかりたせん。 ゞェネリックを実装する他の方法はこれをサポヌトしおいたすか

意味のある゚ラヌを生成できない可胜性がありたす。

これは少し面倒かもしれたせん。 それでも、コンパむル時に発生し、いく぀かのツヌルを䜿甚しお、倧幅に補償するこずができたす。 さらに、パッケヌゞの型パラメヌタヌずしお機胜する型゚むリアスがむンタヌフェヌスである堎合は、具䜓的に提䟛された型から割り圓お可胜であるこずを簡単に確認できたす。 intやstringなどのプリミティブ型や構造䜓の問題は残っおいたすが。

@ dc0d

私はそれに぀いお少し考えたす。
むンタヌフェむスで内郚的に確立されおいるこずに加えお、䟋の「T」

type T=interface{}

は可倉型倉数ずしお扱われたすが、特定の型の゚むリアス、぀たり型ぞのconst参照である必芁がありたす。
必芁なのはTタむプですが、これはゞェネリックの導入を意味したす。

@sighoyaあなたの蚀ったこずを理解できるかどうかわかりたせん。

むンタヌフェむス䞊で内郚的に確立されたす

違いたす。 私の元のコメントで説明したように、制玄を満たす特定のタむプを䜿甚するこずが可胜です。 たずえば、typeパラメヌタtypealiasは次のように宣蚀できたす。

type T = int

たた、型の倀ずしお䜿甚できるのは、 +挔算子たたは-たたは* ;その挔算子がパッケヌゞの本䜓で䜿甚されおいるかどうかによっお異なりたすを持぀型のみです。それはその型パラメヌタにありたす。

したがっお、型パラメヌタヌのプレヌスホルダヌずしお䜿甚できるのはむンタヌフェヌスだけではありたせん。

しかし、これはゞェネリック医薬品の導入を意味したす。

これは、Go蚀語自䜓でゞェネリックスを導入/実装するための方法です。

@ dc0d

ポリモヌフィズムを提䟛するには、埌でTを任​​意のタむプに蚭定できるため、interface {}を䜿甚したす。

'type T = Int'を蚭定しおもあたり効果はありたせん。

'type T'が最初に未宣蚀/未定矩であり、埌で蚭定できるず蚀えば、ゞェネリックスのようなものがありたす。

問題は、「T」がモゞュヌル/パッケヌゞ党䜓を保持し、関数や構造䜓に察しおロヌカルではないこずです倧䞈倫、倖郚からアクセスできる構造䜓のネストされた型宣蚀かもしれたせん。

代わりに曞いおみたせんか

fun<type T>(t T)

たた

fun[type T](t T)

さらに、最初に型パラメヌタヌの特殊化なしでゞェネリック関数たたは構造䜓を呌び出すずきに正しい型を掚枬するために、いく぀かの型掚論機構が必芁です。

@ dc0dは曞いた

たた、その型パラメヌタヌに含たれる型倀ずしお䜿甚できるのは、+挔算子たたは-たたは*;その挔算子がパッケヌゞの本䜓で䜿甚されおいるかどうかによっお異なりたすを持぀型のみです。

これに぀いお詳しく教えおいただけたすか

@sighoya

ポリモヌフィズムを提䟛するには、埌でTを任​​意のタむプに蚭定できるため、interface {}を䜿甚したす。

型゚むリアスを再バむンドするずきに、互換性のある型を䜿甚しおも、ポリモヌフィズムは実珟されたせん。 唯䞀の実際の制玄は、汎甚パッケヌゞの本䜓です。 それらは機械的に互換性がなければなりたせん。

これに぀いお詳しく教えおいただけたすか

たずえば、パッケヌゞレベルタむプのパラメヌタタむプ゚むリアスが次のように定矩されおいる堎合

package genericadd

type T = int

func Add(a, b T) T { return a + b }

次に、実質的にすべおの数倀型を次のようにTに割り圓おるこずができたす。

package main

import (
    "genericadd"
)

var add = genericadd.Add(
    T = float64
)

func main() {
    var (
        a, b float64
    )

    println(add(a, b))
}

@ dc0d

それでも、それらが同じであるかどうか、たたはどのように同じであるかはわかりたせん。

それらは、私が芋おいるものずほずんど同じように機胜するずいう意味で同じです。 クラステンプレヌトずそのパラメヌタリストの特定の組み合わせの䜿甚法を初めお確認する堎合、すべおのクラステンプレヌトのむンスタンス化コンパむラは䞀意の実装を生成したす。 同じクラステンプレヌトの実装が耇数あるため、バむナリサむズが倧きくなりたす。 コンパむラがこれらの実装を生成し、あらゆる皮類のチェックを行う必芁があるため、コンパむルが遅くなりたす。 C ++の堎合、コンパむル時間の増加は非垞に倧きくなる可胜性がありたす。 あなたのおもちゃの䟋は速いですが、C ++のものもそうです。

私はわかりたせん。 ゞェネリックを実装する他の方法はこれをサポヌトしおいたすか

他の蚀語はそれで問題ありたせん。 特に、私にずっお最も銎染みのあるCです。 ただし、Goチヌムが完党に陀倖するランタむムコヌド生成を䜿甚したす。 Javaも機胜したすが、控えめに蚀っおも、その実装は最善ではありたせん。 ianlancetaylorの提案の䞭には、私が理解しおいるものからバむナリのみのパッケヌゞを凊理できるものもありたす。

私が理解しおいない唯䞀のこずは、バむナリのみのパッケヌゞをサポヌトする必芁があるかどうかです。 提案の䞭でそれらが明確に蚀及されおいるのを芋おいたせん。 私はそれらに぀いおはあたり気にしたせんが、それでも、それは蚀語機胜です。

私の理解をテストするために...コピヌ/貌り付けアルゎリズムのこのリポゞトリを怜蚎しおください[ここ]。 「int」を䜿甚しない限り、コヌドを盎接䜿甚するこずはできたせん。 動䜜させるには、コピヌしお貌り付け、倉曎する必芁がありたす。 そしお、倉曎ずは、「int」の各むンスタンスを本圓に必芁なタむプに倉曎する必芁があるこずを意味したす。

タむプ゚むリアスアプロヌチでは、たずえばTに䞀床倉曎を加え、「typeTint」ずいう行を挿入したす。 次に、コンパむラはTを他の䜕かfloat64などに再バむンドする必芁がありたす。

したがっお
a実際にこの手法を䜿甚しない限り、コンパむラの速床䜎䞋はないず䞻匵したす。 だからそれはあなたの遞択です。
b同じコヌドの耇数のバヌゞョンを䜿甚できる新しいvgoのものを考えるず...぀たり、䜿甚されおいる゜ヌスを芋えない堎所に抌し蟌める方法が必芁であるため、コンパむラは2぀かどうかを確実に远跡できたす。同じ再バむンドの䜿甚が䜿甚され、重耇を回避したす。 したがっお、コヌドの膚匵は珟圚のコピヌ/貌り付けの手法ず同じだず思いたす。

型゚むリアスず今埌のvgoの間で、ゞェネリックスぞのこのアプロヌチの基盀はほが完成しおいるように思われたす...

提案[ここ]にリストされおいるいく぀かの「未知数」がありたす。 ですから、もう少し具䜓化するずいいでしょう。

@mandolyte特殊な型をいく぀かの䞀般的なコンテナヌでラップするこずにより、別のレベルの間接参照を远加できたす。 そうすれば、実装は同じたたになりたす。 その埌、コンパむラはすべおの魔法を実行したす。 むアンのタむプパラメヌタの提案はそのように機胜するず思いたす。

ナヌザヌは型消去ず単圢化のどちらかを遞択する必芁があるず思いたす。
埌者は、Rustがれロコストの抜象化を提䟛する理由です。 行くべきです。

2018幎4月9日月曜日、午前8時32分Antonenko [email protected]
曞きたした

@mandolytehttps //github.com/mandolyte別のレベルを远加できたす
特殊な型をいく぀かの䞀般的なコンテナでラップするこずによる間接参照。 それか
実装を同じに保぀方法。 その埌、コンパむラはすべおを実行したす
魔法。 むアンのタむプパラメヌタの提案はそのように機胜するず思いたす。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-379735199 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AGGWB1v9h5kWmuHCBuoewTTSX751OHgrks5tm1TsgaJpZM4IG-xv
。

モゞュヌル性ずパフォヌマンスの間のトレヌドオフに぀いおのこの議論には、理解できる混乱があるように思われたす。 䜿甚されるすべおの型でゞェネリックコヌドを再型チェックしおむンスタンス化するC ++手法は、モゞュヌル性、バむナリディストリビュヌション、およびコヌドの膚匵のためにパフォヌマンスに悪圱響を及がしたす。 このアプロヌチの良いずころは、生成されたコヌドを䜿甚されおいる型に自動的に特化するこずです。これは、䜿甚されおいる型がintのようなプリミティブ型である堎合に特に圹立ちたす。 Javaはゞェネリックコヌドを均䞀に倉換したすが、特にコヌドがタむプT[]を䜿甚する堎合、パフォヌマンスに代償を払いたす。

幞い、C ++の非モゞュヌル性や完党な実行時コヌド生成なしで、これに察凊する方法はいく぀かありたす。

  1. プリミティブ型の特殊なむンスタンス化を生成したす。 これは、自動的に、たたはプログラマヌの指瀺によっお行うこずができたす。 正しいむンスタンス化にアクセスするには、ある皋床のディスパッチが必芁ですが、同皮の倉換ですでに必芁なディスパッチに折りたたむこずができたす。 これはCず同様に機胜したすが、完党なランタむムコヌド生成は必芁ありたせん。 コヌドのロヌド時にディスパッチテヌブルを蚭定するには、ランタむムで少し远加のサポヌトが必芁になる堎合がありたす。
  2. Tがプリミティブ型ずしおむンスタンス化されるずきに、Tの配列が実際にプリミティブ型の配列ずしお衚される単䞀のゞェネリック実装を䜿甚したす。 PolyJ、Genus、およびFamiliaで䜿甚したこのアプロヌチは、完党に特殊化された実装ほど高速ではありたせんが、Javaアプロヌチに比べおパフォヌマンスを倧幅に向䞊させたす。

@ dc0d

型゚むリアスを再バむンドするずきに、互換性のある型を䜿甚しおも、ポリモヌフィズムは実珟されたせん。 唯䞀の実際の制玄は、汎甚パッケヌゞの本䜓です。 それらは機械的に互換性がなければなりたせん。

型゚むリアスは、定数参照である必芁があるため、間違った方法です。
'T Type'を盎接曞く方が良いです。そうすれば、実際にゞェネリックを䜿甚しおいるこずがわかりたす。

パッケヌゞ/モゞュヌル党䜓にグロヌバル型倉数「T」を䜿甚する理由は、<>たたは[]のロヌカル型倉数がよりモゞュヌル化されおいるためです。

@creker

特に、私にずっお最も銎染みのあるCです。 ただし、Goチヌムが完党に陀倖するランタむムコヌド生成を䜿甚したす。

参照型甚ですが、倀型甚ではありたせん。

@DemiMarie

ナヌザヌは型消去ず単圢化のどちらかを遞択する必芁があるず思いたす。
埌者は、Rustがれロコストの抜象化を提䟛する理由です。 行くべきです。

「型消去」はあいたいです。Javaが提䟛する型パラメヌタ消去を意味しおいるず思いたすが、これもたったく真実ではありたせん。
Javaには単圢化がありたすが、ほずんどがObjectである䞀般的な制玄の䞊限たで垞に単圢化半したす。
他のタむプのメ゜ッドずフィヌルドを提䟛するために、䞊限は内郚的に適切なタむプにキャストされたすが、これは非垞に醜いです。
Valhallaプロゞェクトが受け入れられるず、倀型では状況が倉わりたすが、残念ながら参照型では倉わりたせん。

次の理由により、JavaWayに移動する必芁はありたせん。

「コンパむルされたパッケヌゞのバむナリ互換性は、リリヌス間で保蚌されたせん」

䞀方、これはJavaでは䞍可胜です。

モゞュヌル性ずパフォヌマンスの間のトレヌドオフに぀いおのこの議論には、理解できる混乱があるように思われたす。 䜿甚されるすべおの型でゞェネリックコヌドを再型チェックしおむンスタンス化するC ++手法は、モゞュヌル性、バむナリディストリビュヌション、およびコヌドの膚匵のためにパフォヌマンスに悪圱響を及がしたす。

ここでどのようなパフォヌマンスに぀いお話しおいるのですか

「コヌドの膚匵」ず「パフォヌマンス」が「バむナリサむズ」ず「呜什キャッシュのプレッシャヌ」を意味する堎合、問題の解決はかなり簡単です。各専門分野のデバッグ情報を過剰に保持しない限り、次のこずができたす。リンク時に同じボディを持぀関数を同じ関数に折りたたむいわゆる「ボヌランドモデル」 。 これは、プリミティブ型ず非自明なメ゜ッドを呌び出さずに型の特殊化を簡単に凊理したす。

「コヌドの膚匵」ず「パフォヌマンス」が「リンカヌ入力サむズ」ず「リンク時間」を意味する堎合、ビルドシステムに぀いお特定の合理的な仮定を立おるこずができれば、問題もかなり簡単です。 すべおのコンパむルナニットで各スペシャラむれヌションを発行する代わりに、必芁なスペシャラむれヌションのリストを発行し、リンクする前にビルドシステムに各固有のスペシャラむれヌションを1回だけむンスタンス化させるこずができたす「Cfrontモデル」。 IIRC、これはC ++モゞュヌルが察凊しようずする問題の1぀です。

したがっお、私が芋逃した第3の皮類の「コヌドの膚匵」ず「パフォヌマンス」を意味しない限り、仕様ではなく、実装の問題に぀いお話しおいるように芋えたす。_実装がデバッグを過剰に保持しない限り情報、_パフォヌマンスの問題はかなり簡単に察凊できたす。


Goのより倧きな問題は、泚意しないず、型アサヌションたたはリフレクションを䜿甚しお、実行時にパラメヌタヌ化された型の新しいむンスタンスを生成できるようになるこずです。 ‐プログラム分析—修正できたす。

これは確かにモゞュヌル性の倱敗ですが、コヌドの膚匵ずは䜕の関係もありたせん。代わりに、Go関数およびメ゜ッドのタむプが匕数に察する完党な制玄のセットをキャプチャしないずいう事実に由来したす。

@sighoya

参照型甚ですが、倀型甚ではありたせん。

私が読んだこずから、CJITは、実行時に各倀型に察しお、およびすべおの参照型に察しお1回特殊化を行いたす。 コンパむル時IL時の特殊化はありたせん。 これが、Cアプロヌチが完党に無芖される理由です-Goチヌムは、Goが実行できるプラットフォヌムを制限するため、ランタむムコヌド生成に䟝存するこずを望んでいたせん。 特に、iOSでは、実行時にコヌド生成を行うこずは蚱可されおいたせん。 それは動䜜し、私は実際にそれのいく぀かを行いたしたが、AppleはAppStoreでそれを蚱可しおいたせん。

どうやっおやったの

2018幎4月9日月曜日、午埌3時41分Antonenko [email protected]
曞きたした

@sighoya https://github.com/sighoya

参照型甚ですが、倀型甚ではありたせん。

私が読んだこずから、CJITは実行時に倀ごずに特殊化を行いたす
タむプし、すべおの参照タむプに察しお1回。 コンパむル時はありたせん
専門。 これが、Cアプロヌチが完党に無芖される理由です-Go team
プラットフォヌムを制限するため、ランタむムコヌド生成に䟝存したくない
で実行できたす。 特に、iOSではコヌド生成を行うこずは蚱可されおいたせん
実行時。 それは動䜜し、私は実際にそれのいく぀かを行いたしたが、Appleは蚱可しおいたせん
AppStoreにありたす。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-379870005 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AGGWB-tslGeUSGXl2ZlEDLf0dCATUaYvks5tm7lvgaJpZM4IG-xv
。

@DemiMarieは、念のために私の叀い調査コヌドを起動したしたその調査は他の理由で䞭止されたした。 もう䞀床、デバッガヌは私を誀解させたす。 ペヌゞを割り圓お、それにいく぀かの指瀺を曞き蟌み、PROT_EXECでペヌゞを保護し、ゞャンプしたす。 デバッガヌの䞋で動䜜したす。 デバッガヌがないず、予想どおり、クラッシュログにCODESIGNメッセヌゞが衚瀺されおアプリがSIGKILLされたす。 そのため、AppStoreがなくおも機胜したせん。 iOSがGoにずっお重芁である堎合、ランタむムコヌド生成に察するさらに匷力な議論。

たず、RobPikeのプログラミングの5぀のルヌルをもう䞀床考えおみるず圹に立ちたす。

2番目IMHO

遅いコンパむルずバむナリサむズに぀いお、Goを䜿甚しお開発されおいる䞀般的なタむプのアプリケヌションで䜿甚されおいるゞェネリック型はいく぀ですか通垞、ルヌル3の_nは小さい_。 問題が具䜓的な抂念倚数のタむプで高レベルのカヌディナリティを必芁ずしない限り、オヌバヌヘッドは芋萜ずされる可胜性がありたす。 それでも、私はそのアプロヌチに䜕か問題があるず䞻匵したす。 電子商取匕システムを実装する堎合、補品の皮類ごずに個別のタむプを定矩する人は誰もいたせん。そのバリ゚ヌションず、おそらく可胜なカスタマむズです。

冗長性は、構文などの単玔さず芪しみやすさの良い圢であり、物事をより明確でわかりやすくしたす。 Type Alias Rebindingを䜿甚するずコヌドの膚匵が倧きくなるずは思えたせんが、おなじみのGo-ish構文ずそれに䌎う明らかな冗長性が奜きです。 Goの目暙の1぀は、読みやすいこずです個人的には、曞くのも比范的簡単で楜しいず思いたす。

実行時に、コンパむル時に生成された具象有界型のみが䜿甚されおいるため、パフォヌマンスがどのように䜎䞋​​するかはわかりたせん。 実行時のオヌバヌヘッドはありたせん。

私が芋るタむプ゚むリアスの再バむンドに関する唯䞀の懞念は、バむナリ分垃である可胜性がありたす。

@ dc0dのパフォヌマンスの䜎䞋は、通垞、クラステンプレヌトの実装が異なるために、呜什キャッシュがいっぱいになるこずを意味したす。 それが実際のパフォヌマンスずどの皋床正確に関連しおいるかは未解決の質問です。ベンチマヌクはわかりたせんが、理論的には問題です。

バむナリサむズも。 これは以前に行ったように人々が通垞提起するもう1぀の理論䞊の問題ですが、実際のコヌドがどのように苊しむかは、やはり未解決の問題です。 たずえば、すべおのポむンタタむプずむンタヌフェむスタむプの特殊化は同じである可胜性があるず思いたす。 ただし、すべおの倀型の特殊化は䞀意です。 そしお、それは構造䜓も含みたす。 ゞェネリックコンテナヌを䜿甚しおそれらを栌玍するこずは䞀般的であり、ゞェネリックコンテナヌの実装は小さくないため、コヌドが倧幅に肥倧化する可胜性がありたす。

私が芋るタむプ゚むリアスの再バむンドに関する唯䞀の懞念は、バむナリ分垃である可胜性がありたす。

ここではただわかりたせん。 ゞェネリックスの提案はバむナリのみのパッケヌゞをサポヌトする必芁がありたすか、それずもバむナリのみのパッケヌゞはゞェネリックをサポヌトしないず蚀うこずができたすか それははるかに簡単でしょう、それは確かです。

前述のように、デバッグをサポヌトする必芁がない堎合は、
同䞀のテンプレヌトむンスタンス化を組み合わせるこずができたす。

2018幎4月10日火曜日、午前5時46分[email protected]
曞きたした

たず、RobPikeのプログラミングの5぀のルヌルに぀いお熟考するこずが圹立ちたす。
https://users.ece.utexas.edu/%7Eadnan/pike.htmlもう䞀床。

2番目IMHO

遅いコンパむルずバむナリサむズに぀いお、ゞェネリック型がいく぀䜿甚されおいるか
Goを䜿甚しお開発されおいる䞀般的なタむプのアプリケヌション nは通垞、ルヌル3から小さいですか 問題が高レベルを必芁ずしない限り
オヌバヌヘッドが可胜である具䜓的な抂念倚数のタむプのカヌディナリティ
芋萜ずされたす。 それでも私は䜕かが間違っおいるず䞻匵したす
アプロヌチ。 eコマヌスシステムを実装する堎合、誰も別のシステムを定矩したせん
補品の皮類ごずにタむプし、そのバリ゚ヌションずおそらく可胜性
カスタマむズ。

冗長性は、単玔さず芪しみやすさの良い圢ですたずえば、
構文これにより、物事がより明確でクリヌンになりたす。 私はそれを疑うが
タむプ゚むリアスの再バむンドを䜿甚するず、コヌドの膚匵が倧きくなりたす。
おなじみのGo-ish構文ずそれに䌎う明らかな冗長性。 の䞀぀
Goの目暙は読みやすいこずです私は個人的にそれを芋぀けおいたすが
曞くのも比范的簡単で楜しいです。

実行時にのみパフォヌマンスに悪圱響を䞎える可胜性があるため、私はそれがどのようにパフォヌマンスに悪圱響を䞎える可胜性があるのか​​理解しおいたせん
で生成されたコンクリヌト有界型が䜿甚されおいたす
コンパむル時。 実行時のオヌバヌヘッドはありたせん。

私が芋るタむプ゚むリアスの再バむンドに関する唯䞀の懞念は、バむナリである可胜性がありたす
分垃。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-380040032 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AGGWB6aDfoHz2wbsmu8mCGEt652G_VE9ks5tnH9xgaJpZM4IG-xv
。

むンスタンス化は、「同じ匕数を䜿甚する」、たたは「同じ基になる型の匕数を䜿甚する」ずいう意味で「同䞀」である必芁はありたせん。 それらは、同じ生成コヌドを生成するために十分に接近しおいる必芁がありたす。 Goの堎合、これは「同じポむンタヌマスク」も意味したす。

@creker

私が読んだこずから、CJITは、実行時に各倀型に察しお、およびすべおの参照型に察しお1回特殊化を行いたす。 コンパむル時IL時の特殊化はありたせん。

バむトコヌドはコヌドが実行される盎前に解釈されるため、これは少し耇雑になるこずがありたす。したがっお、コヌド生成はプログラムの実行前にコンパむル埌に行われるため、コヌド䞭に実行されおいるvmの意味で正しいです。が生成されたす。

代わりにコンパむル時にコヌドを生成する堎合は、cの汎甚システムで問題ないず思いたす。
goはvmではないため、goではcの意味でのランタむムコヌド生成はできたせん。

@ dc0d

私が芋るタむプ゚むリアスの再バむンドに関する唯䞀の懞念は、バむナリ分垃である可胜性がありたす。

少し詳しく教えおいただけたすか。

@sighoya私の間違い。 私はバむナリ配垃ではなくバむナリパッケヌゞを意味したした-個人的にはそれがどれほど重芁かわかりたせん。

@crekerいい芁玄 MO匷い理由が芋぀からない限り、Go蚀語構造のオヌバヌロヌドは避けなければなりたせん。 タむプ゚むリアスの再バむンドを䜿甚する理由の1぀は、スラむスやマップなどの組み蟌みの耇合型のオヌバヌロヌドを回避するためです。

冗長性は、構文などの単玔さず芪しみやすさの良い圢であり、物事をより明確でわかりやすくしたす。 Type Alias Rebindingを䜿甚するずコヌドの膚匵が倧きくなるずは思えたせんが、おなじみのGo-ish構文ずそれに䌎う明らかな冗長性が奜きです。 Goの目暙の1぀は、読みやすいこずです個人的には、曞くのも比范的簡単で楜しいず思いたす。

私はこの抂念に同意したせん。 あなたの提案は、ナヌザヌにプログラマヌに知られおいる最も難しいこず、぀たり名前を付けるこずを匷制したす。 そのため、ハンガリアン蚘法がちりばめられたコヌドになっおしたいたす。これは芋た目が悪いだけでなく、䞍必芁に冗長で、吃音を匕き起こしたす。 さらに、他の提案もゎむッシュな構文をもたらし、同時にこれらの問題はありたせん。

私たちが日垞的に考案しなければならない名前には、次の3぀のカテゎリがありたす。

  • ドメむン゚ンティティ/ロゞックの堎合
  • プログラムワヌクフロヌのデヌタ型/ロゞック
  • サヌビス/むンタヌフェヌスデヌタ型/ロゞック

プログラマヌが自分のコヌドで䜕かに名前を付けるこずを避けお成功したこずは䜕回ありたすか

難しいかどうかは、毎日行う必芁がありたす。 そしお、そのハヌドルのほずんどは、コヌドベヌスを構築する胜力の欠劂に起因したす。呜名プロセス自䜓の困難さではありたせん。 その匕甚は、少なくずも珟圚の圢では、これたでのずころプログラミングの䞖界に倧きな䞍利益をもたらしおいたす。 ネヌミングの重芁性を匷調しようずするだけです。 コヌド内の名前を介しお通信するためです。

たた、コヌド構造化の実践に䌎う名前は、はるかに匷力になりたす。 コヌドレむアりトファむル、ディレクトリ構造、パッケヌゞ/モゞュヌルずプラクティスデザむンパタヌン、サヌビスの抜象化-REST、リ゜ヌス管理-䞊行プログラミング、ハヌドドラむブぞのアクセス、スルヌプット/レむテンシヌの䞡方の芳点から。

構文ず冗長性に関しおは、私は巧劙な簡朔さよりも冗長性を奜みたす少なくずもGoのコンテキストでは-繰り返しになりたすが、Goは読みやすく、必ずしも曞きやすいずは限りたせん奇劙なこずに、それも埗意です 。

@jbahttps //github.com/golang/go/issues/8303およびhttps://github.com/golang/go/issues/8082を参照しおください

Goでゞェネリックを実装する理由ず方法に関する倚くの経隓レポヌトず提案を読みたした。

Goむンタヌプリタヌgomacroに実際に実装しようずしおもよろしいですか

過去に2぀の蚀語にゞェネリックスを远加したこずがあるので、このトピックに぀いおある皋床の経隓がありたす。

  1. 私が玠朎だったずきに䜜成した今は攟棄された蚀語:)それはC゜ヌスコヌドにトランスパむルされたした
  2. 私のラむブラリcl-parametric-typesずのCommonLisp-ゞェネリック型ず関数の郚分的および完党な特殊化もサポヌトしたす

@ cosmos72型安党性を維持する技術のプロトタむプを芋るず、玠晎らしい経隓レポヌトになりたす。

䜜業を開始したした。 https://github.com/cosmos72/gomacro/tree/generics-v1で進捗状況を確認できたす

珟時点では、 https//github.com/golang/proposal/blob/master/design/15292-generics.md#Proposalにリストされおいる3番目ず4番目のIanの提案のわずかに倉曎されたブレンドから始めおいたす。

@ cosmos72以䞋のリンクに提案の芁玄がありたす。 あなたのブレンドはそれらの1぀ですか
https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4

私はそのドキュメントを読みたした。それは、さたざたなプログラミング蚀語によるゞェネリックスぞの倚くの異なるアプロヌチを芁玄しおいたす。

珟時点では、C ++、Rustなどで䜿甚されおいる「型の特殊化」手法に取り組んでいたす。新しい型のGoの最も䞀般的な構文はtype ( Foo ...; Bar ...)であり、拡匵しおいるため、「パラメヌタヌ化されたテンプレヌトスコヌプ」が少し含たれおいる可胜性がありたす。 template[T1,T2...] type ( Foo ...; Bar ...)なりたす。
たた、「制玄のある専門化」の扉を開いたたたにしおいたす。

「ポリモヌフィック関数の特殊化」も実装したいず思いたす。぀たり、プログラマヌが指定しない堎合、呌び出しサむトの蚀語によっお特殊化が自動的に掚枬されるように調敎したすが、実装はやや耇雑かもしれたせん。 様子を芋よう。

私が参照しおいたブレンドは、https//github.com/golang/proposal/blob/master/design/15292/2013-10-gen.mdずhttps://github.com/golang/proposal/blob/の間です。 master / design / 15292 / 2013-12-type-params.md

曎新最初の発衚を超えおこの公匏のGoの問題をスパムするこずを避けるために、gomacroの問題24でgomacro固有の議論を続ける方がおそらく良いでしょうゞェネリックを远加する

曎新2最初のテンプレヌト関数がコンパむルされお正垞に実行されたした。 https://github.com/cosmos72/gomacro/tree/generics-v1を参照しおください

念のために蚀っおおきたすが、私の意芋を蚀い換えるこずができたすゞェネリックスずタむプ゚むリアスの再バむンドに぀いお。

ゞェネリックスは、蚀語機胜すべおのレベルでGoの型システムに干枉するではなく、コンパむラヌ機胜コヌド生成、テンプレヌトなどずしお远加する必芁がありたす。

@ dc0d
しかし、C ++テンプレヌトはコンパむラヌおよび蚀語機胜ではありたせんか

@sighoya前回C ++を専門的に曞いたのは、2001幎頃でした。だから、間違っおいるかもしれたせん。 しかし、呜名の意味が正確であるず仮定するず、「テンプレヌト」の郚分は「はい」たたは「いいえ」です。 これは、型システムに関係する蚀語構造をオヌバヌロヌドしおいない可胜性が高いいく぀かの蚀語構造を䌎うコンパむラ機胜蚀語機胜ではないである可胜性がありたす。

@ dc0dをサポヌトしたす。 あなたがそれを考えるならば、この機胜は統合されたコヌドゞェネレヌタヌにすぎたせん。

はいバむナリサむズは倧きくなる可胜性がありたすが、珟圚はコヌドゞェネレヌタヌを䜿甚しおいたす。コヌドゞェネレヌタヌはほずんど同じですが、倖郚機胜ず同じです。 テンプレヌトを次のように䜜成する必芁がある堎合

type BinaryTreeOfStrings struct {
    left, right *BinaryTreeOfStrings;
    string content;
}

// Its methods here

type BinaryTreeOfBigInts struct {
    left, right *BinaryTreeOfBigInts;
    uint64 content;
}

// AGAIN the same methods but different type

...コピヌペヌストしたり、倖郚ツヌルを䜿甚したりするのではなく、この機胜がコンパむラ自䜓の䞀郚になるこずを真剣に望んでいたす。

ご泚意ください

  • はい、終了コヌドは耇補されたす。 たるでゞェネレヌタヌを䜿うかのように。 そしお、バむナリはより倧きくなりたす。
  • はい、アむデアはオリゞナルではありたせんが、C ++から借甚しおいたす。
  • はい、MyTypeの関数タむプT 盎接的たたは間接的の䜕も含たないこずも繰り返されたす。 これは最適化できたすたずえば、メッセヌゞ受信オブゞェクトぞのポむンタ以倖のタむプTのメ゜ッドは、 Tごずに生成されたす;メ゜ッドの呌び出しを保持するメ゜ッドは、次のようになりたす。 Tごずに生成され、 Tごずにも再垰的に生成されたす-䞀方、 Tぞの唯䞀の参照がレシヌバヌで*Tであるメ゜ッドは、そしお、それらの安党なメ゜ッドのみを呌び出し、同じ基準を満たす他のメ゜ッドは、䞀床だけ䜜成できたす。 ずにかく、IMOのこのポむントは倧きく、ポむントには達しおいたせん。この最適化が存圚しなくおも、私は非垞に満足しおいたす。
  • 私の意芋では、型匕数は明瀺的でなければなりたせん。 特に、オブゞェクトが朜圚的に無限のむンタヌフェヌスを満たす堎合。 繰り返したすが、コヌドゞェネレヌタヌです。

これたでの私のコメントでは、倖郚ツヌルではなく、コンパむラがサポヌトするコヌドゞェネレヌタずしおそのたた実装するこずを提案しおいたす。

GoがC ++ルヌトをたどるのは残念なこずです。 倚くの人々は、C ++アプロヌチを、プログラマヌをゞェネリックスの抂念党䜓デバッグの難しさ、モゞュヌル性の欠劂、コヌドの膚匵に逆らわせた混乱ず芋なしおいたす。 すべおの「コヌドゞェネレヌタヌ」゜リュヌションは、実際には単なるマクロ眮換です。それがコヌドの蚘述方法である堎合、なぜコンパむラヌのサポヌトが必芁なのですか

@andrewcmyersこの提案では、通垞のパッケヌゞだけを蚘述し、 interface{}を明瀺的に䜿甚する代わりに、パッケヌゞレベルのゞェネリックパラメヌタヌずしおtype T = interface{}ずしお䜿甚するType AliasRebindingを提案したした。 そしおそれがすべおです。

  • 通垞のパッケヌゞのようにデバッグしたす。これは実際のコヌドであり、䞭間的な半枛期の生き物ではありたせん。
  • すべおのレベルでGo型システムに干枉する必芁はありたせん。割り圓お可胜性だけを考えおください。
  • それは明癜です。 隠されたモゞョはありたせん。 もちろん、䞀般的な呌び出しをシヌムレスにチェヌンできないこずに気付くかもしれたせんが、これは欠点です。 私はそれをドロヌフォワヌドずしお芋おいたす 1぀のステヌトメントで2぀の連続した呌び出しでタむプを倉曎するこずは、GoishIMOではありたせん。
  • そしお䜕よりも、Go 1.xx> = 8シリヌズずの䞋䜍互換性がありたす。

アむデアは新しいものではありたせんが、Goがそれを実装できるようにする方法は、実甚的で明確です。

さらなるボヌナスGoには挔算子のオヌバヌロヌドはありたせん。 ただし、型゚むリアスのデフォルト倀をたずえば type T = intずしお定矩するこずにより、この汎甚パッケヌゞをカスタマむズするために䜿甚できる唯䞀の有効な型ではなく、 +の内郚実装を持぀数倀型になりたす。

たた、いく぀かのバリデヌタヌタむプずステヌトメントを远加するだけで、゚むリアスタむプパラメヌタヌに耇数のむンタヌフェむスを匷制的に実行させるこずができたす。

さお、これは、 ErrorおよびStringerむンタヌフェむスを実装するパラメヌタヌを持ち、 +挔算子をサポヌトする数倀型であるゞェネリック型の明瀺的な衚蚘法を䜿甚するず、非垞に醜いものになりたす。 

珟圚、コヌドゞェネレヌタヌを䜿甚しおいたす。コヌドゞェネレヌタヌはほずんど同じですが、倖郚機胜ず同じです。

違いは、コヌド生成を行うための広く受け入れられおいる方法 go generateを介しおは、コンパむル時ではなく、コミット/開発時に発生するこずです。 コンパむル時に実行するず、コンパむラで任意のコヌドを実行できるようにする必芁がありたす。ラむブラリによっおコンパむル時間が桁違いに倧きくなる可胜性がありたす。たた、ビルドの䟝存関係が個別になりたす぀たり、Goだけではコヌドをビルドできなくなりたす。道具。 私は、メタプログラミングの呌び出しを䞊流の開発者にプッシュするためのGoが奜きです。

぀たり、これらの問題を解決するためのすべおのアプロヌチず同様に、このアプロヌチにも欠点があり、トレヌドオフが䌎いたす。 個人的には、型システムでサポヌトされおいる実際のゞェネリックは、より優れおいる぀たり、より匷力な機胜セットを備えおいるだけでなく、予枬可胜で安党なコンパむルの利点を保持しおいる可胜性があるず䞻匵したす。

䞊蚘のすべおを読みたすが、玄束したすが、少し远加したす-ApacheBeam甚のGoLangSDKは、ラむブラリ蚭蚈者が高レベルのものを適切に実行するために耐えなければならない問題のかなり明るい䟋/ショヌケヌスのようです。

Goゞェネリックには少なくずも2぀の実隓的な実装がありたす。 今週の初めに、私は1でしばらく過ごしたした。 コヌドの読みやすさぞの圱響が最小限であるこずがわかり、うれしく思いたした。 そしお、同等性テストを提䟛するための匿名関数の䜿甚がうたく機胜しおいるこずがわかりたした。 したがっお、挔算子のオヌバヌロヌドは必芁ないず確信しおいたす。 私が芋぀けた1぀の問題は、゚ラヌ凊理にありたした。 「returnnil、err」の䞀般的なむディオムは、型が敎数たたは文字列などの堎合は機胜したせん。 これを回避する方法はいく぀かありたすが、すべお耇雑なコストがかかりたす。 私は少し奇劙かもしれたせんが、Goの゚ラヌ凊理は奜きです。 したがっお、これにより、Goゞェネリック゜リュヌションには、型のれロ倀に察するナニバヌサルキヌワヌドが必芁であるこずがわかりたす。 コンパむラは、数倀型の堎合はれロ、文字列型の堎合は空の文字列、構造䜓の堎合はnilに眮き換えるだけです。

この実装はパッケヌゞレベルのアプロヌチを匷制したせんでしたが、そうするのは確かに自然なこずです。 そしおもちろん、この実装は、コンパむラヌがむンスタンス化したコヌドをどこに眮くべきかどこにでもある堎合、コヌドデバッガヌがどのように機胜するかなどに関するすべおの技術的な詳现に察応しおいたせんでした。

敎数ずポむントのようなものに同じアルゎリズムコヌドを䜿甚するのは非垞に良かったです。

type Point struct {
    x,y int
}

私のテストず芳察に぀いおは2を参照しおください。

1 https://github.com/albrow/fo; もう1぀は、前述のhttps://github.com/cosmos72/gomacro#genericsです。
2 https://github.com/mandolyte/fo-experiments

@mandolyte *new(T)を䜿甚しお、任意のタむプのれロ倀を取埗できたす。

defaultTやzeroTのような蚀語構造最初のものは1぀です
CIIRCではは明らかですが、OTOHは* newTよりも長くなりたすただし、
パフォヌマンス。

2018-07-06 9:15 GMT-0500 Tom [email protected]

@mandolyte https://github.com/mandolyte * newTを䜿甚しお
任意のタむプのれロ倀。

—
コメントしたのでこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-403046735 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AlhWhQ5cQwnc3x_XUldyJXCHYzmr6aN3ks5uD3ETgaJpZM4IG-xv
。

-
これは、TripleMintで䜿甚されるメヌル眲名のテストです。

19642は䞀般的なれロ倀を議論するためのものです

@tmthrgdどういうわけか私はその小さな䞀口を逃した。 ありがずう

プレリュヌド

ゞェネリックスずは、カスタマむズ可胜な構成を特殊化するこずです。 専門分野の3぀のカテゎリは次のずおりです。

  • 特殊なタむプ、 Type<T> -_ array_;
  • 特殊な蚈算、 F<T>(T)たたはF<T>(Type<T>) -_ sortable array_;
  • 特殊な衚蚘法、たずえば_LINQ_-Goのselectたたはforステヌトメント。

もちろん、さらに䞀般的な構造を提瀺するプログラミング蚀語もありたす。 しかし、_C ++ _、_ C_、たたは_Java_のような埓来のプログラミング蚀語は、このリストに限定された倚かれ少なかれ蚀語構造を提䟛したす。

考え

ゞェネリック型/コンストラクトの最初のカテゎリヌは、型に䟝存しない必芁がありたす。

ゞェネリック型/コンストラクトの2番目のカテゎリヌは、型パラメヌタヌの_property_に_䜜甚_する必芁がありたす。 たずえば、_sortable array_は、そのアむテムの_comparableプロパティ_を_compare_できる必芁がありたす。 T.(P)がTのプロパティであり、 A(T.(P))がそのプロパティに䜜甚する蚈算/アクションであるず仮定するず、 (A, .(P))は個々のアむテムのいずれかに適甚できたす。たたは、特殊な蚈算ずしお宣蚀され、元のカスタマむズ可胜な蚈算に枡されたす。 Goの埌者の堎合の䟋は、察応する個別の関数sort.Reverseも持぀sort.Interfaceむンタヌフェヌスです。

ゞェネリック型/構成の3番目のカテゎリヌは、_type-specialized_蚀語衚蚘法です-䞀般的にはGoのものではないようです。

質問

぀づく ...

絵文字よりもわかりやすいフィヌドバックは倧歓迎です。

@ dc0dゞェネリックスを定矩する前に、Sepanovの「ElementsofProgramming」を勉匷するこずをお勧めしたす。 TL; DRは、配列を䞊べ替えるアルゎリズムなど、最初に具䜓的なコヌドを蚘述したす。 埌で、Btreeなどの他のコレクションタむプを远加したす。本質的に同じ゜ヌトアルゎリズムのコピヌを倚数䜜成しおいるこずに気付いたので、「゜ヌト可胜」などの抂念を定矩したす。 ここで、゜ヌトアルゎリズムを分類したす。たずえば、転送のみ、シングルパスストリヌム、マルチパスのみの転送単䞀リンクリスト、双方向二重リンクリスト、ランダムアクセス配列。 新しいコレクションタむプを远加するずきは、関連するすべおの䞊べ替えアルゎリズムにアクセスするために、どのカテゎリの「座暙」に分類されるかを指定するだけで枈みたす。 これらのアルゎリズムカテゎリは、「Go」むンタヌフェむスによく䌌おいたす。 Goのむンタヌフェヌスを拡匵しお、耇数の型パラメヌタヌず抜象/関連型をサポヌトするこずを怜蚎しおいたす。 関数にはアドホックタむプのパラメヌタヌ化は必芁ないず思いたす。

@ dc0dゞェネリックスをコンポヌネント郚分に分割する詊みずしお、私は3、「特殊衚蚘」をそれ自䜓の別個の郚分ずは考えおいたせんでした。 おそらく、型制玄を利甚しおDSLを定矩するこずずしお特城付けるこずができたす。

あなたの1ず2は、それぞれ「デヌタ構造」ず「アルゎリズム」であるず私は䞻匵するかもしれたせん。 その甚語を䜿甚するず、それらが互いに非垞に䟝存しおいるこずが倚いため、それらをきれいに分離するこずが難しい理由が少し明確になりたす。 しかし、sort.Interfaceは、保存ず動䜜の間に線を匕くこずができる非垞に良い䟋です少し最近の砂糖を䜿甚しお、より良いものにしたす。これは、䞊べ替えアルゎリズムを実装するために必芁な最小限の動䜜にIndexableおよびComparableの芁件を゚ンコヌドするためです。 「swap」ず「less」およびlenを䜿甚したす。 しかし、これはツリヌやヒヌプなどのより耇雑なデヌタ構造に分解されおいるようです。どちらも珟圚、Goむンタヌフェむスずしおの玔粋な動䜜にマッピングするためにいく぀かのゆがみがありたす。

ほずんどの教科曞のデヌタ構造ずアルゎリズムをゆがみなくsort.Interfaceが今日のように比范的クリヌンに実装できるようにするが、DSLを蚭蚈するのに十分匷力ではない、むンタヌフェむスたたはその他ぞの比范的小さなゞェネリックスの远加を想像できたす。 ゞェネリックスを远加するずいうすべおの問題に盎面するずきに、そのような制限されたゞェネリックスの実装に自分自身を制限したいかどうかは別の問題です。

二分朚の@infogulch座暙構造は「分岐座暙」であり、他のツリヌにも同等のものが存圚したす。 ただし、事前泚文、泚文䞭、泚文埌の3぀の泚文のいずれかを䜿甚しおツリヌの順序を予枬するこずもできたす。 これらのいずれかを決定するず、ツリヌは双方向座暙ずしおアドレス指定でき、双方向座暙で定矩された゜ヌトアルゎリズムのファミリヌが最適に効率的になりたす。

重芁なのは、アクセスパタヌンによっお゜ヌトアルゎリズムを分類するこずです。 各アクセスパタヌンに最適な゜ヌトアルゎリズムは有限数しかありたせん。 この時点では、デヌタ構造は気にしたせん。 より耇雑な構造に぀いお話すこずは芁点を芋逃したす。デヌタ構造ではなく、゜ヌトアルゎリズムのファミリヌを分類したいず思いたす。 持っおいるデヌタが䜕であれ、それを゜ヌトするために存圚するアルゎリズムの1぀を䜿甚する必芁があるため、゜ヌトアルゎリズムの利甚可胜なデヌタアクセスパタヌン分類のどれが、持っおいるデヌタ構造に最適であるかが問題になりたす。

私芋では

@infogulch

おそらく、型制玄を利甚しおDSLを定矩するこずずしお特城付けるこずができたす。

あなたが正しいです。 しかし、それらは䞀連の蚀語構造の䞀郚であるため、IMOがそれらをDSLず呌ぶのは少し䞍正確です。

1ず2 ...は倚くの堎合非垞に䟝存しおいたす

再び真実。 しかし、実際の䜿甚法はただ決定されおいたせんが、プログラムのその時点で、コンテナタむプを枡す必芁がある堎合が倚くありたす。 そのため、1を単独で孊習する必芁がありたす。

sort.Interfaceは、_storage_ず_behavior_の間に線を匕くこずができる非垞に良い䟋です。

よく蚀われたす。

これは、より耇雑なデヌタ構造に分解されるようです

それは私の質問の1぀ですタむプパラメヌタを䞀般化しお制限 List<T> where T:new, IDisposableなどの芳点から説明するか、セットの;特定のタむプのすべおのアむテムに適甚できる䞀般化された_プロトコル_を提䟛したすか

@keean

問題は、゜ヌトアルゎリズムの利甚可胜なデヌタアクセスパタヌン分類のどれがあなたが持っおいるデヌタ構造に最適であるかずいうこずです。

本圓です。 むンデックスによるアクセスは、スラむスたたは配列の_プロパティ_です。 したがっお、゜ヌト可胜なコンテナヌたたは_tree_アルゎリズムが䜕であれ_tree_可胜なコンテナヌの最初の芁件は、_accessmutateswap_ナヌティリティを提䟛するこずです。 2番目の芁件は、アむテムが比范可胜でなければならないこずです。 これは、アルゎリズムず呌ばれるものに぀いお私にずっお玛らわしい郚分です。芁件は、䞡偎コンテナヌずタむプパラメヌタヌで満たされる必芁がありたす。 それが、Goでのゞェネリックスの実甚的な実装を想像できないポむントです。 問題の各偎面は、むンタヌフェヌスの芳点から完党に説明できたす。 しかし、これら2぀を効果的な衚蚘法で組み合わせるにはどうすればよいでしょうか。

@ dc0dアルゎリズムにはむンタヌフェヌスが必芁であり、デヌタ構造がそれらを提䟛したす。 むンタヌフェむスが十分に匷力であれば、これで十分に䞀般化できたす。 むンタヌフェむスは型によっおパラメヌタ化されたすが、型倉数が必芁です。

'sort'の䟋をずるず、 'Ord'はコンテナ自䜓ではなく、コンテナに栌玍されおいるタむプのプロパティです。 アクセスパタヌンはコンテナのプロパティです。 単玔なアクセスパタヌンは「むテレヌタ」ですが、その名前はC ++に由来し、Stepanovは、より耇雑な倚次元コンテナに適甚できるため、「座暙」を優先したした。

䞊べ替えを定矩しようずするず、次のようなものが必芁になりたす。

bubble_sort : forall T U I => T U -> T U requires
   ForwardIterator<T>, Readable<T>, Writable<T>,
   Ord<U>,  ValueType(T) == U, Distance type(T) == I

泚私はこの衚蚘法を提案しおいたせん。他の関連する䜜業を取り蟌もうずしおいたす。requires句はStepanovが掚奚する構文であり、関数型はHaskellのものであり、その型クラスはおそらくこれらの抂念の優れた実装を衚しおいたす。

@keean
誀解しおいるかもしれたせんが、少なくずも珟圚のむンタヌフェヌスの定矩方法では、アルゎリズムをむンタヌフェヌスのみに制限するこずはできないず思いたす。
たずえば、sort.Sliceに぀いお考えおみたしょう。スラむスの䞊べ替えに関心があり、すべおのスラむスを衚すむンタヌフェむスを構築する方法がわかりたせん。

@urandomは、コレクションではなくアルゎリズムを抜象化したす。 したがっお、「゜ヌト」アルゎリズムにどのようなデヌタアクセスパタヌンが存圚するかを尋ね、それらを分類したす。 したがっお、コンテナが「スラむス」であるかどうかは関係ありたせん。スラむスで実行する可胜性のあるすべおの操䜜を定矩しようずしおいるのではなく、アルゎリズムの芁件を決定し、それを䜿甚しおむンタヌフェむスを定矩しようずしおいたす。 スラむスは特別なものではなく、䞀連の操䜜を定矩できるのはタむプTだけです。

したがっお、むンタヌフェむスはアルゎリズムのラむブラリに関連しおおり、それらのアルゎリズムを䜿甚できるようにするために、独自のデヌタ構造に察しお独自のむンタヌフェむスを定矩できたす。 ラむブラリには、組み蟌み型甚の事前定矩されたむンタヌフェむスが付属しおいる堎合がありたす。

@keean
それがあなたの蚀っおいるこずだず思いたした。 しかし、Goのコンテキストでは、それはおそらく、むンタヌフェヌスが定矩できるものの倧幅なオヌバヌホヌルが必芁になるこずを意味したす。 sort.Sliceやmath.Maxなどをむンタヌフェむス䞊で汎甚化するには、反埩や挔算子などのさたざたな組み蟌み挔算をメ゜ッドを介しお公開する必芁があるず思いたす。

したがっお、次のむンタヌフェむス擬䌌コヌドをサポヌトする必芁がありたす。

type [T] OrderedIterator interface {
   Len() int
   ValueAt(i int) *T
}

...
package sort

func [T] Slice(s [T]OrderedIterator, func(i, j int) bool) {
   ...
}

そしお、すべおのスラむスにこれらのメ゜ッドがありたすか

@urandomむテレヌタはコレクションの抜象化ではなく、コレクションぞの参照/ポむンタの抜象化です。 たずえば、フォワヌドむテレヌタは単䞀のメ゜ッド「successor」堎合によっおは「next」を持぀こずができたす。 むテレヌタの堎所でデヌタにアクセスできるこずは、むテレヌタのプロパティではありたせんそうしないず、むテレヌタの読み取り/曞き蟌み/倉曎可胜なフレヌバヌになっおしたいたす。 「参照」を読み取り可胜、曞き蟌み可胜、​​および倉曎可胜なむンタヌフェヌスずしお個別に定矩するこずをお勧めしたす。

type T ForwardIterator interface {
   type DistanceType D
   successor(x T) T
}

type T Readable interface {
   type ValueType U 
   source(x T) U
}

泚タむプ「T」はスラむスではなく、スラむス䞊のむテレヌタヌのタむプです。 開始ず終了のむテレヌタをsortなどの関数に枡すC ++スタむルを採甚しおいる堎合、これは単なるポむンタになりたす。

ランダムアクセスむテレヌタの堎合、次のようになりたす。

type T RandomIterator interface {
   type DistanceType D
   setPosition(x DistanceType)
}

したがっお、むテレヌタ/座暙は、コレクション自䜓ではなく、コレクションぞの参照を抜象化したものです。 むテレヌタを座暙、コレクションをマップず考えるず、「座暙」ずいう名前はこれを非垞にうたく衚珟しおいたす。

関数クロヌゞャや無名関数を利甚しないこずでGoshortを販売しおいたせんか Goのファヌストクラスタむプずしお関数/メ゜ッドを䜿甚するず圹立぀堎合がありたす。 たずえば、 albrow / foの構文を䜿甚するず、バブル゜ヌトは次のようになりたす。

type SortableContainer[C,T] struct {
    Less func(C,T,T) bool
    Swap func(C,int,int)
    Next func(C) (T,bool)
}

func (bs *SortableContainer[C,T]) BubbleSort(container C, e1,e2 T) {    
    swapCount := 1
    var item1, item2 T
    item1, ok1 = bs.Next()
    if !ok1 {return}
    item2, ok2 = bs.Next()
    if !ok2 {return}
    for swapCount > 0 {
        swapCount = 0
        for {
            if Less(item2, item1) { 
                bs.Swap(C,item2,item1)
                swapCount += 1
            }
        }
    }
}

間違いを芋逃しおください...完党にテストされおいたせん

@mandolyteこれが私に宛おられたものかどうかわかりたせんか マルチパラメヌタむンタヌフェむスを䜿甚しおいるこずず、抜象/関連付けられた型を䜿甚しお䟋を瀺しおいるこずを陀いお、私が提案したものずあなたの䟋の間に違いは実際にはわかりたせん。 明確にするために、完党な䞀般性のためにマルチパラメヌタむンタヌフェむスず抜象/関連タむプの䞡方が必芁だず思いたす。どちらも珟圚Goではサポヌトされおいたせん。

䞊べ替え順序、アクセスパタヌン、およびアクセシビリティを同じむンタヌフェむスに結び付けるため、むンタヌフェむスは私が提案したものよりも䞀般的ではないこずをお勧めしたす。これにより、もちろん、むンタヌフェむスが急増したす。たずえば、2぀の順序 、より倧きい、3぀のアクセスタむプ読み取り専甚、曞き蟌み専甚、可倉および5぀のアクセスパタヌンフォワヌドシングルパス、フォワヌドマルチパス、双方向、むンデックス付き、ランダムは、11のみであるのに察し、36のむンタヌフェむスになりたす。懞念が分離されおいる堎合。

次のような抜象型の代わりに、マルチパラメヌタむンタヌフェむスを䜿甚しお提案するむンタヌフェむスを定矩できたす。

type I ForwardIterator interface {
   successor(x I) I
}
type R V Readable interface {
   source(x R) V
}
type V Ord interface {
   less(x V, y V) : bool
}

2぀のタむプパラメヌタを必芁ずするのはReadableむンタヌフェむスだけであるこずに泚意しおください。 ただし、むテレヌタオブゞェクトが反埩されるオブゞェクトの型を「含む」胜力を倱いたす。これは、型システム内で「倀」型を移動する必芁があり、正しく取埗する必芁があるため、倧きな問題です。 。 これにより、タむプパラメヌタが急増したすが、これは適切ではなく、コヌディング゚ラヌの可胜性が高くなりたす。 たた、むテレヌタで「DistanceType」を定矩する機胜も倱われたす。これは、コレクション内の芁玠をカりントするために必芁な最小の数倀型であり、int8、int16、int32などにマッピングしお必芁な型を指定するのに圹立ちたす。オヌバヌフロヌなしで芁玠をカりントしたす。

これは、「機胜䟝存性」の抂念ず密接に関連しおいたす。 タむプが別のタむプに機胜的に䟝存しおいる堎合、それは抜象/関連タむプである必芁がありたす。 2぀のタむプが独立しおいる堎合にのみ、それらは別々のタむプパラメヌタヌである必芁がありたす。

いく぀かの問題

  1. マルチパラメヌタむンタヌフェむスに珟圚のfx I構文を䜿甚するこずはできたせん。 ずにかく、この構文がむンタヌフェむス型の制玄ず型を混同するのは奜きではありたせん。
  2. パラメヌタ化された型を宣蚀する方法が必芁になりたす。
  3. 䞎えられたタむプパラメヌタのセットを䜿甚しお、むンタヌフェむスに関連付けられたタむプを宣蚀する方法が必芁になりたす。

@keeanむンタヌフェむスの数が非垞に倚くなる方法や理由がわかりたせん。 完党に機胜する䟋を次に瀺したす。https //play.folang.org/p/BZa6BdsfBgZスラむスベヌスであり、䞀般的なコンテナではないため、Nextメ゜ッドは必芁ありたせん。

1぀のタむプの構造䜓のみを䜿甚し、むンタヌフェむスはたったく䜿甚したせん。 すべおの無名関数ずクロヌゞャを提䟛する必芁がありたすおそらくトレヌドオフはここにありたすか。 この䟋では、同じバブル゜ヌトアルゎリズムを䜿甚しお、敎数のスラむスず「x、y」ポむントのスラむスの䞡方を゜ヌトしたす。ここで、原点からの距離は、Less関数の基瀎です。

ずにかく、型システムに関数を持たせるこずがどのように圹立぀かを瀺したいず思っおいたした。

@mandolyte私はあなたが提案しおいるこずを誀解したず思いたす。 あなたが話しおいるのは「folang」で、すでにいく぀かの関数型プログラミング機胜がGoに远加されおいたす。 実装したのは、基本的にマルチパラメヌタ型クラスを手動で配管するこずです。 関数ディクショナリず呌ばれるものを゜ヌト関数に枡したす。 これは、むンタヌフェヌスが暗黙的に行うこずを明瀺的に行っおいたす。 これらの皮類の機胜は、マルチパラメヌタむンタヌフェむスおよび関連する型の前におそらく必芁ですが、最終的には、これらすべおのディクショナリを枡す際に問題が発生したす。 むンタヌフェむスは、よりクリヌンで読みやすいコヌドを提䟛するず思いたす。

スラむスの䞊べ替えは解決された問題です。 これは、 go-ligolangが改善された蚀語を䜿甚しお実装されたスラむスquicksort.goのコヌドです。

func main(){
    var data = []int{5,3,1,8,9}

    Sort(data, func(a *int, b *int) int {
        return *a - *b
    })

    fmt.Println(data)
}

あなたは遊び堎でこれを詊すこずができたす

クむック゜ヌトパッケヌゞのむンポヌトはプレむグラりンドでは機胜しないため、完党な䟋をプレむグラりンドに貌り付けるこずができたす。

@ go-liス​​ラむスを䞊べ替えるこずができるず確信しおいたす。できなければ、少し貧匱になりたす。 重芁なのは、䞀般的に、同じコヌドで任意の線圢コンテナヌを゜ヌトできるようにするこずです。これにより、゜ヌトするコンテナヌデヌタ構造や、コンテンツはです。

これを実行できる堎合、暙準ラむブラリはナニバヌサル゜ヌト関数を提䟛でき、誰もそれを再床䜜成する必芁はありたせん。 これには2぀の利点がありたす。正しい䞊べ替えアルゎリズムを䜜成するのは思ったより難しいため、間違いが少なくなりたす。Stepanovは、ほずんどのプログラマヌが「min」ず「max」のペアを正しく定矩できないずいう䟋を䜿甚しおいたす。より耇雑なアルゎリズムを修正したす。 もう1぀の利点は、各゜ヌトアルゎリズムの定矩が1぀しかない堎合に、それを䜿甚するすべおのプログラムに利益をもたらすこずができる明快さたたはパフォヌマンスの改善です。 人々は、異なるデヌタ型ごずに独自のアルゎリズムを䜜成する代わりに、共通のアルゎリズムを改善するために時間を費やすこずができたす。

@keean
以前の議論に関連する別の質問。 アむテムをむテラブルから倉曎し、アむテムが元のタむプずは異なる可胜性がある新しい具象むテラブルタむプを返すマッピング関数をどのように定矩できるかわかりたせん。

そしお、そのような関数のナヌザヌは、別のむンタヌフェヌスではなく、具䜓的な型を返したいず思うでしょう。

@urandom安党ではない「むンプレヌス」で実行する぀もりはないず仮定するず、必芁なのは、あるタむプの「読み取りむテレヌタ」ず別のタむプの「曞き蟌みむテレヌタ」を持぀マップ関数です。これは次のように定矩できたす。

map<I, O, U>(first I, last I, out O, fn U) requires
   ForwardIterator<I>, Readable<I>,
   ForwardIterator<O>, Writable<O>,
   UnaryFunction<U>, Domain(U) == ValueType(I), Codomain(U) == ValueType(O)

わかりやすくするために、「ValueType」は「Readable」および「Writable」むンタヌフェヌスの関連タむプであり、「Domain」および「Codomain」は「UnaryFunction」むンタヌフェヌスの関連タむプです。 コンパむラが「UnaryFunction」のようなデヌタ型のむンタヌフェむスを自動的に導出できる堎合は、明らかに非垞に圹立ちたす。 この皮のリフレクションのように芋えたすが、そうではなく、すべお静的型を䜿甚しおコンパむル時に発生したす。

@keean珟圚のGoのむンタヌフェヌスのコンテキストで、これらの読み取り可胜および曞き蟌み可胜な制玄をモデル化する方法は

぀たり、タむプAがあり、タむプBに倉換する堎合、そのUnaryFunctionのシグネチャはfunc (input A) Bになりたす右が、どうすればよいでしょうか。むンタヌフェむスのみを䜿甚しおモデル化され、その汎甚map たたはfilter 、 reduceなどが型のパむプラむンを維持するためにどのようにモデル化されたすか

@ geovanisouza92 「型族」は、型システムの盎亀メカニズムずしお実装でき、Haskellで行われおいるように、むンタヌフェヌスの構文に統合できるので、うたく機胜するず思いたす。

型族は、型の制限された関数マッピングのようなものです。 むンタヌフェむスの実装はタむプごずに遞択されるため、実装ごずにタむプマッピングを提䟛できたす。

したがっお、次のように定矩したす。

ValueType MyIntArrayIterator -> Int

関数は少しトリッキヌですが、関数には次のようなタむプがありたす。

fn(x : Int) Float

このタむプを曞きたす

Int -> Float

->は単なる䞭眮型コンストラクタヌであり、配列の '[]'は型コンストラクタヌであるため、これを簡単に蚘述できるこずを理解するこずが重芁です。

Fn Int Float
Or
Fn<Int, Float>

型構文の奜みに応じお。 これで、次のように定矩する方法が明確にわかりたす。

Domain  Fn<Int, Float> -> Int
Codomain Fn<Int, Float> -> Float

これらすべおの定矩を手動で提䟛できるようになりたしたが、コンパむラヌによっお簡単に導出できたす。

これらの型族を考えるず、他のすべおの型は機胜的にこれらに䟝存しおいるため、䞊蚘のマップの定矩では、ゞェネリックをむンスタンス化するために型IOずUのみが必芁であるこずがわかりたす。 これらの型は匕数によっお盎接提䟛されおいるこずがわかりたす。

ありがずう、@ keean。

これは、組み蟌み/事前定矩された関数に察しおは正垞に機胜したす。 同じ抂念がナヌザヌ定矩関数たたはナヌザヌランドラむブラリに適甚されるず蚀っおいたすか

これらの「タむプファミリヌ」は、゚ラヌコンテキストの堎合、実行時に実行されたすか

空のむンタヌフェヌス、タむプスむッチ、リフレクションはどうですか


線集私は䞍平を蚀うのではなく、ただ興味がありたす。

@ giovanisouza92誰もゞェネリックを持っお行くこずを玄束しおいないので、私は懐疑論を期埅しおいたす。 私のアプロヌチは、ゞェネリックスを実行する堎合は、正しく実行する必芁があるずいうものです。

私の䟋では、「マップ」はナヌザヌ定矩です。 特別なこずは䜕もありたせん。関数内では、珟圚Goで行うのずたったく同じように、これらの型で必芁なむンタヌフェむスのメ゜ッドを䜿甚するだけです。 唯䞀の違いは、耇数のむンタヌフェヌスを満たすために型を芁求できるこず、むンタヌフェヌスは耇数の型パラメヌタヌを持぀こずができるこずただし、マップの䟋ではこれを䜿甚しおいたせん、関連する型および型の等匏 '=='などの型に察する制玄もあるこずです。しかし、これはプロロヌグの同等性のようなものであり、型を統䞀したす。 これが、関数に必芁なむンタヌフェヌスを指定するための異なる構文がある理由です。 別の重芁な違いがあるこずに泚意しおください。

f(x I, y I) requires ForwardIterator<I>

察

f(x ForwardIterator, y ForwardIterator)

埌者には違いがあるこずに泚意しおください。「x」ず「y」はForwardIteratorむンタヌフェヌスを満たす異なるタむプである可胜性がありたすが、前者の構文では「x」ず「y」は䞡方ずも同じタむプである必芁がありたすフォワヌドむテレヌタヌを満たす。 これは、関数に制玄が䞍足しないようにするために重芁であり、コンパむル䞭に具象型をさらに䌝播できるようにしたす。

むンタヌフェむスの抂念を拡匵しおいるだけなので、タむプスむッチずリフレクションに関しおは䜕も倉わらないず思いたす。 goには実行時型情報があるため、Haskellず同じ問題は発生せず、存圚型が必芁です。

Go、実行時のポリモヌフィズム、および型ファミリヌに぀いお考えるず、実行時に関連するすべおの型を空のむンタヌフェむスずしお扱う必芁がないように、型ファミリヌ自䜓をむンタヌフェむスに制限する必芁がありたす。

したがっお、これらの考えに照らしお、䞊蚘の提案を倉曎し、むンタヌフェむスを宣蚀するずきに、関連付けられたタむプごずにむンタヌフェむス/タむプを宣蚀し、そのむンタヌフェむスのすべおの実装がそのむンタヌフェむスを満たす関連付けられたタむプを提䟛する必芁があるようにしたす。 このようにしお、空のむンタヌフェむスから型を切り替えるこずなく、実行時に関連する型でそのむンタヌフェむスからメ゜ッドを呌び出すこずが安党であるこずがわかりたす。

@keean
議論を進めるために、私が感じおいる誀解を明確にさせおください。ここで発明されおいない症候矀が起こっおいるのず䌌おいたす。

双方向むテレヌタT構文func (*T) *[2]*T のタむプは、go-li構文でfunc (*) *[2]*です。 ぀たり、あるタむプぞのポむンタヌを受け取り、同じタむプの次の芁玠ず前の芁玠ぞの2぀のポむンタヌぞのポむンタヌを返したす。 これは、二重リンクリストで䜿甚される基本的な具䜓的な基本タむプです。

これで、マップず呌ばれるもの、぀たりforeachゞェネリック関数ず呌ばれるものを蚘述できたす。 間違いなく、これはリンクリストだけでなく、双方向むテレヌタを公開するすべおのものに察しお機胜したす。

func Foreach(link func(*) *[2]*, list **, direction byte, f func(*)) {

    if nil == *list {
        return
    }

    var end *
    end = *list

    var e *
    e = (*link(*list))[direction]
    f(end)

    for (e != end) && ((*link(e))[direction] != nil) {
        var newe = (*link(e))[direction]
        f(e)
        e = newe
    }
    return
}

Foreachは、2぀の方法で䜿甚できたす。぀たり、リストたたはコレクション芁玠に察するforルヌプのような反埩でラムダを䜿甚したす。

const forward = 1
const backwards = 0
Foreach(iterator, collection, forward, func(element *element_type){
    // do something with every element
})

たたは、これを䜿甚しお、関数をすべおのコレクション芁玠に機胜的にマップするこずもできたす。

Foreach(iterator, collection, backwards, function_to_be_mapped_on_elements)

もちろん、双方向むテレヌタは、go1のむンタヌフェむスを䜿甚しおモデル化するこずもできたす。
interface Iterator { Iter() [2]Iterator }基になる型をラップ「ボックス」するには、むンタヌフェヌスを䜿甚しおモデル化する必芁がありたす。 次に、むテレヌタナヌザヌは、特定のコレクション芁玠を芋぀けおアクセスしたい堎合に、既知の型をアサヌトしたす。 これは、コンパむル時に安党でない可胜性がありたす。

次に説明するのは、レガシヌアプロヌチずゞェネリックベヌスのアプロヌチの違いです。

func modern(x func  (*) *[2]*, y func  (*) *[2]*){}

このアプロヌチのコンパむル時型は、2぀のコレクションが同じ基になる型を持っおいるかどうか、぀たり、むテレヌタヌが実際に同じ具象型を返すかどうかをチェックしたす。

func modern_T_syntax<T>(x func  (*T) *[2]*T, y func  (*T) *[2]*T){}

䞊蚘ず同じですが、䜿い慣れたTを䜿甚するず、タむププレヌスホルダヌ構文を意味したす

func legacy(x Iterator, y Iterator){}

この堎合、ナヌザヌは、たずえば敎数リンクリストをxずしお、浮動小数点リンクリストをyずしお枡すこずができたす。 これは、朜圚的な実行時゚ラヌ、パニック、たたはその他の内郚デコヒヌレンスに぀ながる可胜性がありたすが、それはすべお、レガシヌが2぀のむテレヌタヌで䜕をするかに䟝存したす。

今誀解。 あなたは、むテレヌタを実行し、それらのむテレヌタを゜ヌトするために䞀般的な゜ヌトを実行するこずが、進むべき道であるず䞻匵したす。 それは本圓に悪いこずです、これが理由です

むテレヌタずリンクリストは同じコむンの衚裏です。 蚌明むテレヌタを公開するコレクションは、リンクリストずしお自分自身をアドバタむズするだけです。 それを䞊べ替える必芁があるずしたしょう。 䜕をしたすか

明らかに、リンクリストをコヌドベヌスから削陀し、バむナリツリヌに眮き換えたす。 たたは、提案されおいるように、avl、red-blackなどのバランスの取れた怜玢ツリヌを䜿いたい堎合は、Ian etallによっお䜕幎前かわかりたせん。 それでも、これはgolangでは䞀般的に行われおいたせん。 さお、それが進むべき道です。

別の解決策は、むテレヌタのONタむムルヌプですばやく、芁玠ぞのポむンタを[]*Tで瀺されるゞェネリックポむンタのスラむスに収集し、貧匱なスラむス゜ヌトを䜿甚しおそれらのゞェネリックポむンタを゜ヌトするこずです。

他の人のアむデアにチャンスを䞎えおください

@ go-liここで発明されおいない症候矀を避けたい堎合は、ゞェネリックプログラミングをほずんど発明したアレックスステパノフに定矩を求める必芁がありたす。 Stepanovの「ElementsofProgramming」111ペヌゞから匕甚しお、これを定矩する方法は次のずおりです。

Bidirectional iterator<T> =
    ForwardIterator<T>
/\ predecessor : T -> T
/\ predecessor takes constant time
/\ (forall i in T) successor(i) is defined =>
        predecessor(successor(i)) is defined and equals i
/\ (forall i in T) predecessor(i) is defined =>
        successor(predecessor(i)) is defined and equals i

これは、ForwardIteratorの定矩によっお異なりたす。

ForwardIterator<T> =
    Iterator<T>
/\ regular_unary_function(successor)

぀たり、基本的に、 successor関数ずpredecessor関数を宣蚀するむンタヌフェヌスず、それらが有効であるために準拠しなければならないいく぀かの公理がありたす。

legacyに関しおは、レガシヌがうたくいかないわけではなく、珟圚Goでも明らかにうたくいかないが、コンパむラヌには最適化の機䌚がなく、型システムには具䜓的な型をさらに䌝播する機䌚がない。 たた、プログラマヌが意図を正確に指定するこずを制限しおいたす。 䟋ずしおは、恒等関数がありたす。これは、枡された型を正確に返すこずを意味したす。

id(x T) T

おそらく、パラメトリックタむプず党称蚘号タむプの違いに぀いおも蚀及する䟡倀がありたす。 パラメトリックタむプはid<T>(x T) Tですが、党称蚘号はid(x T) Tですこの堎合、通垞、最も倖偎の党称蚘号はforall Tを省略したす。 パラメトリック型の堎合、型システムはコヌルサむトでidのT型を提䟛する必芁があり、コンパむルが完了する前にTが具象型ず統合される限り、党称蚘号は必芁ありたせん。 これを理解する別の方法は、パラメトリック関数が型ではなく型のテンプレヌトであり、Tが具象型に眮き換えられた埌にのみ有効な型であるずいうこずです。 党称蚘号関数を䜿甚するず、 idは実際にはforall T . T -> T型になり、 Intず同じようにコンパむラヌが枡すこずができたす。

@ go-li

明らかに、リンクリストをコヌドベヌスから削陀し、バむナリツリヌに眮き換えたす。 たたは、提案されおいるように、avl、red-blackなどのバランスの取れた怜玢ツリヌを䜿いたい堎合は、Ian etallによっお䜕幎前かわかりたせん。 それでも、これはgolangでは䞀般的に行われおいたせん。 さお、それが進むべき道です。

デヌタ構造を䞊べ替えおも、デヌタを䞊べ替える必芁がないずいう意味ではありたせん。

ここで発明されおいない症候矀を避けたい堎合は、アレックス・ステパノフがゞェネリックプログラミングをほずんど発明したので、定矩を探す必芁がありたす。

私は、ゞェネリックプログラミングがC ++によっお発明されたずいう䞻匵に異議を唱えたす。 Liskov etalを読んでください。 実際に機胜するゞェネリックプログラミングの初期モデルタむプセヌフ、モゞュラヌ、コヌド膚匵なしを確認したい堎合は、1977幎のCACMペヌパヌ https //dl.acm.org/citation.cfmid = 359789セクション4を参照 。

この議論をやめお、golangチヌムrussがいく぀かのブログ投皿を出すのを埅っおから、゜リュヌションを実装する必芁があるず思いたす👍vgoを参照圌らはそれを実行したす🎉

https://peter.bourgon.org/blog/2018/07/27/a-response-about-dep-and-vgo.html

この話が他の人ぞの譊告ずしお圹立぀こずを願っおいたす。Goプロゞェクトに実質的な貢献をするこずに興味がある堎合、コアチヌムに由来しない蚭蚈を独立したデュヌデリゞェンスで補うこずはできたせん。

このスレッドは、コアチヌムがコミュニティで解決策を芋぀けるこずに積極的に参加するこずにどのように関心がないかを瀺しおいたす。

しかし、結局、圌らが再び自分たちで解決策を䜜るこずができれば、それは私には問題ありたせん、ただそれを成し遂げおください👍

@andrewcmyersおそらく「発明された」ずいうのは少しストレッチでした。おそらく、1971幎にAdaのいく぀かの汎甚ラむブラリでStepanovず協力したDavidMusserに䌌おいたす。

Elements ofProgrammingはC ++に関する本ではなく、䟋はC ++である可胜性がありたすが、それは非垞に異なるものです。 この本は、あらゆる蚀語でゞェネリックスを実装したい人にずっおは必読だず思いたす。 Stepanovを华䞋する前に、本を実際に読んで、実際の内容を確認する必芁がありたす。

この問題は、GitHubのスケヌラビリティの制限の䞋ですでに負担になっおいたす。 Go提案の具䜓的な問題に焊点を圓おたここでの議論を続けおください。

GoがC ++ルヌトをたどるのは残念なこずです。

@andrewcmyersはい、私は心から同意したす。構文の提案や、適切に実行するためのベンチマヌクずしおC ++を䜿甚しないでください。 代わりに、むンスピレヌションを埗るためにDをご芧ください。

@ nomad-゜フトりェア

私はDがずおも奜きですが、Dが提䟛する匷力なコンパむル時のメタプログラミング機胜が必芁ですか

石噚時代に由来するC ++のテンプレヌト構文も奜きではありたせん。

しかし、通垞のParametricTypeはどうですかJavaたたはCにある暙準。必芁に応じお、これをParametricTypeでオヌバヌロヌドするこずもできたす。

さらに、私はそのbangシンボルを持぀Dのテンプレヌト呌び出し構文が奜きではありたせん。bangシンボルは、関数のパラメヌタヌぞの可倉たたは䞍倉のアクセスを瀺すために最近䜿甚されおいたす。

@ nomad-software C ++構文たたはテンプレヌトメカニズムがゞェネリックスを実行する正しい方法であるこずを瀺唆しおいたせんでした。 Stepanovによっお定矩されおいる「抂念」は、型を代数ずしお扱いたす。これは、ゞェネリックスを実行するための非垞に正しい方法です。 Haskellの型クラスを芋お、これがどのように芋えるかを確認しおください。 Haskell型クラスは、䜕が起こっおいるのかを理解しおいれば、意味的にはc ++テンプレヌトず抂念に非垞に近いものです。

したがっお、c ++構文に埓わない堎合は+1、型に安党でないテンプレヌトシステムを実装しない堎合は+1 :-)

@keean D構文の理由は、 <,>を完党に回避し、文脈自由文法に埓うためです。 これは、Dをむンスピレヌションずしお䜿甚するずいう私のポむントの䞀郚です。 <,>は、ゞェネリックパラメヌタヌの構文ずしおは非垞に悪い遞択です。

@ nomad-software䞊で指摘したように珟圚は非衚瀺のコメントで、パラメトリック型の型パラメヌタヌを指定する必芁がありたすが、党称蚘号型の型パラメヌタヌは指定する必芁はありたせんしたがっお、RustずHaskellの違いにより、型の凊理方法は実際には異なりたす型システムで。 たた、C ++の抂念== Haskell型クラス==少なくずも抂念レベルではGoむンタヌフェヌス。

D構文は本圓に望たしいですか

auto add(T)(T lhs, T rhs) {
    return lhs + rhs;

なぜこれがC ++ / Java / Rustスタむルよりも優れおいるのですか

T add<T>(T lhs, T rhs) {
    return lhs + rhs;
}

たたはScalaスタむル

T add[T](T lhs, T rhs) {
    return lhs + rhs;
}

型パラメヌタヌの構文に぀いお考えたした。 私はC ++ずJavaの「山かっこ」のファンではありたせんでした。なぜなら、それらは構文解析を非垞に難しくし、ツヌルの開発を劚げるからです。 角かっこは実際には叀兞的な遞択ですCLU、System F、およびパラメトリック倚態性を備えた他の初期の蚀語から。

ただし、Goの構文は非垞に扱いにくいものです。おそらく、すでに非垞に簡朔であるためです。 角かっこたたはかっこに基づく可胜な構文は、山かっこによっお導入される構文よりもさらに悪い文法䞊のあいたいさを䜜成したす。 ですから、私の玠因にもかかわらず、アングルブラケットは実際にはGoにずっお最良の遞択のようです。 もちろん、あいたいさを生じさせない実際の山かっこもありたす—⟚⟩—ただし、Unicode文字を䜿甚する必芁がありたす。

もちろん、型パラメヌタヌに䜿甚される正確な構文は、セマンティクスを正しくするこずほど重芁ではありたせん。 その点で、C ++蚀語は悪いモデルです。 Genus PLDI 2015ずFamilia OOPSLA 2017のゞェネリックに関する私の研究グルヌプの研究は、型クラスを拡匵し、それらをむンタヌフェヌスず統合する別のアプロヌチを提䟛したす。

@andrewcmyersどちらの論文も興味深いず思いたすが、属はオブゞェクト指向であり、Goはそうではなく、Familiaはサブタむピングずパラメトリック倚態性を統合しおおり、Goにはどちらもありたせん。 Goは、パラメトリックポリモヌフィズムたたは党称蚘号のいずれかを採甚する必芁があるず思いたす。サブタむピングは必芁ありたせん。私の意芋では、Goはそれを持たないためのより良い蚀語です。

Goは、オブゞェクト指向やサブタむピングを必芁ずしないゞェネリックスを探すべきだず思いたす。 Goにはすでにむンタヌフェヌスがあり、これはゞェネリックスの優れたメカニズムだず思いたす。 Goむンタヌフェヌス== c ++の抂念== Haskell型クラスであるこずがわかるずしたら、「Go」のフレヌバヌを維持しながらゞェネリックを远加する方法は、むンタヌフェヌスを拡匵しお耇数の型パラメヌタヌを取るこずだず思いたす私はむンタヌフェむスの関連する型ず同様ですが、それを個別に拡匵するこずで、耇数の型パラメヌタを受け入れるこずができたす。 これが重芁な倉曎になりたすが、これを有効にするには、関数シグネチャのむンタヌフェむスに「代替」構文が必芁です。これにより、耇数の型のパラメヌタをむンタヌフェむスに取埗できたす。これにより、山かっこ構文党䜓が䜿甚されたす。 。

Goむンタヌフェヌスは型クラスではなく、単なる型ですが、むンタヌフェヌスを型クラスず統合するこずは、Familiaが行う方法を瀺しおいたす。 GenusずFamiliaのメカニズムは、完党にオブゞェクト指向である蚀語に結び付けられおいたせん。 Goむンタヌフェヌスは、すでにGoを重芁な方法で「オブゞェクト指向」にしおいるので、アむデアを少し単玔化した圢で適応させるこずができるず思いたす。

@andrewcmyers

Goむンタヌフェヌスは型クラスではなく、単なる型です。

それらはポリモヌフィズムを可胜にするので、私には型のように振る舞いたせん。 Addable []のようなポリモヌフィック配列のオブゞェクトは、実際の型ランタむムリフレクションで衚瀺を保持しおいるため、単䞀パラメヌタヌ型クラスずたったく同じように動䜜したす。 それらが型眲名の型の代わりに配眮されるずいう事実は、型倉数を省略した単なる省略衚蚘です。 衚蚘法ずセマンティクスを混同しないでください。

f(x : Addable) == f<T>(x : T) requires Addable<T>

もちろん、このIDは、単䞀パラメヌタヌのむンタヌフェヌスに察しおのみ有効です。

むンタヌフェむスず単䞀パラメヌタ型クラスの唯䞀の重芁な違いは、むンタヌフェむスがロヌカルで定矩されるこずですが、これは、Haskellが型クラスで抱えるグロヌバルコヒヌレンスの問題を回避するために圹立ちたす。 これはデザむン空間の興味深い点だず思いたす。 マルチパラメヌタむンタヌフェむスは、ロヌカルであるずいう利点を備えたマルチパラメヌタ型クラスのすべおの機胜を提䟛したす。 Go蚀語に継承やサブタむピングを远加する必芁はありたせんこれは、OOを定矩する2぀の重芁な機胜です。

私芋では

タむプ制限の衚珟専甚のDSLよりも、デフォルトのタむプを䜿甚する方が望たしいでしょう。 関数f(s T fmt.Stringer)を持っおいるようなものです。これは、 fmt.Stringerむンタヌフェむスであるすべおの型を受け入れるゞェネリック関数です。

このようにしお、次のようなゞェネリック関数を持぀こずができたす。

func add(a, b T int) T int {
    return a + b
}

これで、関数add()は、 intのように+挔算子をサポヌトする任意のタむプのTで機胜したす。

@ dc0d珟圚のGo構文を芋るず魅力的だず思いたす。 ただし、ゞェネリックスに必芁なすべおの制玄を衚すこずができないずいう点で「完党」ではなく、これをさらに拡匵する必芁がありたす。 これにより、単玔さの目暙ず矛盟しおいるず私が考えるさたざたな構文が急増したす。 私の芋解では、シンプルさはシンプルではなく、最もシンプルである必芁がありたすが、それでも必芁な衚珟力を提䟛したす。 珟圚、䞀般的な衚珟力におけるGoの䞻な制限は、マルチパラメヌタヌむンタヌフェむスの欠劂です。 たずえば、コレクションむンタヌフェむスは次のように定矩できたす。

type T U Collection interface {
   member(c T, v U) Bool
   insert(c T, v U) T
}

それで、これは理にかなっおいたすか コレクションのようなものの䞊にむンタヌフェヌスを曞きたいず思いたす。 したがっお、問題は、関数でこのむンタヌフェむスをどのように䜿甚するかです。 私の提案は次のようになりたす

func[T, U] f(c T, e U) (Bool, T) requires Collection[T, U] {
   a := member(c, e)
   d := insert(c, e)
   return a, d
}

構文は単なる提案ですが、これらの抂念を蚀語で衚珟できる限り、構文が䜕であるかは気にしたせん。

@keean構文をたったく気にしないず蚀ったら、正確ではありたせん。 ただし、重芁なのは、すべおのゞェネリックパラメヌタヌにデフォルトの型を蚭定するこずに重点を眮くこずでした。 その意味で、提䟛されるむンタヌフェヌスの䟋は次のようになりたす。

type Collection interface (T interface{}, U interface{}) {
   member(c T, v U) Bool
   insert(c T, v U) T
}

(T interface{}, U interface{})の郚分は、制玄の定矩に圹立ちたす。 たずえば、メンバヌがfmt.Stringerを満たすこずを意図しおいる堎合、定矩は次のようになりたす。

type Collection interface (T fmt.Stringer, U fmt.Stringer) {
   member(c T, v U) Bool
   insert(c T, v U) T
}

@ dc0dこれも、耇数の型パラメヌタヌで制玄したいずいう意味で制限的です。次のこずを考慮しおください。

type OrderedCollection[T, U] interface
   requires Collection[T, U], Ord[U] {...}

私はあなたがパラメヌタの配眮でどこから来おいるのかわかるず思いたす、あなたは持っおいるこずができたす

type OrderedCollection interface(T, U)
   requires Collection(T, U), Ord(U) {...}

私が蚀ったように、私はほずんどの構文に慣れるこずができるので、構文にあたり煩わされおいたせん。 䞊蚘から、マルチパラメヌタむンタヌフェむスには括匧「」を䜿甚するこずをお勧めしたす。

@keean heap.Interfaceむンタヌフェヌスに぀いお考えおみたしょう。 暙準ラむブラリの珟圚の定矩は次のずおりです。

type Interface interface {
    sort.Interface
    Push(x interface{}) // add x as element Len()
    Pop() interface{}   // remove and return element Len() - 1.
}

それでは、デフォルトの型を䜿甚しお、ゞェネリックむンタヌフェむスずしお曞き盎しおみたしょう。

type Interface interface (T interface{}) {
    sort.Interface
    Push(x T) // add x as element Len()
    Pop() T   // remove and return element Len() - 1.
}

これは、そこにあるGo1.xコヌドシリヌズのどれも壊したせん。 1぀の実装は、タむプ゚むリアスの再バむンドに関する私の提案です。 しかし、もっず良い実装があるず確信しおいたす。

デフォルトの型を䜿甚するず、Go1.xスタむルのコヌドで䜿甚できるゞェネリックコヌドを蚘述できたす。 そしお、暙準ラむブラリは、䜕も壊すこずなく、ゞェネリックラむブラリになるこずができたす。 それは倧きな勝利のIMOです。

@ dc0dなので、段階的な改善を提案しおいたすか あなたが提案しおいるこずは、段階的な改善ずしお私には問題ないように芋えたすが、それでも䞀般的な衚珟力は限られおいたす。 「Collection」および「OrderedCollection」むンタヌフェヌスをどのように実装したすか

いく぀かの郚分的な蚀語拡匵は、可胜な限り単玔な方法で完党な゜リュヌションを実装するよりも、耇数の代替構文を含むより耇雑な最終補品に぀ながる可胜性があるこずを考慮しおください。

@keean requires Collection[T, U], Ord[U]の郚分がわかりたせん。 タむプパラメヌタTずUをどのように制限しおいたすか

@ dc0dこれらは関数の堎合ず同じように機胜したすが、すべおに適甚されたす。 したがっお、OrderedCollectionであるタむプTUのペアの堎合、TUもCollectionのむンスタンスであり、UはOrdである必芁がありたす。 したがっお、OrderedCollectionを䜿甚する堎合は、必芁に応じおCollectionおよびOrdのメ゜ッドを䜿甚できたす。

ミニマリストの堎合、これらは必芁ありたせん。必芁な関数型に远加のむンタヌフェむスを含めるこずができるためです。たずえば、次のようになりたす。

type OrderedCollection interface(T, U)
{
   first(c T) U
}

func[T] first(c T[]) T requires Collection(T[], T), Ord T
{...}

func[T] f(c T[]) requires OrderedCollection(T[], T), Collection(T[], T), Ord(T)
{...}

しかし、これはもっず読みやすいかもしれたせん

type OrderedCollection interface(T, U) 
   requires Collection(T, U), Ord(U)
{
   first(c T) U
}

func[T] first(c T[]) T
{...}

func[T] f(c T[]) requires OrderedCollection(T[], T)
{...}

@keean IMO型パラメヌタヌに必須のデフォルト倀がある限り、私は満足しおいたす。 このようにしお、Go1.xコヌドシリヌズずの䞋䜍互換性を維持するこずができたす。 それが私が䜜ろうずした芁点です。

@keean

Goむンタヌフェヌスは型クラスではなく、単なる型です。

それらはポリモヌフィズムを可胜にするので、私には型のように振る舞いたせん。

はい、サブタむプのポリモヌフィズムを蚱可したす。 Goには、むンタヌフェむスタむプを介したサブタむピングがありたす。 明瀺的に宣蚀されたサブタむプ階局はありたせんが、それはほが盎亀しおいたす。 Goが完党にオブゞェクト指向ではない理由は、継承がないこずです。

たたは、むンタヌフェむスを型クラスの存圚蚘号アプリケヌションずしお衚瀺するこずもできたす。 それがあなたの心にあるこずだず思いたす。 それがGenusずFamiliaで行ったこずです。

@andrewcmyers

はい、サブタむプのポリモヌフィズムを蚱可したす。

私が知る限り、䞍倉であり、共分散や反倉性はありたせん。これは、これがサブタむピングではないこずを匷く物語っおいたす。 ポリモヌフィック型システムは䞍倉であるため、私にはGoがこのモデルに近いように芋え、むンタヌフェむスを単䞀パラメヌタヌ型クラスずしお扱うこずは、Goの単玔さに沿っおいるように芋えたす。 共倉性ず反倉性がないこずはゞェネリックスにずっお倧きなメリットです。Cのような蚀語でそのようなものが生み出す混乱を芋おください。

https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance

Goは、このような耇雑さを完党に回避する必芁があるず思いたす。 私にずっおこれは、同じ型システムでゞェネリックスずサブタむピングを望たないこずを意味したす。

たたは、むンタヌフェむスを型クラスの存圚蚘号アプリケヌションずしお衚瀺するこずもできたす。 それがあなたの心にあるこずだず思いたす。 それがGenusずFamiliaで行ったこずです。

Goは実行時に型情報を持っおいるため、存圚蚘号を定量化する必芁はありたせん。 Haskellでは型はボックス化されおいたせんネむティブの「C」型のように。これは、存圚するコレクションに䜕かを入れたら、コンテンツの型を簡単に回埩できないこずを意味したす。提䟛されたむンタヌフェむス型クラスを䜿甚するだけです。 。 これは、生デヌタず䞀緒にむンタヌフェむスぞのポむンタを栌玍するこずによっお実装されたす。 Goでは、代わりにデヌタのタむプが保存され、デヌタは「ボックス化」されたすCのボックス化および非ボックス化デヌタの堎合ず同様。 そのため、Goはデヌタずずもに保存されたむンタヌフェむスだけに限定されたせん。コレクション内のデヌタのタむプをタむプケヌスを䜿甚しお回埩できるためです。これは、Haskellで「Reflection」を実装するこずによっおのみ可胜です。 typeclassデヌタを取り出すのは面倒ですが、型ずデヌタ、たずえば文字列をシリアル化しおから、既存のボックスの倖で逆シリアル化するこずは可胜です。 したがっお、私が持っおいる結論は、Haskellが「Reflection」型クラスを組み蟌みずしお提䟛した堎合、Goむンタヌフェむスは型クラスずたったく同じように動䜜するずいうこずです。 そのため、実存的なボックスはなく、コレクションの内容を掻字ケヌスにするこずはできたすが、むンタヌフェむスは型クラスずたったく同じように動䜜したす。 HaskellずGoの違いは、ボックス化されたデヌタずボックス化されおいないデヌタのセマンティクスにあり、むンタヌフェむスは単䞀パラメヌタヌの型クラスです。 実際、「Go」がむンタヌフェヌスをタむプずしお扱う堎合、実際に実行しおいるのは次のずおりです。

Addable[] == exists T . T[] requires Addable[T], Reflection[T]

これは、Rustで「トレむトオブゞェクト」が機胜するのず同じ方法であるこずに泚意しおください。

Goは、実存䞻矩プログラマヌに芋える、共倉性、反倉性を完党に回避できたす。これは良いこずであり、私の意芋では、ゞェネリックスははるかに単玔で匷力になりたす。

私が知る限り、䞍倉であり、共分散や反倉性はありたせん。これは、これがサブタむピングではないこずを匷く物語っおいたす。

ポリモヌフィック型システムは䞍倉であるため、私にはこのモデルに近いように芋え、むンタヌフェむスを単䞀パラメヌタヌ型クラスずしお扱うこずは、Goの単玔さに沿っおいるように芋えたす。

あなたが䞡方ずも正しいこずを提案しおもいいですか その堎合、むンタヌフェむスは型クラスず同等ですが、型クラスはサブタむピングの圢匏です。 私がこれたでに芋぀けたサブタむピングの定矩はすべおかなり曖昧で䞍正確であり、「䞀方を他方に眮き換えるこずができれば、AはBのサブタむプです」に芁玄されたす。 これ、IMOは、型クラスによっお満たされるず非垞に簡単に䞻匵できたす。

分散匕数自䜓は実際にはIMOずしお機胜しおいないこずに泚意しおください。 分散は型構築子の特性であり、蚀語ではありたせん。 たた、蚀語のすべおの型構築子がバリアントであるずは限らないのはごく普通のこずですたずえば、サブタむピングを䜿甚する倚くの蚀語には可倉配列があり、型セヌフにするためには䞍倉である必芁がありたす。 だから私はあなたがバリアント型コンストラクタヌなしでサブタむピングをするこずができなかった理由がわかりたせん。

たた、この議論はGoリポゞトリの問題には少し広すぎるず思いたす。 これは、型理論の耇雑さに぀いお議論するこずではなく、ゞェネリックをGoに远加するかどうかずその方法に぀いお議論するこずです。

@Merovius Varianceは、サブタむピングに関連付けられたプロパティです。 サブタむピングのない蚀語では、差異はありたせん。 そもそも分散があるためには、サブタむピングが必芁です。これにより、型構築子に共倉性/反倉性の問題が発生したす。 ただし、サブタむピングを䜿甚する蚀語では、すべおの型構築子を䞍倉にするこずが可胜です。

型クラスは型ではないため、型クラスは間違いなくサブタむピングではありたせん。 ただし、Goの「むンタヌフェむスタむプ」は、Rustが「特性オブゞェクト」ず呌んでいるものず芋なすこずができたす。事実䞊、タむプクラスから掟生したタむプです。

Goのセマンティクスは、分散がなく、暗黙の「トレむトオブゞェクト」があるため、珟時点ではどちらのモデルにも適合しおいるようです。 したがっお、おそらくGoは転換点にあり、ゞェネリックスず型システムはサブタむピングのラむンに沿っお開発され、分散を導入し、Cのゞェネリックスのようなものになっおしたう可胜性がありたす。 あるいは、Goはマルチパラメヌタヌむンタヌフェむスを導入しお、コレクションのむンタヌフェむスを蚱可するこずもできたす。これにより、むンタヌフェむスず「むンタヌフェむスタむプ」の間の盎接のリンクが切断されたす。 たずえば、次の堎合

type (T, U) Collection interface {
    member : (c T, e U) Bool
    insert: (c T, e U) T
}

member(c int32[], e int32) Bool {...}
insert(c int32[], e int32) int32[] {...}

member(c float32[], e float32) Bool {...}
insert(c float32[], e float32) float32[] {...}

タむプT、Uずむンタヌフェむスコレクションの間に明らかなサブタむプの関係はなくなりたした。 したがっお、むンスタンスタむプずむンタヌフェむスタむプの関係は、単䞀パラメヌタむンタヌフェむスの特殊なケヌスのサブタむピングずしおのみ衚瀺でき、単䞀パラメヌタむンタヌフェむスを䜿甚したコレクションなどの抜象化を衚珟するこずはできたせん。

ゞェネリックスの堎合、コレクションなどをモデル化できる必芁があるこずは明らかなので、マルチパラメヌタヌむンタヌフェむスは私にずっお必須です。 ただし、ゞェネリックスの共倉性ず反倉性の盞互䜜甚は、過床に耇雑な型システムを䜜成するず思うので、サブタむピングは避けたいず思いたす。

@keeanむンタヌフェヌスは型ずしお䜿甚でき、型クラスは型ではないため、Goセマンティクスの最も自然な説明は、むンタヌフェヌスは型クラスではないずいうこずです。 むンタヌフェむスを型クラスずしお䞀般化するこずを䞻匵しおいるこずを理解しおいたす。 蚀語を採甚するこずは合理的な方向性だず思いたす。実際、私たちは公開された䜜品でそのアプロヌチをすでに広範囲にわたっお調査したした。

Goにサブタむピングがあるかどうかに぀いおは、次のコヌドを怜蚎しおください。

package main

type Cloneable interface {
    Clone() Cloneable
}

type CloneableZ interface {
    Clone() Cloneable
    zero() int
}

type S struct {}

func (t S) Clone() Cloneable {
    c := t
    return c
}

func (t S) zero() int {
    return 0
}

var x CloneableZ = S{}
var y Cloneable = x

func main() {
    print("ok\n")
}

xからy $ぞの割り圓おは、 xのタむプが予想される堎所でyのタむプを䜿甚できるこずを瀺しおいたす。 これはサブタむピングの関係であり、 CloneableZ <: CloneableずS <: CloneableZです。 型クラスの芳点からむンタヌフェヌスを説明したずしおも、ここではS <: ∃T.CloneableZ[T] <: ∃T.Cloneable[T]のようなサブタむピング関係がありたす。

関数CloneがS $を返すこずを蚱可するこずは、Goにずっお完党に安党であるこずに泚意しおください。ただし、Goは、むンタヌフェむスぞの準拠のために䞍必芁に制限的なルヌルを適甚したす。実際、Javaず同じルヌルです。圓初は匷制されたした。 @Meroviusが芳察したように、サブタむピングは非䞍倉の型コンストラクタヌを必芁ずしたせん。

@andrewcmyersコレクションを抜象化するために必芁なむンタヌフェヌスなど、マルチパラメヌタヌむンタヌフェヌスはどうなりたすか

さらに、xからyぞの割り圓おは、サブタむピングがたったくないむンタヌフェむスの継承を瀺しおいるず芋なすこずができたす。 Haskell明らかにサブタむピングがないでは、次のように蚘述したす。

class Cloneable t => CloneableZ t where...

xがある堎合は、 CloneableZを実装するタむプであり、定矩䞊、 Cloneableも実装するため、明らかにyに割り圓おるこずができたす。

芁玄するず、むンタヌフェむスを型ずしお衚瀺し、Goを䜿甚しお、共倉たたは逆倉の型コンストラクタヌを䜿甚せずにサブタむピングを制限するか、「特性オブゞェクト」ずしお衚瀺するか、Goでは「 「むンタヌフェヌスオブゞェクト」。これは、事実䞊、むンタヌフェヌス「typeclass」によっお制玄されるポリモヌフィックコンテナヌです。 型クラスモデルにはサブタむプがないため、共倉性ず反倉性に぀いお考える必芁はありたせん。

サブタむピングモデルに固執する堎合、コレクションタむプを䜿甚するこずはできたせん。これが、オブゞェクト指向のサブタむピングではコンテナなどの抂念を䞀般的に定矩するのに十分ではないため、C ++でテンプレヌトを導入する必芁がある理由です。 抜象化のための2぀のメカニズム、オブゞェクトずサブタむピング、およびテンプレヌト/トレむトずゞェネリックスになり、2぀の間の盞互䜜甚は耇雑になりたす。たずえば、C ++、C、およびScalaを芋おください。 これらの他の蚀語に沿っお、ゞェネリックスの胜力を高めるために共倉および反倉コンストラクタヌを導入するための継続的な呌びかけがありたす。

別のゞェネリックシステムを導入せずにゞェネリックコレクションが必芁な堎合は、型クラスのようなむンタヌフェむスを考える必芁がありたす。 マルチパラメヌタむンタヌフェむスは、サブタむピングに぀いお考えるのではなく、むンタヌフェむスの継承に぀いお考えるこずを意味したす。 Goでゞェネリックスを改善し、コレクションなどの抜象化を可胜にし、C ++、C、Scalaなどの蚀語の型システムの耇雑さを望たない堎合は、マルチパラメヌタヌむンタヌフェむスずむンタヌフェむスの継承が方法です。トヌゎ。

@keean

コレクションを抜象化するために必芁なむンタヌフェむスなど、マルチパラメヌタむンタヌフェむスはどうなりたすか

マルチパラメヌタタむプの制玄をサポヌトするGenusずFamiliaに関する論文を参照しおください。 Familiaは、これらの制玄をむンタヌフェヌスず統合し、むンタヌフェヌスが耇数のタむプを制玄できるようにしたす。

サブタむピングモデルに固執する堎合、コレクションタむプを持぀こずはできたせん

「サブタむピングモデル」の意味は完党にはわかりたせんが、JavaずCにコレクションタむプがあるこずは明らかなので、この䞻匵は私にはあたり意味がありたせん。

xがある堎合、CloneableZを実装するタむプであり、定矩䞊、Cloneableも実装するため、明らかにyに割り圓おるこずができたす。

いいえ、私の䟋では、xは倉数であり、yは別の倉数です。 yがCloneableZタむプで、xがCloneableタむプであるこずがわかっおいる堎合、それはyからxに割り圓おるこずができるずいう意味ではありたせん。 それが私の䟋がしおいるこずです。

Goをモデル化するためにサブタむピングが必芁であるこずを明確にするために、以䞋は、道埳的な同等物がHaskellでタむプチェックしない䟋のシャヌプバヌゞョンです。 この䟋は、サブタむピングにより、異なる芁玠が異なる実装を持぀異皮コレクションの䜜成が可胜になるこずを瀺しおいたす。 さらに、可胜な実装のセットは制限がありたせん。

type Cloneable interface {
    Clone() Cloneable
}

type CloneableZ interface {
    Clone() Cloneable
    zero() int
}

type S struct {}

func (t S) Clone() Cloneable {
    c := t
    return c
}

type T struct { x int }

func (t T) Clone() Cloneable {
    c := t
    return c
}

func (t S) zero() int {
    return 0
}

var x CloneableZ = S{}
var y Cloneable = T{}
var a [2]Cloneable = [2]Cloneable{x, y}

@andrewcmyers

「サブタむピングモデル」の意味は完党にはわかりたせんが、JavaずCにコレクションタむプがあるこずは明らかなので、この䞻匵は私にはあたり意味がありたせん。

C ++がテンプレヌトを開発した理由を芋おください。オブゞェクト指向サブタむピングモデルは、コレクションなどを䞀般化するために必芁な䞀般的な抂念を衚珟できたせんでした。 CずJavaは、オブゞェクト、サブタむピング、継承ずは別に完党なゞェネリックシステムを導入する必芁があり、次に、共倉型および反倉型のコンストラクタヌなどずの2぀のシステムの耇雑な盞互䜜甚の混乱をクリヌンアップする必芁がありたした。 埌知恵の恩恵を受けお、OOサブタむピングを回避し、代わりに、単玔に型指定された蚀語にむンタヌフェヌス型クラスを远加した堎合に䜕が起こるかを調べるこずができたす。 これはRustが行ったこずであるため、䞀芋の䟡倀がありたすが、もちろん、生涯を通じお耇雑になりたす。 GoにはGCがあるので、それほど耇雑ではありたせん。 私の提案は、Goを拡匵しおマルチパラメヌタヌむンタヌフェむスを蚱可し、この耇雑さを回避できるこずです。

Haskellではこの䟋を実行できないずいうあなたの䞻匵に関しお、コヌドは次のずおりです。

{-# LANGUAGE ExistentialQuantification #-}

class ICloneable t where
    clone :: t -> t

class ICloneable t => ICloneableZ t where
    zero :: t

data S = S deriving Show

instance ICloneable S where
    clone x = x

data T = T Int deriving Show

instance ICloneable T where
    clone x = x

instance ICloneableZ T where
    zero = T 0

data Cloneable = forall a . (ICloneable a, Show a) => ToCloneable a

instance Show Cloneable where
    show (ToCloneable x) = show x

main = do
    x <- return S
    y <- return (T 27)
    a <- return [ToCloneable x, ToCloneable y]
    putStrLn (show a)

いく぀かの興味深い違いは、Goがこのタむプdata Cloneable = forall a . (ICloneable a, Show a) => ToCloneable aを自動的に導出するこずです。これは、むンタヌフェむスストレヌゞがないをタむプストレヌゞがあるに倉換する方法であるためです。Rustもこれらのタむプを導出し、「特性オブゞェクト」ず呌びたす。 。 Java、C、Scalaなどの他の蚀語では、むンタヌフェヌスをむンスタンス化できないこずがわかりたす。これは実際には「正しい」ものであり、むンタヌフェヌスは型ではなく、ストレヌゞもありたせん。Goは、既存のコンテナヌの型を自動的に取埗しお凊理できるようにしたす。型のようなむンタヌフェヌスであり、Goは、実存的なコンテナヌに、それが掟生するむンタヌフェヌスず同じ名前を付けるこずによっお、これを非衚瀺にしたす。 もう1぀泚意すべき点は、この[2]Cloneable{x, y}はすべおのメンバヌをCloneableに匷制するのに察し、Haskellにはそのような暗黙の匷制はなく、 ToCloneableでメンバヌを明瀺的に匷制する必芁があるずいうこずです。 。

SずTはそうではないので、 CloneableのSずTのサブタむプを考慮すべきではないこずも指摘されおいたす。構造的に互換性がありたす。 文字通り、任意の型をCloneableのむンスタンスずしお宣蚀できGoで関数cloneの関連する定矩を宣蚀するだけで、これらの型は互いにたったく関係がない必芁がありたす。

Genericsの提案のほずんどには、読みやすさずGoのシンプルな感芚を損なうず思う远加のトヌクンが含たれおいるようです。 Goの既存の文法でうたく機胜するず思われる別の構文を提案したいず思いたすGithub Markdownでは構文のハむラむトもかなりうたくいきたす。

提案の芁点

  • Goの文法には、探しおいる特定のトヌクンたたはキヌワヌドがあるため、型宣蚀がい぀終了したかを刀断する簡単な方法があるようです。 これがすべおの堎合に圓おはたる堎合、型匕数は型名自䜓の埌に単玔に远加できたす。
  • ほずんどの提案ず同様に、同じ識別子はどの関数宣蚀でも同じ型を意味したす。 これらの識別子は宣蚀を゚スケヌプするこずはありたせん。
  • ほずんどの提案では、ゞェネリック型の匕数を宣蚀する必芁がありたすが、この提案では暗黙的です。 䞀郚の人々は、これが読みやすさや明快さを損なう暗黙性が悪い、たたはタむプに名前を付ける胜力を制限するず䞻匵するでしょう、反論は次のずおりです

    • 読みやすさを損なうこずになるず、どちらの方法でも議論できるず思いたす。たたは[T]は、構文䞊のノむズを倚く発生させるこずで、読みやすさを損ないたす。

    • 適切に䜿甚された堎合の暗黙性は、蚀語の冗長性を枛らすのに圹立ちたす。 :=を䜿甚しお型宣蚀を垞に削陀したす。これは、それによっお隠されおいる情報が、毎回説明するほど重芁ではないためです。

    • 具䜓的な非ゞェネリック型aたたはtずいう名前を付けるこずはおそらく悪い習慣です。したがっお、この提案では、これらの識別子をゞェネリック型の匕数ずしお機胜するように予玄しおも安党であるず想定しおいたす。 これにはおそらくgofixの移行が必芁ですが

package main

import "fmt"

type LinkedList a struct {
  Head *Node a
  Tail *Node a
}

type Node a {
  Next *Node a
  Prev *Node a

  Value a
}

func main() {
  // Not sure about how recursive we could get with the inference
  ll := LinkedList string {
    // The string bit could be inferred
    Head: Node string { Value: "hello world" },
  }
}

func (l *LinkedList a) Append(value a) {
  newNode := &Node{Value: value}

  if l.Tail == nil {
    l.Head = newNode
    l.Tail = l.Head
    return
  }

  l.Tail.Next = newNode
  l.Tail = l.Tail.Next
}

これは、ここで提案されおいる合蚈タむプだけでなく、もう少し詳现な芁点から取埗されたす https //gist.github.com/aarondl/9b950373642fcf5072942cf0fca2c3a2

これは完党にフラッシュされたゞェネリックスの提案ではなく、そうするこずを意図したものでもありたせん。ゞェネリックスをGoに远加できるようにするために解決すべき問題がたくさんありたす。 これは構文にのみ取り組むものであり、提案されたものが実行可胜/望たしいかどうかに぀いお話し合うこずができるこずを望んでいたす。

@aarondl
この構文を䜿甚するず、私には問題ないように芋えたす。

type Collection a b interface {
   member(c a, e b) Bool
   insert(c a, e b) a
}

func insert(c *LinkedList a, e a) *LinkedList a {
   c.Append(e)
   return c
}

@keean Collectionタむプに぀いお少し説明しおいただけたすか。 私はそれを理解できたせん

type Collection a b interface {
   member(c a, e b) Bool
   insert(c a, e b) a
}

@ dc0dコレクションは_all_コレクションを抜象化するむンタヌフェヌスであるため、ツリヌ、リスト、スラむスなど、任意のデヌタ型を含む任意のコレクションで機胜するmemberやinsertなどの䞀般的な操䜜を実行できたす。 䞊蚘では、前の䟋でLinkedList型に「挿入」を定矩する䟋を瀺したした。

func insert(c *LinkedList a, e a) *LinkedList a {
   c.Append(e)
   return c
}

スラむス甚に定矩するこずもできたす

func insert(c []a, e a) []a {
   return append(c, e)
}

ただし、これが機胜するためには、ポリモヌフィック型aの@aarondlで瀺されおいるような、型倉数を持぀皮類のパラメトリック関数も必芁ありたせん。具䜓的な型を定矩するだけです。

func insert(c *LinkedList int, e int) *LinkedList int {
   c.Append(e)
   return c
}

func insert(c *LinkedList float, e float) *LinkedList float {
   c.Append(e)
   return c
}

func insert(c int[], e int) int[] {
   return append(c, e)
}

func insert(c float[], e float) float[] {
   return append(c, e)
}

したがっお、 Collectionは、コンテナヌのタむプずそのコンテンツのタむプの䞡方を䞀般化するためのむンタヌフェヌスであり、コンテナヌずコンテンツのすべおの組み合わせで動䜜するゞェネリック関数を蚘述できたす。

コレクションのスラむス[]Collectionを䜿甚できない理由はありたせん。ここで、コンテンツはすべお、異なる倀タむプの異なるコレクションタむプであり、組み合わせごずにmemberずinsertが定矩されおいたす。 。

@aarondl type LinkedList aがすでに有効な型宣蚀であるこずを考えるず、これを明確に解析可胜にする方法は2぀しかわかりたせん。文法の文脈䟝存にするCの解析の問題に取り組むか、無制限の先読みを䜿甚する倱敗した堎合の゚ラヌメッセヌゞが悪いため、go文法はこれを回避する傟向がありたす。 私は䜕かを誀解しおいるかもしれたせんが、トヌクンのないアプロヌチに反察するIMOです。

Goの@keeanむンタヌフェヌスは、関数ではなくメ゜ッドを䜿甚したす。 あなたが提案した特定の構文では、コンパむラヌのinsertを*LinkedListに付加するものは䜕もありたせんHaskell instance宣蚀を介しお行われたす。 メ゜ッドが操䜜しおいる倀を倉曎するこずも正垞です。 これはいずれもShow-Stopperではなく、提案しおいる構文がGoではうたく機胜しないこずを指摘しおいるだけです。 おそらくもっず䜕か

type Collection e interface {
    Element(e) book
    Insert(e)
}

func (l *(LinkedList e)) Element(el e) book {
    // ...
}

func (l* (LinkedList e)) Insert(el e) {
    // ...
}

これは、型パラメヌタヌのスコヌプずこれを解析する方法に関しお、さらにいく぀かの質問を瀺しおいたす。

@aarondlあなたの提案に぀いお私が持っおいる質問も他にもありたす。 たずえば、制玄を蚱可しないため、制玄のないポリモヌフィズムのみが取埗されたす。 取埗した倀に察しお䜕も実行できないため、䞀般的にはそれほど䟿利ではありたせんたずえば、すべおのタむプが有効なマップキヌであるずは限らないため、マップを䜿甚しおコレクションを実装できたせんでした。 誰かがそのようなこずをしようずするずどうなりたすか コンパむル時の゚ラヌの堎合、むンスタンス化先のC ++゚ラヌメッセヌゞたたは定矩すべおのタむプで機胜するものがないため、基本的に䜕もできたせんに぀いお文句を蚀いたすか

@keeanそれでも、 aがリストたたはスラむスやその他のコレクションに制限されおいる方法を理解できたせん。 これは、コレクションのコンテキスト䟝存の特別な文法ですか もしそうなら、その䟡倀は䜕ですか この方法でナヌザヌ定矩型を宣蚀するこずはできたせん。

@Meroviusこれは、Goが倚重ディスパッチを実行できず、「関数」の最初の匕数を特別なものにするこずを意味したすか これは、関連付けられたタむプが耇数パラメヌタヌのむンタヌフェヌスよりも適しおいるこずを瀺唆しおいたす。 このようなもの

type Collection interface {
   type Element
   Member(e Element) Bool
   Insert(e Element) Collection
}

type IntSlice struct {
    value []Int,
}

type IntSlice.Element = Int

func (IntSlice) Member(e Int) Bool {...}
func (IntSlice) Insert(e Int) IntSlice {...}

func useIt(c Collection, e Collection.Element) {...}

ただし、2぀のコレクションが同じタむプになるように制玄するものがないため、これにはただ問題がありたす...次のようなものが必芁になりたす。

func[A] useIt(c A, e A.Element) requires A:Collection

違いを説明するために、マルチパラメヌタむンタヌフェむスにはむンスタンス遞択に参加する远加の_input_タむプがありたすしたがっお、マルチディスパッチずの接続が、関連するタむプは_output_タむプであり、レシヌバヌタむプのみがむンスタンス遞択に参加したす。関連するタむプは、受信者のタむプによっお異なりたす。

@ dc0d aずbは、Haskell型クラスず同様に、むンタヌフェヌスの型パラメヌタヌです。 Collectionず芋なされるものに぀いおは、むンタヌフェむスのタむプに䞀臎するメ゜ッドを定矩する必芁がありたす。ここで、 aずbは任意のタむプにするこずができたす。 ただし、 @ Meroviusが指摘しおいるように、Goむンタヌフェヌスはメ゜ッドベヌスであり、倚重ディスパッチをサポヌトしおいないため、マルチパラメヌタヌむンタヌフェヌスは適切ではない可胜性がありたす。 Goのシングルディスパッチメ゜ッドモデルでは、耇数のパラメヌタヌの代わりに、むンタヌフェむスに関連付けられたタむプを䜿甚する方が適しおいるように思われたす。 ただし、倚重ディスパッチがないため、 unify(x, y)のような関数を実装するのは難しく、ダブルディスパッチパタヌンを䜿甚する必芁がありたす。これはあたり良くありたせん。

マルチパラメヌタに぀いおもう少し詳しく説明するず、次のようになりたす。

type Cloneable[A] interface {
   clone(x A) A
}

ここでaは任意のタむプを衚したす。正しい関数が定矩されおいる限り、それがCloneableであるず芋なす限り、それが䜕であるかは関係ありたせん。 むンタヌフェむスは、型自䜓ではなく、型に察する制玄ず芋なされたす。

func clone(x int) int {...}

したがっお、「clone」の堎合、むンタヌフェむス定矩のintをaに眮き換え、眮換が成功した堎合はcloneを呌び出すこずができたす。 これは、次の衚蚘法ずうたく䞀臎したす。

func[A] test(x A) A requires Cloneable[A] {...}

これは次ず同等です。

type Cloneable interface {
   clone() Cloneable
}

ただし、メ゜ッドではなく関数を宣蚀し、耇数のパラメヌタヌで拡匵できたす。 倚重ディスパッチのある蚀語を䜿甚しおいる堎合、関数/メ゜ッドの最初の匕数に぀いお特別なこずは䜕もないので、別の堎所に曞き蟌むのはなぜですか。

Goには耇数のディスパッチがないため、これはすべお䞀床に倉曎するには倚すぎるように感じ始めたす。 制限はありたすが、関連付けられたタむプの方が適しおいるようです。 これにより、抜象的なコレクションは可胜になりたすが、統合などの掗緎された゜リュヌションは可胜になりたせん。

@Merovius提案をご芧いただきありがずうございたす。 私はあなたの懞念に察凊しようずしたす。 私たちがそれに぀いおもっず議論する前にあなたが提案を芪指で䞋ろしたのは悲しいです、私はあなたの考えを倉えるこずができるこずを願っおいたす-たたは倚分あなたは私のものを倉えるこずができたす:)

無制限の先読み
したがっお、提案で述べたように、珟圚、Go文法には、ほずんどすべおの「終わり」を構文的に怜出するための優れた方法があるようです。 そしお、暗黙の䞀般的な匕数のために、私たちはただそうしたす。 䞀文字の小文字は、そのゞェネリック匕数を䜜成する構文構造です-たたは、そのむンラむントヌクンを䜜成するこずにしたものは䜕でも、構文が十分に気に入った堎合は、提案の@aのようなトヌクン化されたものにフォヌルバックするこずもできたすが、そうではありたせんトヌクンがないずコンパむラの難しさを考えるず可胜ですが、それを行うずすぐに提案は倚くの魅力を倱いたす。

aはゞェネリック型の匕数であるこずがわかっおいるため、この提案でのtype LinkedList aの問題はそれほど難しくありたせん。したがっお、これはtype LinkedListず同じコンパむラ゚ラヌで倱敗したす。 prog.go:3:16: expected type, found newline (and 1 more errors)で倱敗したす。 元の投皿は実際には出おこなかったのですが、具䜓的なタむプ[a-z]{1}ずいう名前を付けるこずはできなくなりたした。これは、この問題を解決し、私たち党員が倧䞈倫だず思う犠牲です。䜜成䞭今日のGoコヌドで1文字の名前を持぀実際の型を䜜成する堎合にのみ䞍利益が芋られたす。

制玄のないポリモヌフィズムです
あらゆる皮類の特性やゞェネリック匕数の制玄を省略した理由は、それがGoでのむンタヌフェむスの圹割であるず感じおいるためです。倀を䜿甚しお䜕かを実行する堎合、その倀は完党にゞェネリック型ではなくむンタヌフェむス型である必芁がありたす。 この提案はむンタヌフェヌスでもうたくいくず思いたす。

この提案では、 +のような挔算子を䜿甚した堎合ず同じ問題が発生するため、すべおの数倀型に察しお汎甚のadd関数を䜜成するこずはできたせんが、匕数ずしお汎甚のadd関数を受け入れるこずはできたす。 次のこずを考慮しおください。

func Sort(slice []a, compare func (a, a) bool) { ... }

スコヌピングに関する質問

ここに䟋を瀺したした

type Collection e interface {
    Element(e) book
    Insert(e)
}

func (l *(LinkedList e)) Element(el e) book {
    // ...
}

func (l* (LinkedList e)) Insert(el e) {
    // ...
}

原則ずしお、これらの識別子の範囲は、それらが含たれる特定の宣蚀/定矩にバむンドされおいたす。それらはどこにも共有されおおらず、その理由はわかりたせん。

@keeanこれは非垞に興味深いこずですが、他の人が指摘しおいるように、実際にむンタヌフェむスを実装できるようにするには、そこに衚瀺されおいるものを倉曎する必芁がありたす珟圚、この䟋では、レシヌバヌを備えたメ゜ッドはなく、関数のみです。 これが私の最初の提案にどのように圱響するかに぀いおもっず考えようずしおいたす。

その䞀般的な匕数を䜜成する構文構造である1文字の小文字

私はそれに぀いお気分が悪い。 それは、識別子が文脈に䟝存しおいるもののために別々のプロダクションを持぀こずを必芁ずし、たたタむプのために特定の識別子を恣意的に犁止するこずを意味したす。 しかし、これらの詳现に぀いお話すずきではありたせん。

この提案では、+のような挔算子を䜿甚した堎合ず同じ問題が発生したす。

私はこの文を理解しおいたせん。 珟圚、+挔算子にはこれらの問題はありたせん。これは、そのオペランドのタむプがロヌカルで既知であり、゚ラヌメッセヌゞが明確で明確であり、問​​題の原因を瀺しおいるためです。 すべおの可胜なタむプで蚱可されおいないゞェネリック倀の䜿甚を犁止したいず蚀っおいるず仮定しお正しいですかそのような操䜜の倚くは考えられたせん そしお、ゞェネリック関数で問題のある匏のコンパむラ゚ラヌを䜜成したすか ゞェネリック医薬品の䟡倀を制限しすぎるIMO。

倀を䜿甚しお䜕かを実行したい堎合、その倀は完党にゞェネリック型ではなく、むンタヌフェヌス型である必芁がありたす。

ゞェネリックが必芁な2぀の䞻な理由は、パフォヌマンスむンタヌフェむスの折り返しを避けるず型の安党性同じ型がどちらであるかを気にせずに、異なる堎所で䜿甚されるようにするこずです。 これはそれらの理由を無芖しおいるようです。

䞀般的なadd関数を匕数ずしお受け入れるこずができたす。

本圓です。 しかし、かなり非人間的です。 sort APIに぀いお、そこにどれだけの苊情があるかを考えおみおください。 倚くの汎甚コンテナヌの堎合、呌び出し元が実装しお枡す必芁のある関数の量は法倖なようです。 container/heapの実装は、この提案の䞋でどのように芋え、人間工孊の芳点から、珟圚の実装よりもどのように優れおいるかを考えおみおください。 せいぜい、ここでの勝利はごくわずかであるように思われたす。 より倚くの些现な機胜を実装する必芁がありたすそしお、各䜿甚サむトで耇補/参照。

@メロノィクス

@aarondlからこの点に぀いお考える

䞀般的なadd関数を匕数ずしお受け入れるこずができたす。

䞭眮挔算子を定矩するための構文を考えるず、加算のオヌバヌロヌドを可胜にするAddableむンタヌフェむスがある方がよいでしょう。

type Addable interface {
   + (x Addable, y Addable) Addable
}

残念ながら、これは機胜したせん。これは、すべおのタむプが同じであるず期埅しおいるこずを衚しおいないためです。 远加可胜オブゞェクトを定矩するには、マルチパラメヌタむンタヌフェむスのようなものが必芁になりたす。

type Addable[A] interface {
   + (x A, y A) A
}

次に、Goで倚重ディスパッチを実行する必芁がありたす。これは、関数内のすべおの匕数がむンタヌフェむスマッチングのレシヌバヌのように扱われるこずを意味したす。 したがっお、䞊蚘の䟋では、むンタヌフェむス定矩の関数定矩を満たす関数+が定矩されおいる堎合、どのタむプもAddableになりたす。

しかし、これらの倉曎を考えるず、次のように曞くこずができたす。

type S struct {
   value: int
}

func (+) (x S, y S) S {
   return S {
      value: x.value + y.value
   }
}

func main() {
    println(S {value: 27} + S {value: 5})
}

もちろん、関数のオヌバヌロヌドず倚重ディスパッチは、人々がGoで決しお望んでいないこずかもしれたせんが、ベクトル、行列、耇玠数などのナヌザヌ定矩型で基本的な算術を定矩するようなこずは垞に䞍可胜です。 䞊で述べたように、むンタヌフェヌスの「関連付けられた型」は、ゞェネリックプログラミング機胜のいくらかの増加を可胜にしたすが、完党な䞀般性ではありたせん。 倚重ディスパッチおよびおそらく関数のオヌバヌロヌドは、Goで発生する可胜性のあるものですか

ベクトル、行列、耇玠数などのナヌザヌ定矩型で基本的な算術を定矩するようなこずは、垞に䞍可胜です。

䞀郚の人は、機胜を怜蚎するかもしれたせん:) AFAIRどこかに浮かんでいる提案やスレッドがあり、それが必芁かどうかを議論しおいたす。 FWIW、これは-再び-話題から倖れおさたよっおいるず思いたす。 挔算子のオヌバヌロヌドたたは䞀般的な「Gomore Haskell」のアむデアは、実際にはこの問題のポむントではありたせん:)

倚重ディスパッチおよびおそらく関数のオヌバヌロヌドは、Goで発生する可胜性のあるものですか

絶察ずは絶察蚀うな。 個人的には期埅しおいたせん。

@メロノィクス

䞀郚の人はその機胜を考えるかもしれたせん:)

もちろん、Goがそれを行わない堎合は、他の蚀語がありたす:-) Goがすべおの人にずっおすべおである必芁はありたせん。 Goでゞェネリックスのスコヌプを確立しようずしおいたした。 私は自分自身ず定型文を繰り返すこずに嫌悪感を持っおいるので、完党に䞀般的な蚀語を䜜成するこずに焊点を圓おおいたすそしお私はマクロが奜きではありたせん。 毎回ペニヌを持っおいた堎合、特定のデヌタ型のリンクリストたたはツリヌを「C」で䜜成する必芁がありたした。 それを理解するために頭の䞭に保持し、倉曎を通じお維持する必芁のあるコヌドの量のために、実際には小さなチヌムにずっおいく぀かのプロゞェクトを䞍可胜にしたす。 ゞェネリックスを必芁ずしない人は、ただ十分な倧きさのプログラムを䜜成しおいないず思うこずがありたす。 もちろん、代わりに、開発者の倧芏暡なチヌムが䜕かに取り組んでいお、各開発者がコヌド党䜓のごく䞀郚にのみ責任を持぀ようにするこずもできたすが、私は1人の開発者たたは小さなチヌムをできるだけ効果的にするこずに興味がありたす。

関数のオヌバヌロヌドず倚重ディスパッチが範囲倖であり、 @ aarondlの提案による解析の問題も考慮するず、関連する型をむンタヌフェむスに远加し、型パラメヌタヌを関数に远加するこずは、ほが必芁な範囲であるように思われたす。 Goでゞェネリックを䜿甚したす。

このようなものは正しい皮類のもののように思われたす

type Collection interface {
   type Element
   Member(e Element) Bool
   Insert(e Element) Collection
}

type IntSlice struct {
    value []Int,
}

type IntSlice.Element = Int

func (IntSlice) Member(e Int) Bool {...}
func (IntSlice) Insert(e Int) IntSlice {...}

func useIt<T>(c T, e T.Element) requires T:Collection {...}

次に、実装においお、パラメトリック型を䜿甚するか、党称蚘号型を䜿甚するかを決定したす。 パラメトリック型Javaなどの堎合、「ゞェネリック」関数は実際には関数ではなく、ある皮のタむプセヌフな関数テンプレヌトであるため、型パラメヌタヌが指定されおいない限り、匕数ずしお枡すこずはできたせん。

f(useIt) // not okay with parametric types
f(useIt<List>) // okay with parametric types

党称蚘号型を䜿甚するず、useItを匕数ずしお枡すこずができ、 f内に型パラメヌタヌを指定できたす。 パラメトリック型を奜む理由は、コンパむル時にポリモヌフィズムを単圢化できるため、実行時にポリモヌフィック関数を䜜成する必芁がないためです。 Goはすでにむンタヌフェヌスでランタむムディスパッチを実行しおいるため、これがGoの懞念事項かどうかはわかりたせん。 useItのtypeパラメヌタヌがCollectionを実装しおいる限り、実行時に正しいレシヌバヌにディスパッチできたす。定量化はおそらくGoにずっお正しい方法です。

SFINAEは@bcmillsによっおのみ蚀及されおいるのだろうか。 提案では蚀及されおいたせんただし、゜ヌトは䟋ずしおありたす。
スラむスずリンクリストのSortどのように芋えるでしょうか

@keean
あなたの提案で䞀般的な「スラむス」コレクションをどのように定矩するのか理解できたせん。 'Collection'を実装しおいる可胜性のある 'IntSlice'を定矩しおいるようですがInsertはむンタヌフェむスで必芁なタむプずは異なるタむプを返したす、これは䞀般的な 'slice'ではありたせん。 、およびメ゜ッドの実装はint専甚です。 タむプごずに特定の実装を定矩する必芁がありたすか

ゞェネリックスを必芁ずしない人は、ただ十分な倧きさのプログラムを䜜成しおいないず思うこずがありたす。

私はあなたに印象が間違っおいるこずを保蚌するこずができたす。 そしお、FWIW、ISTMは、「反察偎」が「必芁性を認識しおいない」こずを「䜿甚を認識しおいない」こずず同じバケットに入れおいるこずを瀺しおいたす。 私はその䜿甚法を芋お、それを論駁したせん。 でも、その必芁性はあたりわかりたせん。 倧芏暡なコヌドベヌスでも、問題なく実行できたす。

たた、「正しく行われるこずを望み、既存の提案がどこにないのかを指摘する」こずず、「アむデアそのものに根本的に反察する」こずも間違えないでください。

たた、 @ aarondlの提案による構文解析の問題も考えられたす。

私が蚀ったように、私は構文解析の問題に぀いお話すこずは今のずころ本圓に生産的だずは思いたせん。 構文解析の問題は解決できたす。 制玄されたポリモヌフィズムのラックは、意味的にはるかに深刻です。 IMO、それなしでゞェネリックを远加するこずは、本圓に努力する䟡倀がありたせん。

@urandom

あなたの提案で䞀般的な「スラむス」コレクションをどのように定矩するのか理解できたせん。

䞊蚘のように、スラむスのタむプごずに個別の実装を定矩する必芁がありたすが、汎甚むンタヌフェむスの芳点からアルゎリズムを蚘述できるこずで利益を埗るこずができたす。 すべおのスラむスにゞェネリック実装を蚱可する堎合は、パラメトリック関連のタむプずメ゜ッドを蚱可する必芁がありたす。 レシヌバヌタむプの前に発生するように、タむプパラメヌタヌをキヌワヌドの埌に​​移動したこずに泚意しおください。

type<T> []T.Element = Int

func<T> ([]T) Member(e T) Bool {...}
func<T> ([]T) Insert(e T) Collection {...}

ただし、特殊化に察凊する必芁がありたす。これは、誰かがより特殊化された[]intに関連付けられたタむプずメ゜ッドを定矩でき、どちらを䜿甚するかを凊理する必芁があるためです。 通垞は、より具䜓的なむンスタンスを䜿甚したすが、さらに耇雑なレむダヌが远加されたす。

これが実際にどれだけあなたを埗るのかはわかりたせん。 䞊蚘の私の元の䟋では、むンタヌフェむスを䜿甚しお䞀般的なコレクションに䜜甚する䞀般的なアルゎリズムを蚘述でき、実際に䜿甚するタむプのメ゜ッドず関連するタむプを提䟛するだけで枈みたす。 私にずっおの䞻な利点は、任意のコレクションでの䞊べ替えなどのアルゎリズムを定矩し、それらのアルゎリズムをラむブラリに配眮できるこずです。 次に「図圢」のリストがある堎合は、図圢のリストのコレクションむンタヌフェむスメ゜ッドを定矩するだけで、ラむブラリ内の任意のアルゎリズムを䜿甚できたす。 すべおのスラむスタむプのむンタヌフェむスメ゜ッドを定矩できるこずは、私にはあたり興味がなく、Goにずっおは耇雑すぎるかもしれたせん。

@メロノィクス

でも、その必芁性はあたりわかりたせん。 倧芏暡なコヌドベヌスでも、問題なく実行できたす。

100,000行のプログラムに察応できる堎合は、100,000行の非ゞェネリック行よりも100,000行の䞀般行でより倚くのこずを実行できたす繰り返しのため。 したがっお、あなたは非垞に倧きなコヌドベヌスに察凊できるスヌパヌスタヌの開発者かもしれたせんが、冗長性を排陀するので、非垞に倧きな汎甚コヌドベヌスでより倚くのこずを達成できたす。 そのゞェネリックプログラムは、さらに倧きな非ゞェネリックプログラムに拡匵されたす。 あなたはただ耇雑さの限界に達しおいないように私には思えたす。

しかし、あなたは正しいず思いたす。「必芁性」は匷すぎたす。ゞェネリックスがないこずに䞍満を感じるこずもありたすが、私は喜んでgoコヌドを曞いおいたす。これを回避するには、コヌドを远加するだけです。Goでは、そのコヌドは完党に盎接的なものです。ず文字通り。

制玄されたポリモヌフィズムの欠劂は、意味的にはるかに深刻です。 IMO、それなしでゞェネリックを远加するこずは、本圓に努力する䟡倀がありたせん。

私はこれに賛同する。

100,000の非ゞェネリックラむンよりも100,000のゞェネリックラむンでより倚くのこずができるようになりたす繰り返しのため

あなたの仮説の䟋から、これらの行の䜕が総称関数になるのか興味がありたすか
私の経隓では、これは115k LOCのコヌドベヌスから2未満であるため、「コレクション」甚のラむブラリを䜜成しない限り、これは適切な議論ではないず思いたす。

最終的にゞェネリック医薬品を入手したいのですが

@keean

Haskellではこの䟋を実行できないずいうあなたの䞻匵に関しお、コヌドは次のずおりです。

このコヌドは、私が曞いたコヌドず道埳的に同等ではありたせん。 ICloneableむンタヌフェむスに加えお、新しいCloneableラッパヌタむプが導入されおいたす。 Goコヌドにはラッパヌは必芁ありたせんでした。 サブタむピングをサポヌトする他の蚀語も同様です。

@andrewcmyers

このコヌドは、私が曞いたコヌドず道埳的に同等ではありたせん。 ICloneableむンタヌフェむスに加えお、新しいCloneableラッパヌタむプが導入されおいたす。

これはこのコヌドが行うこずではありたせん

type Cloneable interface {...}

これは、むンタヌフェヌスから掟生したデヌタ型「Cloneable」を導き出したす。 むンタヌフェむスのむンスタンス宣蚀がないため、「ICloneable」は衚瀺されたせん。メ゜ッドを宣蚀するだけです。

むンタヌフェむスを実装するタむプが構造的に互換性がある必芁がない堎合、サブタむピングず芋なすこずができたすか

@keean Cloneableは単なる型であり、実際には「デヌタ型」ではないず思いたす。 Javaのような蚀語では、コヌドずは異なり、ラッパヌがないため、 Cloneableの抜象化に远加のコストは基本的にありたせん。

むンタヌフェむスを実装するタむプ間の構造的な類䌌性を芁求するこずは制限的で望たしくないように思われるので、ここであなたが䜕を考えおいるかに぀いお混乱しおいたす。

@andrewcmyers
タむプずデヌタタむプを同じ意味で䜿甚しおいたす。 デヌタを含むこずができるすべおの型はデヌタ型です。

コヌドずは異なり、ラッパヌがないためです。

Goタむプは垞にボックス化されおいるため、ラッパヌは垞に存圚したす。したがっお、ラッパヌはすべおの呚りに存圚したす。 Haskellはボックス化されおいないタむプを持っおいるので、ラッパヌを明瀺的にする必芁がありたす。

むンタヌフェむスを実装するタむプ間の構造的な類䌌性のため、ここで䜕を考えおいるのか混乱しおいたす。

構造サブタむピングでは、タむプが「構造的に互換性がある」必芁がありたす。 継承を䌎うオブゞェクト指向蚀語のような明瀺的な型階局がないため、サブタむピングは名目䞊できないため、存圚する堎合は構造的である必芁がありたす。

しかし、私はあなたが䜕を意味するのかわかりたす。これは、むンタヌフェむスを、必芁なメ゜ッドを実装する任意のタむプずのある皮の暗黙の名目サブタむプ関係を持぀、むンタヌフェむスではなく抜象基本クラスであるず芋なすず説明したす。

Goは珟圚䞡方のモデルに適合しおいるず思いたす。ここからどちらの方向にも進む可胜性がありたすが、クラスではなくむンタヌフェむスず呌ぶこずは、サブタむピングを行わない考え方を瀺唆しおいるず思いたす。

@keeanあなたのコメントがわかりたせん。 最初にあなたはあなたが同意しないず私に蚀い、そしお私は「ただ私の耇雑さの限界に達しおいない」ずあなたは私にあなたが同意するず蚀いたすその「必芁性」はあたりにも匷い蚀葉です。 たた、あなたの議論は誀りだず思いたすLOCが耇雑さの䞻芁な尺床であり、コヌドのすべおの行が等しいず仮定したす。 しかし、䜕よりも、「より耇雑なプログラムを曞いおいるのは誰か」ずいうのは、実際には生産的な議論ではないず思いたす。 私は、「あなたが私に同意しない堎合、それはあなたが難しい問題や興味深い問題に取り組んでいないこずを意味しおいるに違いない」ずいう議論は説埗力がなく、誠意を持っお倖れないこずを明確にしようずしおいたした。 同等の胜力を持ち、同じように興味深いこずをしながら、この機胜の重芁性に぀いお人々があなたに反察できるこずを信頌しおいただければ幞いです。

@merovius
私はあなたが私よりも有胜なプログラマヌである可胜性が高いず蚀っおいたので、より耇雑に䜜業するこずができたす。 確かに、あなたがそれほど面癜くなく、それほど耇雑でない問題に取り組んでいるずは思いたせん。そのように遭遇したこずを残念に思いたす。 私は昚日スキャナヌを動䜜させるために費やしたしたが、これは非垞に興味深い問題ではありたせんでした。

ゞェネリックは、限られた頭脳でより耇雑なプログラムを曞くのに圹立぀ず思いたす。たた、ゞェネリックを「必芁ずしない」こずも認めおいたす。 それは皋床の問題です。 ゞェネリックスがなくおもプログラミングはできたすが、必ずしも同じ耇雑さの゜フトりェアを䜜成できるずは限りたせん。

私が誠意を持っお行動しおいるこずを安心させおくれるこずを願っおいたす。ここに隠された議題はありたせん。Goがゞェネリックを採甚しない堎合でも、それを䜿甚したす。 私はゞェネリックスを行うための最良の方法に぀いお意芋を持っおいたすが、それだけではありたせん。私は自分の経隓からしか話すこずができたせん。 私が助けおいないのなら、私が時間を費やすこずができる他のこずがたくさんあるので、蚀葉を蚀うだけで、私は他の堎所に再び焊点を合わせたす。

@Meroviusダむアログを続けおくれおありがずう。

| ゞェネリックが必芁な2぀の䞻な理由は、パフォヌマンスむンタヌフェむスの折り返しを避けるず型の安党性同じ型がどちらであるかを気にせずに、異なる堎所で䜿甚されるようにするこずです。 これはそれらの理由を無芖しおいるようです。

たぶん、私が提案したものを非垞に異なっお芋おいるのかもしれたせん。私の芳点からは、私が知る限り、これらの䞡方を行っおいるのでしょうか。 リンクリストの䟋では、むンタヌフェむスによるラッピングがないため、特定のタむプに察しお手曞きされた堎合ず同じようにパフォヌマンスが向䞊するはずです。 型安党性の面でも同じです。 あなたがどこから来おいるのかを理解するのに圹立぀反䟋はありたすか

| 本圓です。 しかし、かなり非人間的です。 ゜ヌトAPIに぀いおどこにどれだけの苊情があるかを考えおください。 倚くの汎甚コンテナヌの堎合、呌び出し元が実装しお枡す必芁のある関数の量は法倖なようです。 人間工孊の芳点から、コンテナ/ヒヌプの実装はこの提案の䞋でどのように芋え、珟圚の実装よりもどのように優れおいるかを考えおみおください。 せいぜい、ここでの勝利はごくわずかであるように思われたす。 より倚くの些现な機胜を実装する必芁がありたすそしお、各䜿甚サむトで耇補/参照。

私は実際にはこれにはたったく関心がありたせん。 関数の数が法倖なものになるずは思いたせんが、いく぀かの反䟋を目にするこずは間違いありたせん。 人々が䞍満を蚀ったAPIは、関数を提䟛する必芁のあるAPIではなく、ここにある元のAPIであったこずを思い出しおください https //golang.org/pkg/sort/#Interfaceここで、単玔な新しいタむプを䜜成する必芁がありたしたスラむス+タむプを入力し、3぀のメ゜ッドを実装したす。 このむンタヌフェヌスに関連する苊情ず苊痛に照らしお、以䞋が䜜成されたした https //golang.org/pkg/sort/#Slice、私はこのAPIに問題はなく、このパフォヌマンスのペナルティを回埩したす提案では、定矩をfunc Slice(slice []a, less func(a, a) bool)に倉曎するだけで議論しおいたす。

container/heapのデヌタ構造に関しおは、どのような䞀般的な提案を受け入れおも、党䜓を曞き盎す必芁がありたす。 $ sortパッケヌゞが独自のデヌタ構造の䞊にアルゎリズムを提䟛しおいるのず同じようにcontainer/heap []interface{}が、どちらのパッケヌゞもデヌタ構造を所有しおいたせん。それに関連するコスト。 ゞェネリックスのおかげで具䜓的なタむプのスラむスを所有するHeapを持぀こずができるので、おそらくそれらを倉曎したす。これは、私がここで芋たどの提案にも圓おはたりたす私自身を含む 。

私が提案したものに぀いおの私たちの芋方の違いをばらばらにしようずしおいたす。 そしお、構文的に個人的な奜みを超えお䞍䞀臎の根本は、ゞェネリック型に制玄がないこずだず思いたす。 しかし、私はただそれが私たちに䜕をもたらすのかを理解しようずしおいたす。 答えが、パフォヌマンスに関係するものがむンタヌフェむスを䜿甚するこずを蚱可されおいないずいうこずである堎合、ここで蚀えるこずはあたりありたせん。

次のハッシュテヌブル定矩を怜蚎しおください。

// Hasher turns a key into a hash
type Hasher interface {
  func Hash() []byte
}

type HashTable v struct {
   Keys   []Hasher
   Values []v
}

// Note that the generic arguments must be repeated here and immediately
// understood without reading another line of code, which to me
// is a readability win over the sudden appearance of the K and V which are
// defined elsewhere in the code in the example below. This is of course because
// the tokenized type declarations with constraints are fairly painful in general
// and repeating them everywhere is simply too much.
func (h (*HashTable v)) Insert(key Hasher, value v) { ... }

[]Hasherはパフォヌマンス/ストレヌゞの問題のために初心者ではなく、Goでゞェネリックスの実装を成功させるには、絶察に次のようなものが必芁だず蚀っおいたすか

// Without selecting another proposal I have no idea how the constraint might be defined or implemented so let's just pretend
type [K: Hasher, V] HashTable a struct {
   Keys   []K
   Values []V
}

func (h *HashTable) Insert(key K, value V) { ... }

うたくいけば、あなたは私がどこから来おいるのかわかるでしょう。 しかし、特定のコヌドに課したい制玄を私が理解しおいない可胜性は間違いありたせん。 芁件が䜕であるか、そしお提案がどのようにそれらを倱敗させおいるかをより完党に理解したいず思っおいるにもかかわらず、私が考慮しおいないナヌスケヌスがあるかもしれたせん。

たぶん、私が提案したものを非垞に異なっお芋おいるのかもしれたせん。私の芳点からは、私が知る限り、これらの䞡方を行っおいるのでしょうか。

匕甚しおいるセクションの「これ」は、むンタヌフェヌスの䜿甚を指したす。 問題は、プロポヌザルがどちらも実行しないずいうこずではなく、プロポヌザルが制玄付きポリモヌフィズムを蚱可しおいないこずです。これにより、ほずんどの䜿甚法が陀倖されたす。 そしお、あなたが提案した代替案は、ゞェネリックスのコアナヌスケヌスにも実際には察応しおいないむンタヌフェむスです私が蚀及した2぀の理由のため。

たずえば、最初に䜜成された提案では、実際には、あらゆる皮類の汎甚マップを䜜成するこずはできたせんでした。これは、少なくずも==を䜿甚しおキヌを比范できる必芁があるためですこれは制玄であるため、マップには制玄付きポリモヌフィズムが必芁です。

このむンタヌフェヌスに関連する苊情ず苊痛に照らしお、以䞋が䜜成されたした https //golang.org/pkg/sort/#Slice

このむンタヌフェむスは、長さずスワッピングのリフレクションに䟝存しおいるため、ゞェネリックスの提案ではただ䜿甚できないこずに泚意しおくださいしたがっお、スラむス操䜜に制玄がありたす。 そのAPIをゞェネリックスが達成できるはずの䞋限ずしお受け入れたずしおも倚くの人はそうしたせん。そのAPIの型安党性の欠劂に぀いおはただ倚くの䞍満がありたす、あなたの提案は合栌したせん。そのバヌ。

ただし、ここでも、䜜成した特定のポむントに察する応答を匕甚しおいたす。぀たり、APIで関数リテラルを枡すこずで、制玄されたポリモヌフィズムを取埗できたす。 そしお、制玄されたポリモヌフィズムの欠劂を回避するために提案したその特定の方法では、倚かれ少なかれ叀いAPIを実装する必芁がありたす。 ぀たり、この議論に察する私の回答を匕甚しおいるのですが、それを繰り返しおいるだけです。

定矩をfuncSliceslice [] a、less funca、aboolに倉曎するだけで、議論しおいる提案の䞋でこれのパフォヌマンスペナルティを回埩したす。

ただし、これは叀いAPIです。 「私の提案では制玄付きポリモヌフィズムは蚱可されおいたせんが、ゞェネリックを䜿甚できず、代わりに既存の゜リュヌションリフレクション/むンタヌフェむスを䜿甚できるため、問題ありたせん」ずおっしゃっおいたす。 ええず、「あなたの提案は、人々がゞェネリックを望んでいる最も基本的なナヌスケヌスを蚱可しおいたせん」ず「私たちは、それらの最も基本的なナヌスケヌスのためにゞェネリックなしで人々がすでに行っおいるこずをするこずができたす」ず答えるこずは私たちを埗るようには芋えたせんどこでも、TBH。 基本的なコンテナタむプ、䞊べ替え、最倧倀でさえ曞くのに圹立たないゞェネリックスの提案は、それだけの䟡倀がないようです。

これは、私がここで芋た提案私自身を含むのいずれにも圓おはたりたす。

ほずんどのゞェネリックスの提案には、型パラメヌタヌを制玄する方法が含たれおいたす。 ぀たり、「タむプパラメヌタにはLessメ゜ッドが必芁」、たたは「タむプパラメヌタは比范可胜でなければならない」ず衚珟したす。 あなたの-AFAICT-はそうではありたせん。

次のハッシュテヌブル定矩を怜蚎しおください。

あなたの定矩は䞍完党です。 aキヌタむプにも同等性が必芁であり、b異なるキヌタむプの䜿甚を劚げおいない。 ぀たり、これは合法です。

type hasherA uint64

func (a hasherA) Hash() []byte {
    b := make([]byte, 8)
    binary.BigEndian.PutUint64(b, uint64(a))
    return b
}

type hasherB string

func (b hasherB) Hash() []byte {
    return []byte(b)
}

h := new(HashTable int)
h.Insert(hasherA(42), 1)
h.Insert(hasherB("Hello world"), 2)

ただし、さたざたなキヌタむプを䜿甚しおいるため、合法ではありたせん。 ぀たり、コンテナは人々が望む皋床にタむプチェックされおいたせん。 キヌタむプず倀タむプの䞡方でハッシュテヌブルをパラメヌタヌ化する必芁がありたす

type HashTable k v struct {
    Keys []k
    Values []v
}

func (h *(HashTable k v)) Insert(key k, value v) {
    // You can't actually do anything with k, as it's unconstrained. i.e. you can't hash it, compare it

    // Implementing this is impossible in your proposal.
}

// If it weren't impossible, you'd get this:
h := new(HashTable hasherA int)
h[hasherA(42)] = 1
h[hasherB("Hello world")] = 2 // compile error - can't use hasherB as hasherA

たたは、それが圹立぀堎合は、ハッシュセットを実装しようずしおいるず想像しおください。 同じ問題が発生したすが、結果のコンテナには、 interface{}を超える远加の型チェックがありたせん。

これが、提案が最も基本的なナヌスケヌスに察応しおいない理由です。ポリモヌフィズムを制玄するためにむンタヌフェヌスに䟝存しおいたすが、実際にはそれらのむンタヌフェヌスの敎合性をチェックする方法を提䟛しおいたせん。 䞀貫性のある型チェックを行うこずも、ポリモヌフィズムを制玄するこずもできたすが、䞡方を行うこずはできたせん。 しかし、䞡方が必芁です。

Goでゞェネリックスの実装を成功させるには、絶察に次のようなものが必芁ですか

それは少なくずも私がそれに぀いおどう感じおいるか、ええ、ほずんどです。 提案がタむプセヌフなコンテナの䜜成や゜ヌトを蚱可しない堎合、たたは 既存の蚀語にコストを正圓化するのに十分重芁なものを実際に远加するこずはありたせん。

@メロノィクスわかりたした。 私はあなたが䜕を望んでいるのか理解しおいるず思いたす。 あなたのナヌスケヌスは私が望むものから非垞に遠いこずを芚えおおいおください。 あなたが蚀ったように、それは少数意芋かもしれないず私は思うが、私はタむプセヌフな容噚を本圓にかゆくはしおいない。 私が芋たい最倧のこずのいく぀かは、゚ラヌではなく結果タむプであり、どこでも重耇や反映のない簡単なスラむス操䜜であり、私の提案は適切な察凊方法を実行したす。 ただし、基本的なナヌスケヌスがむンタヌフェむスを䜿甚せずに汎甚コンテナを䜜成しおいる堎合、どのように「最も基本的なナヌスケヌスに察応しおいない」かがわかりたす。

このむンタヌフェむスは、長さずスワッピングのリフレクションに䟝存しおいるため、ゞェネリックスの提案ではただ䜿甚できないこずに泚意しおくださいしたがっお、スラむス操䜜に制玄がありたす。 そのAPIをゞェネリックスが達成できるはずの䞋限ずしお受け入れたずしおも倚くの人はそうしたせん。そのAPIの型安党性の欠劂に぀いおはただ倚くの䞍満がありたす、あなたの提案は合栌したせん。そのバヌ。

これを読むず、この提案の䞋で䞀般的なスラむスがどのように機胜するか/すべきかを完党に誀解しおいるこずは明らかです。 この誀解によっお、「このむンタヌフェヌスはただあなたの提案では䞍可胜である」ずいう誀った結論に達したのです。 どんな提案の䞋でも、䞀般的なスラむスが可胜でなければなりたせん、これは私が思うこずです。 そしお、私が芋た䞖界のlen()は、次のように定矩されたす。 func len(slice []a)これは、任意のスラむスに察しお非反射的な方法で長さをカりントできるこずを意味する䞀般的なスラむス匕数です。 これが先ほど申し䞊げたようにスラむス操䜜が簡単この提案のポむントの倚くであり、私が䞎えた䟋ず私が䜜った芁点を通しおそれをうたく䌝えるこずができなかったのは残念です。 䞀般的なスラむスは、今日の[]intず同じくらい簡単に䜿甚できるはずです。これに察応しおいない提案スラむス/配列の亀換、割り圓お、len、capなどに぀いおは、もう䞀床蚀いたす。 私の意芋では䞍十分です。

そうは蚀っおも、今ではお互いの目暙が䜕であるかがはっきりずわかりたした。 私がやったこずを提案したずき、それは単に構文䞊の提案であり、詳现は非垞に曖昧であるず非垞に蚀いたした。 しかし、ずにかく詳现に取り掛かったのですが、それらの詳现の1぀は制玄がないこずでした。私がそれを曞いたずき、私がやりたいこずにずっお重芁ではないので、それらを念頭に眮いおいたせんでした。 、それらを远加できなかった、たたはそれらが望たしくないずいうこずではありたせん。 提案された構文を続行し、制玄をシュヌホヌンしようずする際の䞻な問題は、䞀般的な匕数の定矩が珟圚意図的に繰り返されおいるため、制玄などを決定するために他の堎所でコヌドを参照するこずがないこずです。どうすればこれを維持できるかわかりたせん。

最良の反䟋は、前に説明した゜ヌト関数です。

type Sort(slice []a:Lesser, less func(a:Lesser, a:Lesser)) { ... }

ご芧のずおり、これを実珟するための優れた方法はありたせん。ゞェネリックスぞのトヌクンスパムアプロヌチは、再び良く聞こえ始めたす。 これらの制玄を定矩するには、元の提案から2぀のこずを倉曎する必芁がありたす。

  • 型匕数をポむントしお制玄を䞎える方法が必芁です。
  • 制玄は単䞀の定矩よりも長く続く必芁がありたす。おそらくそのスコヌプはタむプであり、おそらくそのスコヌプはファむルですファむルは実際にはかなり合理的に聞こえたす。

免責事項以䞋は提案の実際の修正ではありたせん。ランダムな蚘号を投げおいるだけです。これらの構文を䟋ずしお䜿甚しお、提案を元の状態に修正するために䜕ができるかを瀺しおいたす。

// Decorator style, follows the definition of the type thorugh all
// of it's methods.
<strong i="14">@a</strong>: Lesser, Hasher, Equaler
func Sort(slice []a) { ... }
<strong i="15">@k</strong>: Equaler, Hasher
type HashTable k v struct

// Inline, follows the definition of the type through
// all of it's methods.
func [a: Hasher, Equaler] Sort(slice []a) { ... }
type [k: Hasher, Equaler] HashTable k v struct

// File-scope global style, if k appears as a generic argument
// it's constrained by this that appears at the top of the file underneath
// the imports but before any other code.
<strong i="16">@k</strong>: Equaler, Hasher

繰り返しになりたすが、䞊蚘のどれも実際には提案に远加したくないこずに泚意しおください。 問題を解決するためにどのような構成を䜿甚できるかを瀺しおいるだけであり、それらがどのように芋えるかは今のずころやや無関係です。

次に答える必芁のある質問は、暗黙の䞀般的な匕数からただ䟡倀を埗るのかずいうこずです。 提案の䞻なポむントは、蚀語のクリヌンなGoのような感觊を維持し、物事をシンプルに保ち、過剰なトヌクンを排陀するこずによっお物事を十分に䜎ノむズに保぀こずでした。 マップ関数や結果タむプの定矩など、制玄が䞍芁な倚くの堎合、芋栄えは良く、Goのように感じたすか、䟿利ですか 制玄が䜕らかの圢で利甚可胜であるず仮定したす。

func map(slice []a, mapper func(a) b) {
  for i := range slice {
    slice[i] = mapper(slice[i])
  }
}

type Result a b struct {
  Ok  a
  Err b
}

@aarondl説明しおみたす。 型制玄が必芁な理由は、それが型の関数たたはメ゜ッドを呌び出すこずができる唯䞀の方法だからです。 制玄のない型a考えおみおください。これはどの型である可胜性がありたすか。文字列、Intなどの可胜性がありたす。 したがっお、タむプがわからないため、関数やメ゜ッドを呌び出すこずはできたせん。 型スむッチずランタむムリフレクションを䜿甚しお型を取埗し、その䞊でいく぀かの関数たたはメ゜ッドを呌び出すこずができたすが、これはゞェネリックスでは避けたいものです。 たずえば、タむプを制玄する堎合、 aは動物であり、 aで動物に察しお定矩された任意のメ゜ッドを呌び出すこずができたす。

あなたの䟋では、はい、マッパヌ関数を枡すこずができたすが、これにより、関数が倚くの匕数を取るこずになり、基本的にはむンタヌフェむスのない蚀語のようになり、ファヌストクラスの関数だけになりたす。 タむプaで䜿甚するすべおの関数を枡すず、実際のプログラムで非垞に長い関数のリストが取埗されたす。特に、䟝存性泚入甚のゞェネリックコヌドを䞻に蚘述しおいる堎合は、次のようにしたす。結合を最小限に抑えたす。

たずえば、mapを呌び出す関数も汎甚である堎合はどうなりたすか ゞェネリックなどを呌び出す関数の堎合はどうなりたすか。 aのタむプがただわからない堎合、マッパヌをどのように定矩したすか

func m(slice []a) []b {
   mapper := func(x a) b {...}
   return map(slice, mapper)
}

mapperを定矩しようずするず、 xでどの関数を呌び出すこずができたすか

@keean制玄の目的ず機胜を理解しおいたす。 私は単に、ゞェネリックコンテナ構造䜓いわばゞェネリックコンテナではないやゞェネリックスラむスのような単玔なものほど高く評䟡しおいないため、元の提案にそれらを含めおいたせんでした。

私は今でも、䟝存性泚入を行っおいる堎所のような問題に察する正しい答えはむンタヌフェヌスであるず信じおいたす。それは単にゞェネリックスにずっお正しい堎所ではないようですが、私が蚀うには誰ですか。 圌らの責任の重耇は私の目には非垞に倧きいので、なぜ@Meroviusず私は、圌らなしで生きられるかどうかに぀いお話し合う必芁がありたした。圌は、いく぀かのナヌスケヌスで圹立぀ず私に確信させおくれたした。私が最初に行った提案に機胜を远加するために私たちができるかもしれないこずを少し調べたした。

あなたの䟋ずしお、xで関数を呌び出すこずはできたせん。 ただし、それ自䜓で非垞に圹立぀他のスラむスず同じように、スラむスを操䜜するこずもできたす。 たた、func内のfuncが䜕であるかわからない...倚分あなたはvarに割り圓おる぀もりでしたか

@aarondl
おかげさたで構文を修正したしたが、意味はただはっきりしおいるず思いたす。

䞊蚘の䟋では、パラメトリックポリモヌフィズムずむンタヌフェむスの䞡方を䜿甚しお、ある皋床のゞェネリックプログラミングを実珟したしたが、倚重ディスパッチがないため、達成可胜な䞀般性のレベルに垞に䞊限がありたす。 そのため、Goは私が探しおいる機胜を蚀語で提䟛しないようです。぀たり、䞀郚のタスクにGoを䜿甚できないわけではありたせん。実際、私はすでに䜿甚しおおり、䜿甚したこずがある堎合でも正垞に機胜したす。実際には1぀の定矩しか必芁ずしないコヌドをカットアンドペヌストしたす。 将来、そのコヌドを倉曎する必芁がある堎合、開発者が貌り付けられたすべおのむンスタンスを芋぀けるこずができるこずを願っおいたす。

それから私は、蚀語にそのような倧きな倉曎を加えるこずなく可胜な限られた䞀般性が、それが远加する耇雑さを考慮しお、良い考えであるかどうかに぀いお、2぀の考えを持っおいたす。 たぶん、Goの方がシンプルなたたで、前凊理のようなマクロや、Goにコンパむルされる他の蚀語を远加しお、これらの機胜を提䟛できたすか 䞀方、パラメトリック倚型を远加するこずは、良い最初のステップです。 これらのタむプパラメヌタを制玄できるようにするこずは、次の良いステップです。 次に、関連付けられた型パラメヌタヌをむンタヌフェヌスに远加するず、かなり䞀般的なものになりたすが、それはおそらく、倚重ディスパッチなしで取埗できる範囲です。 別々の小さな機胜に分割するこずで、それらが受け入れられる可胜性が高くなるず思いたすか

@keean
倚重ディスパッチは必芁ですか ネむティブにサポヌトしおいる蚀語はほずんどありたせん。 C ++でさえそれをサポヌトしおいたせん。 Cはdynamicを介しおそれをサポヌトしおいたすが、実際に䜿甚したこずはなく、䞀般的なキヌワヌドは実際のコヌドでは非垞にたれです。 私が芚えおいる䟋は、ゞェネリックスを曞くのではなく、JSON解析のようなものを扱っおいたす。

倚重ディスパッチは必芁ですか

私芋、 @ keeanは、型クラス/むンタヌフェヌスによっお提䟛される静的倚重ディスパッチに぀いお話しおいるず思いたす。
これは、メ゜ッドのオヌバヌロヌドによっおC ++でも提䟛されたすCに぀いおはわかりたせん

぀たり、動的な倚重ディスパッチは、共甚䜓型のない静的蚀語では非垞に面倒です。 動的蚀語は、静的型チェック動的蚀語の郚分的な型掚論、Cの「動的」型の堎合ず同じを省略するこずで、この問題を回避したす。

タむプを「単なる」パラメヌタずしお提䟛できたすか

func Append(t, t2 type, arr []t, value t2) []t {
    v := t(value) // conversion
    return append(arr, v)
}

var arr []float64
v := 0

arr = Append(float64, int, arr, v)

@Inuartは曞いた

タむプを「単なる」パラメヌタずしお提䟛できたすか

これがどの皋床可胜であるか、たたは倖出先で望たれるかに぀いおは疑わしい

䞀般的な制玄がサポヌトされおいる堎合は、代わりに必芁なこずを実珟できたす。

func Append(arr []t, value s) []t  requires Convertible<s,t>{
    v := t(value) // conversion
    return append(arr, v)
}

var arr []int64
v := 0.5

arr = Append(arr, v)

たた、これは制玄付きでも可胜であるはずです。

func convert(value s) t requires Convertible<s,t>{
    return t(value);
}

f:float64:=2.0

i:int64=convert(f)

その䟡倀に぀いおは、私たちのGenus蚀語は耇数のディスパッチをサポヌトしおいたす。 制玄のモデルは、にディスパッチされる耇数の実装を提䟛できたす。

コンパむル時の安党性のためにConvertible<s,t>衚蚘が必芁であるこずを理解しおいたすが、ランタむムチェックに䜎䞋する可胜性がありたす

func Append(t, t2 type, arr []t, value t2) []t {
    v, ok := t(value) // conversion
    if !ok {
        panic(...) // or return an err
    }
    return append(arr, v)
}

var arr []float64
v := 0

arr = Append(float64, int, arr, v)

しかし、これはreflectのシンタックスシュガヌのように芋えたす。

@Inuartのポむントは、コンパむラがコンパむル時に型が型クラスを実装しおいるこずを確認できるため、実行時の確認は䞍芁です。 利点は、パフォヌマンスの向䞊ですいわゆるれロコストの抜象化。 ランタむムチェックの堎合は、 reflectを䜿甚するこずもできたす。

@creker

倚重ディスパッチは必芁ですか

私はこれに぀いおあたりにも気にしおいたす。 䞀方では、耇数パラメヌタヌ型クラスを䜿甚した倚重ディスパッチは、「Go」が「むンタヌフェヌス倀」ず呌ぶ実存的存圚ではうたく機胜したせん。

type Equals<T> interface {eq(right T) bool}
(left I) eq(right I) bool {return left == right}
(left I) eq(right F) bool {return false}
(left F) eq(right I) bool {return false}
(left F) eq(right F) bool {return left == right}

func main() {
    x := []Equals<?>{I{2}, F{4.0}, I{2}, F{4.0}}
}

Equalsのスラむスを定矩するこずはできたせん。これは、右偎のパラメヌタヌが同じコレクションからのものであるこずを瀺す方法がないためです。 Haskellではこれを行うこずさえできたせん

data Equals = forall a . IEquals a a => Equals a

タむプをそれ自䜓ず比范するこずしかできないので、これは良くありたせん

data Equals = forall a b . IEquals a b => Equals a

bをaず同じコレクション内の別の存圚になるように制玄する方法がないため、これは適切ではありたせん aがコレクション内にある堎合でも。

ただし、新しいタむプでの拡匵は非垞に簡単です。

(left K) eq(right I) bool {return false}
(left K) eq(right F) bool {return false}
(left I) eq(right K) bool {return false}
(left F) eq(right K) bool {return false}
(left K) eq(right K) bool {return left == right}

そしお、これはデフォルトのむンスタンスたたは特殊化でさらに簡朔になりたす。

䞀方、これを「Go」で曞き盎すこずができたす。これは珟圚機胜しおいたす。

package main

type I struct {v int}
type F struct {v float32}

type EqualsInt interface {eqInt(left I) bool}
func (right I) eqInt (left I) bool {return left == right}
func (right F) eqInt (left I) bool {return false}

type EqualsFloat interface {eqFloat(left F) bool}
func (right I) eqFloat (left F) bool {return false}
func (right F) eqFloat (left F) bool {return left == right}

type EqualsRight interface {
    EqualsInt
    EqualsFloat
}

type EqualsLeft interface {eq(right EqualsRight) bool}
func (left I) eq (right EqualsRight) bool {return right.eqInt(left)}
func (left F) eq (right EqualsRight) bool {return right.eqFloat(left)}

type Equals interface {
    EqualsLeft
    EqualsRight
}

func main() {
    x := []Equals{I{2}, F{4.0}, I{2}, F{4.0}}
    println(x[0].eq(x[1]))
    println(x[1].eq(x[0]))
    println(x[0].eq(x[2]))
    println(x[1].eq(x[3]))
}

これは実存的むンタヌフェヌス倀でうたく機胜したすが、はるかに耇雑で、䜕が起こっおいるのか、どのように機胜するのかを確認するのが難しく、タむプごずに1぀のむンタヌフェヌスが必芁であり、蚱容可胜なものをハヌドコヌディングする必芁があるずいう倧きな制限がありたすこのような右偎のタむプ

type EqualsRight interface {
    EqualsInt
    EqualsFloat
}

぀たり、むンタヌフェむスEqualsRightは拡匵できないため、ラむブラリ゜ヌスを倉曎しお新しいタむプを远加する必芁がありたす。

したがっお、マルチパラメヌタむンタヌフェむスがないず、等匏のような拡匵可胜な汎甚挔算子を定矩できたせん。 マルチパラメヌタむンタヌフェむスでは、存圚むンタヌフェむス倀が問題になりたす。

提案された倚くの構文構文 Blah[E]に関する私の䞻な問題は、基瀎ずなる型にゞェネリックスの包含に関する情報が衚瀺されないこずです。

䟋えば

type Comparer[C] interface {
    Compare(other C) bool
}
// or
type Comparer c interface {
    Compare(other c) bool
}
...

これは、基になる型にさらに情報を远加する新しい型を宣蚀しおいるこずを意味したす。 type宣蚀のポむントは、別のタむプに基づいお名前を定矩するこずではありたせんか

私は次の行に沿っお構文をもっず提案したいず思いたす

type Comparer interface[C] {
    Compare(other C) bool
}

぀たり、実際にはComparerはinterface[C] { ... }に基づくタむプであり、 interface[C] { ... }はもちろんinterface { ... }ずは別のタむプです。 これにより、必芁に応じお、名前を付けずに汎甚むンタヌフェむスを䜿甚できたす通垞のむンタヌフェむスで蚱可されおいたす。 この゜リュヌションはもう少し盎感的で、Goの型システムでうたく機胜するず思いたすが、間違っおいる堎合は蚂正しおください。

泚ゞェネリック型の宣蚀は、次の構文のむンタヌフェむス、構造䜓、および関数でのみ蚱可されたす。
interface[G] { ... }
struct[G] { ... }
func[G] (vars...) { ... }

次に、ゞェネリックを「実装」するず、次の構文になりたす。
interface[G] { ... }[string]
struct[G] { ... }[string]
func[G] (vars...) { ... }[int](args...)

そしお、もう少し明確にするためのいく぀かの䟋を瀺したす。

むンタヌフェヌス

package add

type Adder interface[E] {
    // Adds the element and returns the size
    Add(elem E) int
}

// Adds the integer 5 to any implementation of Adder[int].
func AddFiveTo(a Adder[int]) int {
    return a.Add(5)
}

構造䜓

package heap

type List struct[T] {
    slice []T
}

func (l *List) Add(elem T) { // T is a type defined by the receiver
    l.slice = append(l.slice, elem)
}

機胜

func[A] AddManyTo(a Adder[A], many ...A) {
    for _, each := range a {
        a.Add(each)
    }
}

これはGo2契玄ドラフトに察応しおおり、その構文を䜿甚したすが、パラメトリック倚型の提案に適甚されるため、ここに投皿したす。

タむプパラメヌタの埋め蟌みは蚱可されるべきではありたせん。

怜蚎

type X(type T C) struct {
  R // A regular type with method Foo()
  T // Some type parameter
}
// X defines some methods other than Foo(),
// some of which invoke Foo.

いく぀かの任意の型RずFoo()を含たないいく぀かの任意の契玄C $の堎合。

Tには、 Cに必芁なすべおのセレクタヌが含たれたすが、 Tの特定のむンスタンス化には、 Fooを含む任意の他のセレクタヌも含たれる堎合がありたす。

Barが、 Cの䞋で蚱容される構造䜓であり、 Fooずいう名前のフィヌルドがあるずしたす。

X(Bar)は違法なむンスタンス化である可胜性がありたす。 タむプにセレクタヌがないずいうコントラクトを指定する方法がなければ、これは掚枬されたプロパティである必芁がありたす。

X(Bar)のメ゜ッドは、$ Foo X(Bar).R.Foo $ずしお解決し続けるこずができたす。 これにより、ゞェネリック型の蚘述が可胜になりたすが、解決ルヌルの問題に慣れおいない読者にずっおは混乱を招く可胜性がありたす。 Xのメ゜ッド以倖では、セレクタヌはあいたいなたたなので、 interface { Foo() }はXのパラメヌタヌに䟝存したせんが、 Xの䞀郚のむンスタンス化はそれを満たさない。

タむプパラメヌタの埋め蟌みを犁止する方が簡単です。

ただし、これが蚱可される堎合、 type S = io.Readerずしお定矩された埋め蟌みSのフィヌルド名がSであるのず同じ理由で、フィヌルド名はTになりたす。 Sであり、 Readerではありたせんが、 Tむンスタンス化する型は、必ずしも名前を持っおいる必芁はないためです。

@jimmyfrascheゞェネリック型の埋め蟌みフィヌルドは、堎所に少し厄介な郚分がある堎合でも、それらを蚱可するのに十分圹立぀ず思いたす。 私の提案は、すべおのゞェネリックコヌドで、埋め蟌み型がすべおの可胜なレベルですべおの可胜なフィヌルドずメ゜ッドを定矩しおいるず想定するこずです。これにより、ゞェネリックコヌド内で、非ゞェネリック型のすべおの埋め蟌みメ゜ッドずフィヌルドが消去されたす。

そのように䞎えられた

type R struct(type T) {
    io.Reader
    T
}

Rのメ゜ッドは、Readerを介しお間接化せずにRのReadを呌び出すこずはできたせん。 䟋えば

func (r R) Do() {
     r.Read(buf)     // Illegal
     r.Reader.Read(buf)  // ok
}

これに぀いお私が芋るこずができる唯䞀の欠点は、動的型が静的型よりも倚くのメンバヌを含む可胜性があるこずです。 䟋えば

func (r R) Do() {
    var x interface{} = r
    x.(io.Reader)    // Succeeds
}

@rogpeppe

これに぀いお私が芋るこずができる唯䞀の欠点は、動的型が静的型よりも倚くのメンバヌを含む可胜性があるこずです。

これは型パラメヌタヌに盎接圓おはたるので、パラメトリック型でも問題ないず思いたす。 @jimmyfrascheが提瀺した問題の解決策は、パラメヌタヌ化された型の目的のメ゜ッドセットをコントラクトに入れるこずかもしれないず思いたす。

contract C(t T) {
  interface { Foo() } (X(T){})
  // ...
}

type X(type T C) struct {
  R // A regular type with method Foo()
  T // Some type parameter
}
// X defines some methods other than Foo(),
// some of which invoke Foo.

これにより、 FooをX盎接呌び出すこずができたす。 もちろん、これは「契玄にロヌカル名がない」ずいうルヌルに反するこずになりたす...

@stevenblenkinsopうヌん、厄介な堎合は、 Xを参照せずにそれを行うこずができたす

contract C(t T) {
  struct{ R; T }{}.Foo
}

Cは、もう少し緩くはありたすが、 Xの実装にバむンドされおいたす。

あなたがそれをしなければ、あなたは曞く

func (x X(T)) Fooer() interface { Foo() } {
  return x
}

コンパむルしたすか 契玄で保蚌をしない堎合にも採甚する必芁があるず思われる@rogpeppeのルヌルには埓わないでしょう。 しかし、それは、十分なコントラクトなしで型匕数を埋め蟌む堎合、たたはすべおの埋め蟌みにのみ適甚されたすか

単にそれを犁止する方が簡単でしょう。

Go2ドラフトが発衚される前に、私はこの提案に取り組み始めたした。

アナりンスを芋たずき、喜んでスクラップする準備ができおいたしたが、ドラフトの耇雑さにただ䞍安を感じおいたので、仕䞊げたした。 それほど匷力ではありたせんが、よりシンプルです。 他に䜕もないずしおも、それは盗む䟡倀のあるビットを持っおいるかもしれたせん。

@ianlancetaylorの以前の提案の構文を拡匵したものです。これは、私が始めたずきに利甚可胜だったものです。 それは基本的なこずではありたせん。 (type Tなどの構文たたは同等のものに眮き換えるこずができたす。 セマンティクスの衚蚘法ずしお構文が必芁でした。

ここにありたす https //gist.github.com/jimmyfrasche/656f3f47f2496e6b49e041cd8ac716e4

ルヌルは、1型匕数のIDがわかっおいるか、2メ゜ッドが倖郚で呌び出し可胜であるず䞻匵されない限り、埋め蟌み型パラメヌタヌよりも深いずころからプロモヌトされたメ゜ッドを呌び出すこずができないずいうこずです。タむプパラメヌタを制玄するコントラクトでタむプしたす。 コンパむラヌは、プロモヌトされたメ゜ッドが倖郚型O内に持぀必芁のある深さの䞊限ず䞋限を刀別し、それらを䜿甚しお、メ゜ッドがOを埋め蟌む型で呌び出し可胜かどうかを刀別するこずもできたす。぀たり、他の促進された方法ず競合する可胜性があるかどうか。 同様のこずが、呌び出し可胜なメ゜ッドを持぀ようにアサヌトされおいるすべおの型パラメヌタヌにも圓おはたりたす。ここで、型パラメヌタヌ内のメ゜ッドの深さの範囲は[0、infになりたす。

タむプパラメヌタの埋め蟌みは、完党に犁止するにはあたりにも䟿利なようです。 䞀぀には、それは透明な構成を可胜にしたすが、それは埋め蟌みむンタヌフェヌスのパタヌンでは蚱可されたせん。

たた、契玄の定矩にも䜿甚できる可胜性がありたす。 *Tでメ゜ッドが定矩されおいる可胜性のあるタむプT ポむンタヌタむプの堎合もありたすの倀を受け入れられるようにし、その倀をむンタヌフェむスでは、メ゜ッドが*Tにある可胜性があるため、必ずしもTをむンタヌフェむスに配眮するこずはできたせん。たた、 *T Tむンタヌフェむスに配眮するこずはできたせん。 *Tには空のメ゜ッドが蚭定されおいる可胜性がありたす。 ただし、次のようなラッパヌがある堎合

type Wrapper(type T) { T }

コントラクトがむンタヌフェヌスを満たしおいるず蚀っおいる堎合は、すべおの堎合にむンタヌフェヌスに*Wrapper(T)を入れるこずができたす。

あなたはただするこずはできたせん

type Interface interface {
  SomeMethod(int) error
}

contract MightBeAPointer(t T) {
  Interface(t)
}

func Example(type T MightBeAPointer)(v T) {
  var i Interface = v
  // ...
}

誰かが電話をかけた堎合に察凊しようずしおいたす

type S struct{}
func (s *S) SomeMethod(int) error { ... }
...
var s S
Example(S)(s)

SはInterfaceに倉換できず、 *Sのみが倉換できるため、これは機胜したせん。

明らかに、答えは「そうしないでください」かもしれたせん。 ただし、契玄提案では、次のような契玄に぀いお説明しおいたす。

contract Contract(t T) {
    var _ error = t.SomeMethod(int(0))
}

Sは、 *Sず同様に、自動アドレス指定によりこの契玄を満たしたす。 私が察凊しようずしおいるのは、コントラクトのメ゜ッド呌び出しずむンタヌフェヌス倉換の間の機胜のギャップです。

ずにかく、これは少し接線であり、タむプパラメヌタを埋め蟌むための1぀の朜圚的な甚途を瀺しおいたす。

再埋め蟌み、「構造䜓に埋め蟌むこずができる」ずいうのは、蚱可された堎合にコントラクトがキャプチャしなければならないもう1぀の制限だず思いたす。

怜蚎

contract Embeddable(type X, Y) {
    type S struct {
        X
        Y
    }
}

type Embedded(type First, Second Embeddable) struct {
        First
        Second
}

// Error: First and Second both provide method Read.
// That must be diagnosed to the Embeddable contract, not the definition of Embedded itself.
type Boom = Embedded(*bytes.Buffer, *strings.Reader)

@bcmillsは、あいたいなセレクタヌを䜿甚しお型を埋め蟌むこずが蚱可されおいるため、そのコントラクトがどのように解釈されるのかわかりたせん。

ずにかく、既知のタむプのみを埋め蟌む堎合は問題ありたせん。 タむプパラメヌタのみを埋め蟌む堎合は問題ありたせん。 奇劙になる唯䞀のケヌスは、1぀以䞊の既知の型ず1぀以䞊の型パラメヌタヌを埋め蟌んだ堎合ず、既知の型のセレクタヌず型匕数が互いに玠でない堎合のみです。

@bcmillsは、あいたいなセレクタヌを䜿甚しお型を埋め蟌むこずが蚱可されおいるため、そのコントラクトがどのように解釈されるのかわかりたせん。

うヌん、良い点。 ゚ラヌをトリガヌするためのもう1぀の制玄がありたせん。¹

contract Embeddable(type X, Y) {
    type S struct {
        X
        Y
    }
    var _ io.Reader = S{}
}

¹https //play.golang.org/p/3wSg5aRjcQc

これには、 XたたはYのいずれかが必芁ですが、䞡方がio.Readerである必芁はありたせん。 契玄システムがそれを可胜にするのに十分衚珟力があるのは興味深いこずです。 そのような獣の型掚論芏則を理解する必芁がないのはうれしいです。

しかし、それは実際には問題ではありたせん。

それはあなたがするずきです

type S (type T C) struct {
  io.Reader
  T
}
func (s *S(T)) X() io.Reader {
  return s
}

Cが持っおいない限り、 TはReadセレクタヌを持぀こずができるので、それはコンパむルに倱敗するはずです

struct{ io.Reader; T }.Read

しかし、 Cがセレクタヌセットが互いに玠であるこずを保蚌せず、 Sがセレクタヌを参照しない堎合のルヌルは䜕でしょうか あいたいなセレクタヌを䜜成するタむプを陀いお、すべおのむンスタンス化Sがむンタヌフェむスを満たすこずは可胜ですか

あいたいなセレクタヌを䜜成するタむプを陀いお、すべおのむンスタンス化Sがむンタヌフェむスを満たすこずは可胜ですか

はい、そうです。 それはもっず深いこずを意味するのだろうか...🀔

私は取り返しの぀かないほど厄介なものを構築するこずができたせんでしたが、非察称性は非垞に䞍快であり、私を䞍安にさせたす

type I interface { /* ... */ }
a := G(A) // ok, A satisfies contract
var _ I = a // ok, no selector overlap
b := G(B) // ok, B satisfies contract
var _ = b // error, selector overlap

G0(B)がG1(B)を䜿甚する堎合の゚ラヌメッセヌゞが心配です。 。 。 Gn(B)を䜿甚し、$ Gnが゚ラヌの原因です。 。 。 。

FTR、埋め蟌みでタむプ゚ラヌをトリガヌするためにあいたいなセレクタヌの問題を経隓する必芁はありたせん。

// Error: Duplicate field name Reader
type Boom = Embedded(*bytes.Reader, *strings.Reader)

埋め蟌みフィヌルド名は匕数の型に基づいおいるず想定しおいたすが、埋め蟌み型パラメヌタヌの名前である可胜性が高くなりたす。 これは、タむプ゚むリアスを埋め蟌み、フィヌルド名が゚むリアスするタむプの名前ではなく゚むリアスである堎合ず䌌おいたす。

これは、パラメヌタ化された型に関するセクションのドラフト蚭蚈で実際に指定されおいたす。

パラメヌタ化された型が構造䜓であり、型パラメヌタが構造䜓のフィヌルドずしお埋め蟌たれおいる堎合、フィヌルドの名前は型匕数の名前ではなく、型パラメヌタの名前になりたす。

type Lockable(type T) struct {
    T
    mu sync.Mutex
}

func (l *Lockable(T)) Get() T {
    l.mu.Lock()
    defer l.mu.Unlock()
    return l.T
}

泚メ゜ッド宣蚀にLockableXを蚘述した堎合、これはうたく機胜したせん。メ゜ッドはlTたたはlXを返す必芁がありたすかおそらく、構造䜓ぞの型パラメヌタヌの埋め蟌みを犁止する必芁がありたす。

私はただ傍芳者ずしおここに座っお芳察しおいたす。 しかし、少し心配するこずもありたす。

私が恥ずかしくないこずの1぀は、この議論の90が私の頭䞊にあるずいうこずです。

ゞェネリックスやパラメトリックポリモヌフィズムが䜕であるかを知らずに゜フトりェアを曞くこずで生蚈を立おおきた20幎は、私が仕事を成し遂げるこずを劚げおいないようです。

悲しいこずに、私はGoを孊ぶのに玄1幎前の時間しかかかりたせんでした。 私はそれが急な孊習曲線であり、生産的になるのに時間がかかりすぎるず誀った仮定をしたした。

私はもっ​​ず間違っおいたはずがない。

私は、週末以内にパフォヌマンスの問題を抱えおいたnode.jsサヌビスを完党に砎壊するマむクロサヌビスを構築するために十分なGoを孊ぶこずができたした。

皮肉なこずに、私はただ遊んでいたした。 私は囲碁で䞖界を埁服するこずに぀いお特に真剣ではありたせんでした。

それでも、数時間以内に、私は自分の前かがみの敗北した姿勢から立ち䞊がっおいるこずに気づきたした。たるで、自分の垭の端でアクションスリラヌを芋おいるようでした。 私が構築しおいたAPIは非垞に迅速に統合されたした。 明らかにそのデザむンが非垞に実甚的だったので、これは確かに私の貎重な時間を投資する䟡倀のある蚀語であるこずに気づきたした。

そしお、それが私がGoに぀いお気に入っおいるこずです。 それは非垞に速いです.....孊ぶために。 私たちは皆、そのパフォヌマンス胜力を知っおいたす。 しかし、それを孊ぶこずができる速床は、私が長幎にわたっお孊んだ他の8぀の蚀語ずは比べものにならないほどです。

それ以来、私はGoの称賛を歌い続け、さらに4人の開発者にそれを気に入っおもらいたした。 私は圌らず数時間座っお䜕かを䜜りたす。 結果はそれ自䜓を物語っおいたす。

シンプルさ、そしお孊ぶスピヌド。 これらは、蚀語の真のキラヌ機胜です。

䜕ヶ月にもわたるハヌドスログ孊習を必芁ずするプログラミング蚀語は、倚くの堎合、圌らが匕き付けようずしおいる開発者そのものを保持しおいたせん。 私たちにはやるべき仕事があり、毎日進歩を芋たいず思っおいる雇甚䞻アゞャむルに感謝し、感謝したす

ですから、Goチヌムが考慮に入れおほしいこずが2぀ありたす。

1私たちが解決しようずしおいる日々の問題は䜕ですか

ゞェネリックスや、ゞェネリックスず呌ばれるものによっお解決されるショヌストッパヌを䜿甚した、実際の䟋を芋぀けるこずができないようです。

問題のある日垞のタスクのクックブックスタむルの䟋ず、これらの蚀語倉曎の提案によっおどのように改善されるかに぀いおの䟋。

2Goの他のすべおの優れた機胜ず同様に、シンプルに保ちたす

ここにいく぀かの信じられないほどむンテリゞェントなコメントがありたす。 しかし、私のような䞀般的なプログラミングに日垞的にGoを䜿甚しおいる開発者の倧倚数は、珟状に完党に満足しおいお生産的であるず確信しおいたす。

おそらく、そのような高床な機胜を有効にするためのコンパむラの議論ですか '-ハヌドコア'

コンパむラのパフォヌマンスに悪圱響を䞎えたら、本圓に悲しいです。 ただ蚀っお

そしお、それが私がGoに぀いお気に入っおいるこずです。 それは非垞に速いです.....孊ぶために。 私たちは皆、そのパフォヌマンス胜力を知っおいたす。 しかし、それを孊ぶこずができる速床は、私が長幎にわたっお孊んだ他の8぀の蚀語ずは比べものにならないほどです。

同意したす。 完党にコンパむルされた蚀語でのパワヌずシンプルさの組み合わせは、完党にナニヌクなものです。 私は間違いなくGoがそれを倱いたくないし、ゞェネリックが欲しいのず同じくらい、その費甚でそれだけの䟡倀があるずは思わない。 しかし、それを倱う必芁はないず思いたす。

ゞェネリックスや、ゞェネリックスず呌ばれるものによっお解決されるショヌストッパヌを䜿甚した、実際の䟋を芋぀けるこずができないようです。

ゞェネリックスの䞻な䜿甚䟋は2぀ありたす。バむナリツリヌ、セット、 sync.Mapなどの耇雑なデヌタ構造のタむプセヌフなボむラヌプレヌト陀去ず、ベヌスで動䜜する_compile-time_タむプセヌフ関数を䜜成する機胜です。メモリ内のレむアりトではなく、玔粋に匕数の機胜に基づいおいたす。 蚀語の単玔さを完党に壊さずにサポヌトを远加するこずが䞍可胜な堎合、私ができるこずを気にしないいく぀かのより玠晎らしいこずがありたすが、私はそれらを行うこずができなくおもかたいたせん。

正盎なずころ、この蚀語にはすでにかなり乱甚されおいる機胜がありたす。 それらが悪甚されない䞻な理由は、ほずんどの堎合、そのようなコヌドのクリヌンで芋぀けやすい䟋を提䟛する暙準ラむブラリず組み合わせお、「慣甚的な」コヌドを曞くずいうGoの文化であるず私は思いたす。 ゞェネリックスを暙準ラむブラリにうたく利甚するこずは、それらを実装する際の優先事項であるこずは間違いありたせん。

@camstuart

ゞェネリックスや、ゞェネリックスず呌ばれるものによっお解決されるショヌストッパヌを䜿甚した、実際の䟋を芋぀けるこずができないようです。

ゞェネリックスは、自分でコヌドを曞く必芁がないようにするためのものです。 したがっお、別のリンクリスト、バむナリツリヌ、deque、たたはpriority-queueを再床実装する必芁はありたせん。 䞊べ替えアルゎリズム、分割アルゎリズム、回転アルゎリズムなどを実装する必芁はありたせん。デヌタ構造は暙準コレクションたずえば、リストのマップを構成し、凊理は暙準アルゎリズムデヌタ、分割、ず回転。 これらのコンポヌネントを再利甚できる堎合、優先床キュヌたたはパヌティショニングアルゎリズムを再実装するたびに、間違っおバグが発生する可胜性があるため、゚ラヌ率が䜎䞋したす。

ゞェネリックずは、曞くコヌドを枛らし、再利甚するこずを意味したす。 ぀たり、暙準のよく維持されたラむブラリ関数ず抜象デヌタ型をより倚くの状況で䜿甚できるため、独自に䜜成する必芁はありたせん。

さらに良いこずに、これらはすべおGoで技術的に実行できたすが、コンパむル時の型安党性がほが完党に倱われ、実行時のオヌバヌヘッドが倧きくなる可胜性がありたす。 ゞェネリックスは、これらの欠点のどちらもなしでそれを行うこずができたす。

ゞェネリック関数の実装

/*

* "generic" is a KIND of types, just like "struct", "map", "interface", etc...
* "T" is a generic type (a type of kind generic).
* var t = T{int} is a value of type T, values of generic types looks like a "normal" type

*/

type T generic {
    int
    float64
    string
}

func Sum(a, b T{}) T{} {
    return a + b
}

関数の呌び出し元

Sum(1, 1) // 2
// same as:
Sum(T{int}(1), T{int}(1)) // 2

ゞェネリック構造䜓の実装

type ItemT generic {
    interface{}
}

type List struct {
    l []ItemT{}
}

func NewList(t ItemT) *List {
    l := make([]t)
    return &List{l}
}

func (p *List) Push(item ItemT{}) {
    p.l = append(p.l, item)
}

発信者

list := NewList(ItemT{int})
list.Push(42)

Swiftを孊んでいお奜きではないが、Go、C、Javaなどの他の蚀語での豊富な経隓を持぀人ずしお。 ゞェネリックスたたはテンプレヌト、たたはあなたがそれを呌びたいものはGo蚀語に远加するのは良いこずではないず私は本圓に信じおいたす。

たぶん私は珟圚のバヌゞョンのGoの経隓が豊富ですが、他の人が曞いたコヌドを理解するのがより難しいずいう点で、これはC ++ぞの回垰のように感じたす。 型の叀兞的なTプレヌスホルダヌは、関数が䜕をしようずしおいるのかを理解するのを非垞に難しくしたす。

これは人気のある機胜リク゚ストなので、着地したら察凊できたすが、2セント意芋を远加したいず思いたした。

@jlubawy
リンクリストやクむック゜ヌトアルゎリズムを実装する必芁がない別の方法を知っおいたすか Alexander Stepanovが指摘しおいるように、ほずんどのプログラマヌは「最小」関数ず「最倧」関数を正しく定矩できないため、倚くのデバッグ時間をかけずに、より耇雑なアルゎリズムを正しく実装する必芁がありたす。 私はむしろ、これらのアルゎリズムの暙準バヌゞョンをラむブラリから匕き出しお、自分が持っおいるタむプに適甚したいず思っおいたす。 どのような遞択肢がありたすか

@jlubawy

たたはテンプレヌト、たたはあなたがそれを呌びたいものは䜕でも

すべおは実装に䟝存したす。 C ++テンプレヌトに぀いお話しおいる堎合は、そうです。䞀般的に理解するのは困難です。 それらを曞くこずさえ難しいです。 䞀方、Cゞェネリックを採甚する堎合、それはたったく別のこずです。 コンセプト自䜓はここでは問題ではありたせん。

ご存じない方のために、GoチヌムはGo2.0のドラフトを発衚したした。
https://golang.org/s/go2designs

Go 2.0契玄のゞェネリックデザむンのドラフトがありたす。 あなたは圌らのWikiを芋おフィヌドバックを䞎えるこずをお勧めしたす。

これは関連するセクションです

ゞェネリック

ドラフトを読んだ埌、私は尋ねたす

なぜ

T远加可胜

「契玄远加可胜を実装するタむプT」を意味したすか 新しいものを远加する理由
そのためのむンタヌフェヌスがすでにある堎合のコンセプトは むンタヌフェむスの割り圓おは
ビルド時間をチェックむンしたので、私たちはすでに䜕も必芁ずしない手段を持っおいたす
ここに远加の抂念。 この甚語を䜿甚しお、次のように蚀うこずができたす。
むンタヌフェむスAddableを実装するタむプT。 さらに、T_たたはTAny
特別なキヌワヌドたたはinterface {}の組み蟌み゚むリアスである
トリック。

そのようなもののほずんどを再実装する理由がわかりたせん。 したせん
センスず冗長性がありたす冗長性ぱラヌの新しい凊理であるため
パニックの凊理。

2018-09-14 6:15 GMT-0500コアラペン[email protected] 

ご存じない方のために、GoチヌムはGo2.0のドラフトを発衚したした。
https://golang.org/s/go2designs

Go 2.0契玄のゞェネリックデザむンのドラフトがありたす。 あなたが望むかもしれたせん
芋お、フィヌドバックを䞎えるために
https://github.com/golang/go/wiki/Go2GenericsFeedback on their Wiki
https://github.com/golang/go/wiki/Go2GenericsFeedback 。

これは関連するセクションです

ゞェネリック

—
コメントしたのでこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-421326634 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AlhWhS8xmN5Y85_aUKT5VnutoOKUAaLLks5ua4_agaJpZM4IG-xv
。

-
これは、TripleMintで䜿甚されるメヌル眲名のテストです。

線集「[...]は、特定の芁件が必芁ない堎合にトリックを実行したす
タむプ匕数」。

2018-09-17 11:10 GMT-0500 Luis Masuelli [email protected] 

ドラフトを読んだ埌、私は尋ねたす

なぜ

T远加可胜

「契玄远加可胜を実装するタむプT」を意味したすか 新しいものを远加する理由
そのためのむンタヌフェヌスがすでにある堎合のコンセプトは むンタヌフェむスの割り圓おは
ビルド時間をチェックむンしたので、私たちはすでに䜕も必芁ずしない手段を持っおいたす
ここに远加の抂念。 この甚語を䜿甚しお、次のように蚀うこずができたす。
むンタヌフェむスAddableを実装するタむプT。 さらに、T_たたはTAny
特別なキヌワヌドたたはinterface {}の組み蟌み゚むリアスである
トリック。

そのようなもののほずんどを再実装する理由がわかりたせん。 したせん
センスず冗長性がありたす冗長性ぱラヌの新しい凊理であるため
パニックの凊理。

2018-09-14 6:15 GMT-0500コアラペン[email protected] 

ご存じない方のために、GoチヌムはGo2.0のドラフトを発衚したした。
https://golang.org/s/go2designs

Go 2.0契玄のゞェネリックデザむンのドラフトがありたす。 しおもいいです
芋お、フィヌドバックを送りたい
https://github.com/golang/go/wiki/Go2GenericsFeedback on their Wiki
https://github.com/golang/go/wiki/Go2GenericsFeedback 。

これは関連するセクションです

ゞェネリック

—
コメントしたのでこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-421326634 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AlhWhS8xmN5Y85_aUKT5VnutoOKUAaLLks5ua4_agaJpZM4IG-xv
。

-
これは、TripleMintで䜿甚されるメヌル眲名のテストです。

-
これは、TripleMintで䜿甚されるメヌル眲名のテストです。

@ luismasuelli-jobsity Goで䞀般的な実装の履歎を正しく読んだ堎合、コントラクトを導入する理由は、むンタヌフェむスでの挔算子のオヌバヌロヌドを望たなかったためず思われたす。

最終的に拒吊された以前の提案では、むンタヌフェむスを䜿甚しおパラメトリックポリモヌフィズムを制玄しおいたしたが、むンタヌフェむスで定矩できないため、このような関数で「+」などの䞀般的な挔算子を䜿甚できなかったため、拒吊されたようです。 コントラクトを䜿甚するず、 t == tたたはt + tを蚘述できるため、型が等匏たたは加算などをサポヌトする必芁があるこずを瀺すこずができたす。

線集たた、Goは耇数の型パラメヌタヌむンタヌフェむスをサポヌトしおいないため、ある意味でGoは、型クラスを2぀の別個のもの、関数型パラメヌタヌを盞互に関連付けるコントラクト、およびメ゜ッドを提䟛するむンタヌフェむスに分離したした。 それが倱うのは、耇数の型に基づいお型クラスの実装を遞択する機胜です。 むンタヌフェむスたたはコントラクトのみを䜿甚する必芁がある堎合は間違いなく簡単ですが、䞡方を䞀緒に䜿甚する必芁がある堎合はより耇雑になりたす。

T:Addableが「コントラクトAddableを実装するタむプT」を意味するのはなぜですか

それは実際にはそれが意味するこずではありたせん。 1぀の型匕数に぀いおはそのように芋えたす。 ドラフトの他の堎所では、関数ごずに1぀のコントラクトしか持おないずいうコメントがありたす。これが䞻な違いです。コントラクトは、実際には、関数のタむプだけでなく、関数のタむプに関するステヌトメントです。 たずえば、

func Example(type K, V someContract)(k K, v V) V

あなたは次のようなこずをするこずができたす

contract someContract(k K, v V) {
  k.someMethod(v)
}

これにより、関数シグニチャで型を冗長に指定するこずなく、耇数の型の調敎が倧幅に簡玠化されたす。 圌らは「䞍思議なこずに繰り返される䞀般的なパタヌン」を避けようずしおいるこずを忘れないでください。 たずえば、型を制玄するために䜿甚されるパラメヌタヌ化されたむンタヌフェヌスを持぀同じ関数は、次のようになりたす。

type someMethoder(V) interface {
  someMethod(V)
}

func Example(type K: someMethoder(V), V)(k K, v V) V

これはちょっず厄介です。 ただし、コントラクトの「匕数」は、関数がパラメヌタヌを入力するのず同じ数のコントラクトを持っおいる堎合、コンパむラヌによっお自動入力されるため、コントラクト構文を䜿甚するず、必芁に応じおこれを実行できたす。 ただし、必芁に応じお手動で指定できたす。぀たり、この状況では特に有甚ではありたせんが、本圓に必芁な堎合はfunc Example(type K, V someContract(K, V))(k K, v V) Vを実行できたす。

コントラクトが個々の匕数ではなく関数党䜓に関するものであるこずを明確にする1぀の方法は、名前に基づいおそれらを単玔に関連付けるこずです。 䟋えば、

contract Example(k K, v V) {
  k.someMethod(v)
}

func Example(type K, V)(k K, v V) V

䞊蚘ず同じになりたす。 ただし、欠点は、コントラクトが再利甚できず、コントラクトの匕数を手動で指定する機胜が倱われるこずです。

線集圌らが䞍思議な繰り返しパタヌンを解決したい理由をさらに瀺すために、圌らが参照し続けた最短経路問題を考えおみたしょう。 パラメヌタ化されたむンタヌフェむスを䜿甚するず、定矩は次のようになりたす。

type E(Node) interface {
  Nodes() []Node
}

type N(Edge) interface {
  Edges() (from, to Edge)
}

type Graph(type Node: N(Edge), Edge: E(Node)) struct { ... }
func New(type Node: N(Edge), Edge: E(Node))(nodes []Node) *Graph(Node, Edge) { ... }
func (*Graph(Node, Edge)) ShortestPath(from, to Node) []Edge { ... }

個人的には、関数のコントラクトを指定する方法が奜きです。 私は実際のコントラクト仕様ずしお「通垞の」関数本䜓を䜿甚するこずにあたり熱心ではありたせんが、コントラクトを自動単玔化するある皮のgofmtのような単玔化を導入するこずで、朜圚的な問題の倚くを解決できるず思いたす。無関係な郚品。 次に、関数本䜓をコピヌしお単玔化し、そこから倉曎するこずができたす。 残念ながら、これを実装するこずがどれほど可胜かはわかりたせん。

ただし、いく぀かのこずを指定するのはただ少し厄介であり、コントラクトずむンタヌフェヌスの間の明らかな重耇はただ少し奇劙に思えたす。

「CRTP」バヌゞョンは、はるかに明確で、より明確で、操䜜が簡単です䞀連の倉数に察する既存のコントラクト間の関係を定矩するためにのみ存圚するコントラクトを䜜成する必芁はありたせん。 確かに、それはアむデアに長幎粟通しおいるだけかもしれたせん。

明確化。 ドラフト蚭蚈により、機胜ずタむプの䞡方にコントラクトを適甚できたす。

"" "
むンタヌフェむスたたはコントラクトのみを䜿甚する必芁がある堎合は間違いなく簡単ですが、䞡方を䞀緒に䜿甚する必芁がある堎合はより耇雑になりたす。
"" "

コントラクト内で挔算子ず関数だけでなく、DRYを蚱可する1぀以䞊のむンタヌフェむスを参照できる限り、この問題および私の䞻匵は解決されたす。 契玄曞を読み間違えたり、完党に読んでいない可胜性がありたす。たた、䞊蚘の機胜がサポヌトされおいお、気づかなかった可胜性もありたす。 そうでない堎合は、そうする必芁がありたす。

次のこずができたせんか

contract Example(t T, v V) {
  t.(interface{
    SomeMethod() V
  })
}

コントラクトが宣蚀されおいるのず同じパッケヌゞから識別子を参照できないずいう制限があるため、他の堎所で宣蚀されおいるむンタヌフェむスを䜿甚するこずはできたせんが、これは可胜です。 たたは、その制限を取り陀くこずもできたす。 少し恣意的なようです。

@DeedleFakeいいえ、どのむンタヌフェむスタむプもタむプアサヌトできるためです実行時にパニックになる可胜性がありたすが、コントラクトは実行されたせん。 ただし、代わりに割り圓おを䜿甚できたす。

t.(someInterface)は、それがむンタヌフェヌスでなければならないこずも意味したす

いい芖点ね。 うわヌ。

私が芋るこの䟋が倚ければ倚いほど、「関数本䜓からそれを理解する」ずいう゚ラヌが発生しやすくなるようです。

人を混乱させる堎合、異なる操䜜の同じ構文、異なる構成からの含意の色合いなど、倚くの堎合がありたすが、ツヌルはそれを取埗しお通垞の圢匏に瞮小するこずができたす。 しかし、そのようなツヌルの出力は、私たちが暗蚘で孊ばなければならない型制玄を衚珟するための事実䞊のサブ蚀語になり、誰かが逞脱しお手で契玄を曞くずき、それはさらに驚くべきこずになりたす。

私も泚意したす

contract I(t T) {
  var i interface { Foo() }
  i = t
  t.(interface{})
}

Tは、少なくずもFoo()のむンタヌフェむスである必芁がありたすが、他の数の远加メ゜ッドを䜿甚するこずもできたす。

Tは、少なくずもFoo()のむンタヌフェヌスである必芁がありたすが、他の数の远加メ゜ッドを䜿甚するこずもできたす。

しかし、それは問題ですか 通垞、特定の機胜を蚱可するように制限したいのですが、他の機胜は気にしたせんか そうでなければ、のような契玄

contract Example(t T) {
  t + t
}

たずえば、枛算は蚱可されたせん。 しかし、私が実装しおいるものは䜕であれ、型が枛算を蚱可するかどうかは関係ありたせん。 枛算を実行できないように制限するず、たずえば、 Sum()関数などに䜕かを枡すこずができなくなりたす。 それは恣意的に制限されおいるようです。

いいえ、たったく問題ありたせん。 それは私にずっお盎感的ではない特性でしたが、おそらくそれは䞍十分なコヌヒヌが原因でした。

珟圚のコントラクト宣蚀には、より適切なコンパむラメッセヌゞが必芁であるず蚀っおも過蚀ではありたせん。 そしお、有効な契玄のルヌルは厳栌でなければなりたせん。

こんにちは
玄半幎前にこのスレッドに投皿したゞェネリックスの制玄に぀いお提案したした。
これでバヌゞョン2を䜜成したした。 䞻な倉曎点は次のずおりです。

  • 構文は、go-teamによっお提案されたものに適合されおいたす。
  • フィヌルドによる制玄は省略されおいるため、かなり単玔化できたす。
  • 厳密に必芁ではないず思われる段萜が削陀されたした。

私は最近、タむプIDに関する興味深いしかし、蚭蚈のこの段階では適切よりも詳现なのか質問を考えたした。

func Foo() interface{} {
    type S struct {}
    return S{}
}

func Bar(type T)() interface{} {
    type S struct {}
    return S{}
}

func Baz(type T)() interface{} {
    type S struct{t T}
    return S{}
}

func main() {
    fmt.Println(Foo() == Foo()) // 1
    fmt.Println(Bar(int)() == Bar(string)()) // 2
    fmt.Println(Baz(int)() == Baz(string)()) // 3
}
  1. 戻り倀の型は同じ型宣蚀に由来するため、 trueを出力したす。
  2. 版画 
  3. falseを出力するず思いたす。

぀たり、問題は、ゞェネリック関数で宣蚀された2぀の型が同䞀である堎合ず、そうでない堎合です。 これは〜spec〜デザむンで説明されおいるずは思いたせんか 少なくずも今は芋぀かりたせん:)

@merovius私は真ん䞭のケヌスが想定されおいたず思いたす

fmt.Println(Bar(int)() == Bar(int)()) // 2

これは興味深いケヌスであり、タむプが「生成的」であるか「適甚的」であるかによっお異なりたす。 実際には、さたざたなアプロヌチをずるMLのバリアントがありたす。 適甚型は、ゞェネリックを型関数ず芋なしたす。したがっお、fint== fintです。 ゞェネレヌティブタむプは、ゞェネリックを、䜿甚されるたびに新しい䞀意の「むンスタンス」タむプを䜜成するタむプテンプレヌトず芋なしたす。したがっお、t <int>= t <int>です。 これは、統䞀、掚論、および健党性に埮劙な圱響を䞎えるため、型システムレベル党䜓でアプロヌチする必芁がありたす。 その時の皮類の問題の詳现ず䟋に぀いおは、Andreas Rossbergの「F-ingmodules」ペヌパヌを読むこずをお勧めしたす https //people.mpi-sws.org/~rossberg/f-ing/このペヌパヌはMLに぀いお話しおいるが "ファンクタヌ」これは、MLが型システムを2぀のレベルに分割し、ファンクタヌはゞェネリックず同等のMLであり、モゞュヌルレベルでのみ䜿甚できるためです。

@keeanあなたは間違っおいるず思いたす。

@meroviusはい、私の間違いです。質問は、型パラメヌタヌが䜿甚されおいないためですファントム型。

生成型では、むンスタンス化ごずに「S」の䞀意の型が異なるため、パラメヌタヌが䜿甚されおいなくおも、それらは等しくありたせん。

適甚型の堎合、各むンスタンス化の「S」は同じ型になるため、等しくなりたす。

ケヌス2の結果がコンパむラの最適化に基づいお倉曎された堎合は奇劙になりたす。 UBのように聞こえたす。

2018幎の人ですが、1982幎のように実際に入力する必芁があるずは信じられたせん。

func minx、y intint {
x <y {の堎合
xを返す
}
yを返す
}

func maxx、y intint {
x> y {の堎合
xを返す
}
yを返す
}

぀たり、真剣に、MININT、INTINTの男、それはどのように蚀語ではないのですか
私は怒っおいるんだ。

@ dataf3lプレオヌダヌで期埅どおりに機胜させたい堎合は、次のようにしたす。

func min(x, y int) int {
   if x <= y {
      return x
   }
   return y
}

これにより、ペアminx、y、maxx、yは垞に区別され、x、yたたはy、xのいずれかになりたす。したがっお、これは2぀の芁玠の安定した゜ヌトです。

したがっお、これらが蚀語たたはラむブラリにあるべきである別の理由は、人々がそれらをほずんど間違えるずいうこずです:-)

<vs <=に぀いお考えたしたが、敎数の堎合、違いがよくわかりたせん。
倚分私はただ銬鹿です...

違いがよくわかりたせん。

この堎合はありたせん。

@cznicは敎数であるため、この堎合はtrueですが、スレッドはゞェネリックに関するものであるため、ラむブラリのコメントはminずmaxのゞェネリック定矩に関するものであり、ナヌザヌが自分で宣蚀する必芁はないず想定したした。 OPを読み盎すず、敎数の単玔な最小倀ず最倧倀が必芁であるこずがわかりたす。これは悪いこずですが、ゞェネリックスに関するスレッドで単玔な統合関数を芁求するトピックから倖れおいたした:-)

ゞェネリックスは、特に組み蟌みのデヌタ構造がないこずを考えるず、この蚀語ぞの重芁な远加です。 これたでのずころ、Goでの私の経隓は、Goが玠晎らしくお簡単に習埗できる蚀語であるずいうこずです。 ただし、これには倧きなトレヌドオフがありたす。぀たり、同じこずを䜕床も䜕床もコヌディングする必芁がありたす。

䜕かが足りないかもしれたせんが、これは蚀語のかなり倧きな欠陥のようです。 結論ずしお、組み蟌みのデヌタ構造はほずんどなく、デヌタ構造を䜜成するたびに、各Tをサポヌトするようにコヌドをコピヌしお貌り付ける必芁がありたす。

私の芳察結果を「ナヌザヌ」ずしおここに投皿する以倖に、どのように貢献するかわかりたせん。 私は蚭蚈や実装に貢献するのに十分な経隓を積んだプログラマヌではないので、ゞェネリックスは蚀語の生産性を倧幅に向䞊させるずしか蚀えたせんビルド時間ずツヌルが珟圚のように玠晎らしいたたである限り。

@webernありがずう。 https://go.googlesource.com/proposal/+/master/design/go2draft.mdを参照しおください。

@webernありがずう。 https://go.googlesource.com/proposal/+/master/design/go2draft.mdを参照しおください。

@ianlancetaylorは、投皿した埌、かなり過激でナニヌクなアむデアが頭に浮かびたした。蚀語ずツヌルに関する限り、「軜量」だず思いたす。 私はただあなたのリンクを完党に読んでいたせん、私はそうしたす。 しかし、MD圢匏のゞェネリックプログラミングのアむデア/提案を提出したい堎合、どうすればよいですか

ありがずう。

@webernそれを曞いおほずんどの人はマヌクダりン圢匏に芁点を䜿甚しおいたす、ここでwikiを曎新したすhttps://github.com/golang/go/wiki/Go2GenericsFeedback

他の倚くの人はすでにそうしおいたす。

私は最新のヒントに察しおマヌゞし、契玄ドラフト蚭蚈を実装するパヌサヌおよびプリンタヌのGophercon以前のプロトタむプ実装のCLをアップロヌドしたした。 構文の詊甚に興味がある堎合は、 https //golang.org/cl/149638をご芧ください。

それで遊ぶには

1最近のレポでCLをチェリヌピックしたす。
git fetch https://go.googlesource.com/go refs / Changes / 38/149638/2 && git Cherry-pick FETCH_HEAD

2コンパむラを再構築しおむンストヌルしたす。
cmd / compileをむンストヌルしたす

3コンパむラを䜿甚したす。
ツヌルコンパむルfoo.goに移動したす

詳现に぀いおは、CLの説明を参照しおください。 楜しみ

contract Addable(t T) {
    t + t
}

func Sum(type T Addable)(x []T) T {
    var total T
    for _, v := range x {
        total += v
    }
    return total
}

このゞェネリックデザむン、 func Sum(type T Addable)(x []T) Tは、非垞に非垞に醜いです!!!

func Sum(type T Addable)(x []T) Tず比范するず、 func Sum<T: Addable> (x []T) Tの方が明確であり、他のプログラミング蚀語を䜿甚しおいるプログラマヌに負担がかからないず思いたす。

構文がより冗長であるこずを意味したすか
func Sum(T Addable)(x []T) Tではない理由があるに違いありたせん。

typeキヌワヌドがないず、ゞェネリック関数ず、それ自䜓が呌び出されおいる別の関数を返す関数を区別する方法がありたせん。

@urandomこれはむンスタンス化時の問題であり、 typeキヌワヌドは必芁ありたせんが、あいたいなAIUIを䜿甚するだけです。

問題は、 typeキヌワヌドがないず、 func Foo(x T) (y T)は、 Tを取り、䜕も返さないゞェネリック関数を宣蚀するか、 Tを受け取る非ゞェネリック関数ずしお解析される可胜性があるこずです。 Tを返したす。

func Sumx [] TT

私は同意したす、私はこれらの線に沿った䜕かを奜みたす。 ゞェネリックスで衚される蚀語範囲の拡倧を考えるず、ゞェネリック関数に「泚意を喚起する」ためにこの構文を導入するこずは合理的だず思いたす。

たた、これにより、人間の読者がコヌドを解析しやすくなり読みLisp-yが少なくなりたす、さらに先のあいたいな解析のあいたいさにぶ぀かる可胜性が䜎くなるず思いたすC ++の「MostVexingParse」を参照。十分な泚意を促すために。

2018幎の人ですが、1982幎のように実際に入力する必芁があるずは信じられたせん。

func minx、y intint {
x <y {の堎合
xを返す
}
yを返す
}

func maxx、y intint {
x> y {の堎合
xを返す
}
yを返す
}

぀たり、真剣に、MININT、INTINTの男、それはどのように蚀語ではないのですか
私は怒っおいるんだ。

それには理由がありたす。
わからない堎合は、孊ぶか、立ち去るこずができたす。
あなたの遞択。

圌らがそれをより良くしおくれるこずを心から願っおいたす。
しかし、あなたの「孊ぶこずも離れるこずもできる」ずいう態床は、他の人が埓うべき良い䟋を提䟛しおいたせん。 それは䞍必芁に研磚性を読み取りたす。 私はそれがこのコミュニティが@ petar-dambovalievに぀いおのものであるずは思いたせん。 しかし、それは私の堎所ではありたせん。

ゞェネリック医薬品には匷い感情がたくさんあるこずは知っおいたすが、 Gopherの䟡倀芳を芚えおおいおください。 䌚話を尊重し、あらゆる面で歓迎しおください。

@bcmillsありがずうございたす、あなたはコミュニティをより良い堎所にしたす。

@katzdmは同意したした、蚀語にはすでに非垞に倚くの括匧がありたす、この新しいものは私には本圓に曖昧に芋えたす

generics定矩するず、$$ 1 type's type $のようなものが導入されるのは避けられないようです。これにより、 Goはかなり耇雑になりたす。

これがあたり話題から倖れおいないこずを願っおいたすが、 function overloadの機胜は私には十分に思えたす。

ずころで、私はオヌバヌロヌドに぀いおいく぀かの議論があったこずを知っおいたす。

@xgfone同意したす。蚀語にはすでに非垞に倚くの括匧があり、コヌドが䞍明確になっおいたす。
func Sum<T: Addable> (x []T) Tたたはfunc Sum<type T Addable> (x []T) Tの方が優れおおり、明確です。

䞀貫性を保぀ために組み蟌みのゞェネリックスを䜿甚、 func Sum[T: Addable] (x []T) Tはfunc Sum<T: Addable> (x []T) Tよりも優れおいたす。

私は他の蚀語での以前の仕事の圱響を受けおいるかもしれたせんが、 Sum<T: Addable> (x []T) Tは䞀芋、より明確で読みやすいように芋えたす。

たた、 @ katzdmは、蚀語の新しいこずに泚意を向けるのに優れおいるずいう点で同意したす。 たた、Goに飛び蟌むGo以倖の開発者にもよく知られおいたす。

FWIW、Goがゞェネリックに山かっこを䜿甚する可胜性は玄0です。 C ++の文法は、a、b、およびcのタむプを理解せずに、䞀般的な呌び出しからa <b> c合法であるが無意味な䞀連の比范を区別できないため、解析できたせん。 他の蚀語では、この理由からゞェネリックに山括匧を䜿甚するこずを避けおいたす。

func a < b Addable> (...
funcの埌には、関数名、 ( 、たたは<のいずれかしか持おないこずに気付いた堎合は可胜だず思いたす。

@carlmjohnsonあなたが正しいこずを願っおいたす

f := sum<int>(10)

しかし、ここであなたはsumが契玄であるこずを知っおいたす。

C ++の文法は、a、b、およびcのタむプを理解せずに、䞀般的な呌び出しからa <b> c合法であるが無意味な䞀連の比范を区別できないため、解析できたせん。

GoはC ++ずは異なり、型システムではこれを蚱可しおいたせんが、 <および>挔算子はGoおよび<でbool返すため、指摘する䟡倀があるず思いたす。 <ず>はboolで䜿甚できたせん。構文的には合法であるため、これは䟝然ずしお問題です。

山かっこに関するもう1぀の問題は、 List<List<int>>です。この堎合、 >>は右シフト挔算子ずしおトヌクン化されたす。

[]の䜿甚に関する問題は䜕でしたか 䞊蚘のほずんどは、それらを䜿甚するこずで解決されるように思われたす。

  • 構文的には、䞊蚘の䟋を䜿甚するf := sum[int](10)は、配列たたはマップアクセスず同じ構文を持っおいるため、明確です。その埌、型システムは、すでに行っおいるのず同じように、埌でそれを理解できたす。たずえば、配列アクセスずマップアクセスの違い。 これは<>の堎合ずは異なりたす。これは、単䞀の<が合法であり、あいたいさをもたらすためですが、単䞀の[ $は合法ではありたせん。
  • func Example[T](v T) Tも明確です。
  • ]]はそれ自䜓のトヌクンではないため、問題も回避されたす。

蚭蚈ドラフトでは、 type A [T] intなどの型宣蚀のあいたいさに぀いお蚀及しおいたすが、これはいく぀かの異なる方法で比范的簡単に解決できるず思いたす。 たずえば、䞀般的な定矩は、タむプ名ではなく、キヌワヌド自䜓に移動できたす。

  • func[T] Example(v T) T
  • type[T] A int

ここでの耇雑さは、次のような型宣蚀ブロックの䜿甚に起因する可胜性がありたす。

type (
  A int
)

しかし、これは非垞にたれであるため、ゞェネリックが必芁な堎合はそれらのブロックの1぀を䜿甚できないず基本的に蚀うのは問題ないず思いたす。

曞くのはずおも䞍幞だず思いたす

type[T] A []T
var s A[int]

角かっこはAの䞀方の偎からもう䞀方の偎に移動するためです。 もちろんそれは可胜ですが、私たちはより良いものを目指すべきです。

ずはいえ、珟圚の構文でtypeキヌワヌドを䜿甚するこずは、括匧を角かっこで眮き換えるこずができるこずを意味したす。

これは、配列タむプず匏の構文が[N]Tずarr[i]であるのず、䜕かがどのように䜿甚されおいるかず䞀臎しないず宣蚀されるずいう点で、それほど違いはないようです。 はい、 var arr [N]Tでは、角かっこはarr arrを䜿甚する堎合ず同じ偎になりたすが、通垞、構文は型ず匏の構文の芳点から考えたす。反察です。

( vs < vs [に぀いお話し合っおいるのか、 typeの䜿甚がバむクシェディングなのか、構文に本圓に問題があるのか​​はわかりたせん。

@ianlancetaylor ...フィヌドバックが提案されたデザむンの埮調敎を正圓化するかどうか疑問に思いたしたか 私自身のフィヌドバックの感芚は、少なくずも最初は、むンタヌフェヌスずコントラクトを組み合わせるこずができるず倚くの人が感じおいたずいうこずでした。 しばらくするず、2぀の抂念を分離しおおく必芁があるずいう倉化のように芋えたした。 しかし、私はトレンドを間違っお読んでいる可胜性がありたす。 今幎のリリヌスで実隓的なオプションを芋たいです

はい、私たちは、人々が行った倚くの反察提案を怜蚎するこずを含め、ドラフト蚭蚈の倉曎を怜蚎しおいたす。 䜕も確定しおいたせん。

いく぀かの実践的な経隓レポヌトを远加するための突き出し
Goむンタヌプリタヌhttps://github.com/cosmos72/gomacroに蚀語拡匵機胜ずしおゞェネリックスを実装したした。 興味深いこずに、䞡方の構文

type[T] Pair struct { First T; Second T }
type Pair[T] struct { First T; Second T }

パヌサヌに倚くのあいたいさを導入するこずが刀明したした。2番目は、PairがT構造䜓の配列であるずいう宣蚀ずしお解析できたす。ここで、Tは定数敎数です。 Pairを䜿甚するず、あいたいさもありたす。 Pair[int]は、型ではなく匏ずしお解析するこずもできたす。 Pairずいう名前の配列/スラむス/マップにむンデックスを付けるこずができたす。むンデックス匏int 泚 intおよびその他の基本型はGoで予玄されたキヌワヌドではありたせん、したがっお、新しい構文に頌らなければなりたせんでした-確かに醜いですが、仕事はしたす

template[T] type Pair struct { First T; Second T }
type pairOfInt = Pair#[int]
var p Pair#[int]

関数に぀いおも同様です。

template[T] func Sum(args ...T) T { /*...*/ }
Sum#[int] (1,2,3)

したがっお、理論的には構文が衚面的な問題であるこずに同意したすが、次のこずを指摘する必芁がありたす。
1䞀方の偎から芋るず、構文はGoプログラマヌがさらされるものです。したがっお、衚珟力があり、シンプルで、おそらく口に合うものでなければなりたせん。
2反察偎から芋るず、構文の遞択が間違っおいるず、導入されたあいたいさを解決するために、パヌサヌ、タむプチェッカヌ、およびコンパむラヌが耇雑になりたす。

Pair[int]は、型ではなく匏ずしお解析するこずもできたす。 Pairずいう名前の配列/スラむス/マップにむンデックス匏intでむンデックスを付けるこずができたす。

これは構文解析のあいたいさではなく、意味的なものです名前解決埌たで。 構文構造はどちらの方法でも同じです。 Sum#[int]は、 Sumが䜕であるかに応じお、型たたは匏のいずれかになり埗るこずに泚意しおください。 同じこずが既存のコヌドの(*T)にも圓おはたりたす。 名前の解決が解析察象の構造に圱響を䞎えない限り、問題はありたせん。

これを<>の問題ず比范しおください

f ( a < b , c < d >> (e) )

>>は1぀たたは2぀のトヌクンである可胜性があるため、これをトヌクン化するこずもできたせん。 次に、 fに1぀たたは2぀の匕数があるかどうかを刀断できたせん...匏の構造は、 aで瀺されるものに応じお倧幅に倉化したす。

ずにかく、ゞェネリックスに぀いおのチヌムの珟圚の考え方、特に「制玄はただのコヌド」が繰り返されおいるのか、攟棄されおいるのかを知りたいず思いたす。 明確な制玄蚀語を定矩するこずを避けたいこずは理解できたすが、関係する型を十分に制玄するコヌドを曞くず䞍自然なスタむルが匷制され、コンパむラがコヌドに基づいお型に぀いお実際に掚論できるものにも限界を蚭ける必芁がありたすそうしないず、これらの掚論が任意に耇雑になる可胜性があるため、たたは将来倉曎される可胜性のある蚀語に関する事実に䟝存する可胜性があるためです。

@ cosmos72

たぶん私は間違っおいたすが、 @ stevenblenkinsopによっお蚀われたこずのほかに、その甚語はすべお可胜ですか

a b

たた、オプションの[identifier]が远加された英数字挔算子なし/区切り文字なしであり、aが特別なキヌワヌド/特別な英数字ではないたずえば、むンポヌトなし/堎合、bはタむプではないこずを意味する堎合もありたす。 package / type / func?.

行き過ぎの文法がわからない。

ある意味で、intやSum [int]のような型は、ずにかく匏ずしお扱われたす。

type (
    nodeList = []*Node  // nodeList and []*Node are identical types
    Polar    = polar    // Polar and polar denote identical types
)

goが䞭眮関数を蚱可する堎合、 typeは䞭眮関数たたは型である可胜性があるため、実際にa type tagはあいたいになりたす。

私は今日、この提案の問題の抂芁がスむフトを䞻匵しおいるこずに気づきたした。

TがEquatableプロトコルを満たすこずを宣蚀するず、関数本䜓での==の䜿甚が有効になりたす。 EquatableはSwiftに組み蟌たれおいるようですが、それ以倖の方法で定矩するこずはできたせん。

これは、このトピックに関する決定に深く圱響を䞎えるものずいうよりは脇にあるように芋えたすが、偶然にも、私がむンスピレヌションを埗るよりもはるかに賢く人々に䞎えるこずができたす。実際には特別なものは䜕もないこずを指摘したいず思いたす。蚀語で事前定矩されおいる以倖は玄Equatable 䞻に、他の倚くの組み蟌み型がそれに「準拠」できるようにするため。 同様のプロトコルを䜜成するこずは完党に可胜です。

protocol Equatable2 {
    static func == (lhs: Self, rhs: Self) -> Bool
}

class uniq: Equatable2 {
    static func == (lhs: uniq, rhs: uniq) -> Bool {
        return false
    }
}

let narf = uniq(), poit = uniq()

func !=<T: Equatable2> (lhs: T, rhs: T) -> Bool {
    return !(lhs == rhs)
}

print(narf != poit)

@sighoya
ゞェネリックスに提案された構文a[b]のあいたいさに぀いお話しおいたした。これは、スラむスずマップのむンデックス䜜成にすでに䜿甚されおいるためです。 a bに぀いおではありたせん。

その間、私はHaskellを研究しおいお、型掚論が広く䜿われおいるこずを事前に知っおいたしたが、そのゞェネリックスの衚珟力ず掗緎さには驚かされたした。

残念ながら、それは非垞に独特な呜名スキヌムを持っおいるので、䞀芋しお理解するのは必ずしも簡単ではありたせん。 たずえば、 classは、実際には型䞀般的かどうかの制玄です。 Eqクラスは、倀を「==」および「/ =」ず比范できる型の制玄です。

class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool

䞭眮関数==ず/=の「特殊化」実際にはHaskell甚語では「むンスタンス」が存圚する堎合、タむプaが制玄Eq $を満たすこずを意味したす。 /=は、それぞれタむプがaの2぀の匕数を受け入れ、 Boolの結果を返したす。

私は珟圚、Haskellゞェネリックに芋られるアむデアのいく぀かをGoゞェネリックの提案に適合させ、それらがどれほどうたく適合するかを確認しようずしおいたす。 C ++やJava以倖の他の蚀語でも調査が行われおいるのを芋お本圓にうれしいです。

䞊蚘のSwiftの䟋ず私のHaskellの䟋は、ゞェネリック型の制玄がすでにいく぀かのプログラミング蚀語で実際に䜿甚されおいるこず、およびゞェネリックず制玄ぞのさたざたなアプロヌチに関する自明ではない量の経隓が存圚し、これらのプログラマヌの間で利甚できるこずを瀺しおいたすおよび他の蚀語。

私の意芋では、Goゞェネリックの提案を完成させる前に、そのような経隓を研究するこずは確かに䟡倀がありたす。

迷いたしたゞェネリック型が満たす制玄の圢匏がむンタヌフェむス定矩ずほが䞀臎する堎合は、すでに慣れおいる既存の型アサヌション構文を䜿甚できたす。

type Comparer interface {
  Compare(v interface{}) (*int, error)
}
type PriorityQueue<T.(Comparer)> struct {
  things []T
}

これがすでに他の堎所で培底的に議論されおいる堎合はお詫びしたす。 私はそれを芋たこずがありたせんが、私はただ文孊に巻き蟌たれおいたす。 Goのどのバヌゞョンにもゞェネリックスが必芁ないので、私は少しの間それを無芖しおきたした。 しかし、このアむデアは、コミュニティ党䜓で勢いを増し、必然性を感じおいるようです。

@ jesse-amanoGoのどのバヌゞョンでもゞェネリックスが必芁ないのは興味深いこずです。 プログラマヌずしお私は自分自身を繰り返すのが本圓に奜きではないので、これを理解するのは難しいず思いたす。 'C'でプログラムするずきはい぀でも、新しいデヌタ型にリストやツリヌなどの同じ基本的なものを実装する必芁があり、必然的に私の実装にはバグがたくさんありたす。 ゞェネリックスを䜿甚するず、アルゎリズムのバヌゞョンを1぀だけ持぀こずができ、コミュニティ党䜓がその1぀のバヌゞョンを最高のものにするこずに貢献できたす。 繰り返さないためのあなたの解決策は䜕ですか

もう1぀の点に぀いおは、むンタヌフェむスで挔算子のオヌバヌロヌド '=='や '+'などが蚱可されおいないため、Goはゞェネリック制玄の新しい構文を導入しおいるようです。 これには2぀の方法がありたす。ゞェネリック制玄の新しいメカニズムを定矩する方法です。これは、Goが行っおいるように芋える方法です。たたは、むンタヌフェむスが挔算子をオヌバヌロヌドできるようにする方法です。これは、私が奜む方法です。

2番目のオプションは、蚀語構文をより小さく単玔に保ち、通垞の挔算子を䜿甚できる新しい数倀型たずえば、「+」で远加できる耇玠数を宣蚀できるため、2番目のオプションを奜みたす。 これに反察する議論は、人々が挔算子のオヌバヌロヌドを悪甚しお '+'に奇劙なこずをさせるかもしれないずいうこずのようですが、私はすでに任意の関数名を悪甚できるので、これは私には議論の䜙地がないようです。 'ハヌドドラむブ䞊のすべおのデヌタを消去し、プログラムを終了したす。 挔算子ず関数の䞡方の過負荷を、可換性や結合性などの特定の公理的特性に準拠するように制限する機胜が欲しいのですが、それが挔算子ず関数の䞡方に圓おはたらない堎合は、あたり意味がありたせん。 挔算子は単なる䞭眮関数であり、関数は結局のずころ単なる接頭蟞挔算子です。

もう1぀の泚意点は、耇数の型パラメヌタヌを参照するゞェネリック制玄は非垞に䟿利です。単䞀パラメヌタヌのゞェネリック制玄が型の述語である堎合、耇数パラメヌタヌの制玄は型の関係です。 Goむンタヌフェヌスは耇数の型パラメヌタヌを持぀こずができないため、新しい構文を導入するか、むンタヌフェヌスを再蚭蚈する必芁がありたす。

ですから、私があなたに同意する方法で、Goはゞェネリック蚀語ずしお蚭蚈されおおらず、ゞェネリックを远加しようずする詊みは最適ではありたせん。 ゞェネリックスなしでGoを維持し、ゞェネリックスを䞭心に新しい蚀語をれロから蚭蚈しお、単玔な構文で蚀語を小さく保぀方がよいかもしれたせん。

@keean必芁なずきに䜕床か繰り返すこずに匷い嫌悪感はありたせん。゚ラヌ凊理、メ゜ッドレシヌバヌなどに察するGoのアプロヌチは、通垞、ほずんどのバグを寄せ付けないようにするのに適しおいるようです。

過去4幎間のいく぀かのケヌスで、耇雑で䞀般化可胜なアルゎリズムを2぀以䞊の耇雑で䞀貫性のあるデヌタ構造に適甚する必芁がある状況に遭遇したした。すべおの堎合、これを次のように蚀いたす。すべおの深刻さ-gogenerateによるコヌド生成で十分であるこずがわかりたした。

経隓レポヌトを読んでいるず、倚くの堎合、gogenerateたたは同様のツヌルで問題を解決できたず思いたす。たた、Go1が適切な蚀語ではなかったように感じたり、他の䜕かが問題を解決した可胜性もありたす。代わりに䜿甚されたすGoコヌドで䜿甚する必芁がある堎合はプラグむンラッパヌを䜿甚する可胜性がありたす。 しかし、私は自分が䜕をしたのか、䜕をしたのか、どれがうたくいったのかを掚枬するのは簡単だず知っおいたす。 これたでのずころ、Go1にゞェネリック型を衚珟する方法がもっずあるこずを願うような実践的な経隓はありたせんでしたが、物事に぀いお奇劙な考え方をしおいる可胜性がありたす。ゞェネリックを本圓に必芁ずしないプロゞェクトで。

Go2が䞀般的な構文をサポヌトするこずになった堎合、ボクシング/アンボクシング、「具䜓化」、継承チェヌンなどから発生する可胜性のある奇劙な゚ッゞケヌスがなく、生成されるロゞックぞのマッピングがかなり簡単になるこずを期埅しおいたす。他の蚀語が心配しなければならないこず。

@ jesse-amano私の経隓では、数回だけではなく、すべおのプログラムはよく知られたアルゎリズムの組み合わせです。 前回オリゞナルのアルゎリズムを曞いたずきのこずを思い出せたせん。おそらく、ドメむン知識を必芁ずする耇雑な最適化問題です。

プログラムを䜜成するずき、私が最初に行うこずは、問題を、䜜成できるよく知られたチャンク、匕数パヌサヌ、ファむルストリヌミング、制玄ベヌスのUIレむアりトに分解するこずです。 人々が間違える耇雑なアルゎリズムだけでなく、「min」ず「max」の正しい実装を初めお曞くこずはほずんどできたせんhttp://componentsprogramming.com/writing-min-function-part5/を参照。

gogenerateの問題は、基本的には単なるマクロプロセッサであり、型の安党性がないこずです。生成されたコヌドの型チェックず゚ラヌチェックを行う必芁がありたす。これは、生成を実行するたで実行できたせん。 この皮のメタプログラミングは、デバッグが非垞に困難です。 私はプログラムを曞くためにプログラムを曞きたくありたせん、私はただプログラムを曞きたいです:-)

したがっお、ゞェネリックスずの違いは、コヌドを生成せずに、意味を理解するこずで゚ラヌチェックずタむプチェックが可胜な単玔な_direct_プログラムを蚘述し、それをデバッグしおバグをゞェネレヌタヌに戻すこずができるこずです。

本圓に簡単な䟋は「スワップ」です。2぀の倀をスワップしたいのですが、それらが䜕であるかは関係ありたせん。

swap<A>(x: *A, y: *A) {
   let tmp = *x
   *x = *y
   *y = tmp
}

この関数が正しいかどうかを確認するのは簡単だず思いたす。たた、この関数が䞀般的であり、どのタむプにも適甚できるこずを確認するのは簡単です。 スワップを䜿甚する可胜性のある倀ぞのすべおのタむプのポむンタヌに察しお、なぜこの関数を䜕床も入力したいのでしょうか。 もちろん、むンプレヌス゜ヌトのように、これからより倧きな汎甚アルゎリズムを構築できたす。 単玔なアルゎリズムであっおも、gogenerateコヌドが正しいかどうかを確認するのは簡単ではないず思いたす。

私は簡単に次のような間違いを犯す可胜性がありたす

let tmp = *x
*y = *x
*x = tmp

2぀のポむンタヌの内容を亀換するたびに、これを手で入力したす。

Goでこの皮のこずを行う慣甚的な方法は、空のむンタヌフェむスを䜿甚するこずであるこずを理解しおいたすが、これはタむプセヌフではなく、䜎速です。 ただし、Goには、この皮のゞェネリックプログラミングを゚レガントにサポヌトするための適切な機胜がなく、空のむンタヌフェむスは問題を回避するための゚スケヌプハッチを提䟛しおいるように思われたす。 goのスタむルを完党に倉えるよりも、この皮のゞェネリックに適した蚀語を最初から開発する方がよいようです。 興味深いこずに、「Rust」は倚くの䞀般的なものを正しく取埗したすが、ガベヌゞコレクションではなく静的メモリ管理を䜿甚するため、ほずんどのプログラミングには実際には必芁ない非垞に倚くの耇雑さが远加されたす。 Haskell、Go、Rustの間には、たずもな䞻流のゞェネリック蚀語を䜜るために必芁なすべおの芁玠があり、すべおが混同されおいるず思いたす。

情報私は珟圚、Goゞェネリックに関するりィッシュリストを曞いおいたす。

GoゞェネリックC ++テンプレヌトをモデルにしたものの異なる実装をすでに持っおいる私のGoむンタヌプリタヌgomacroに実際に実装するこずを意図しおいたす。

ただ完了しおいたせん。フィヌドバックは倧歓迎です:)

@keean

min関数に぀いおリンクしたブログ投皿ずそれに至るたでの4぀の投皿を読みたした。 「 'min'の正しい実装を曞くこずができる人はほずんどいない」ずいう議論をしようずしおも、私は芳察したせんでした。 ドメむンが数倀に制限されおいる限り、ラむタヌは実際に最初の実装が正しいこずを認めおいるようです。 これは、オブゞェクトずクラスの導入であり、1぀のディメンションの倀が同じでない限り、それらを1぀のディメンションのみに沿っお比范する必芁がありたす。ただし、次の堎合などを陀き、耇雑さが増したす。 耇雑なオブゞェクトでコンパレヌタヌず゜ヌト関数を泚意深く定矩する必芁があるこずに䌎う埮劙な隠れた芁件が、私がゞェネリックスを抂念ずしお_奜きではない_理由です少なくずもGoでは; Springを䜿甚したJavaは、すでに䜜成するのに十分な環境のようです成熟したラむブラリの束を䞀緒にアプリケヌションに。

私は個人的に、マクロゞェネレヌタヌの型安党性の必芁性を感じおいたせん。 読みやすいコヌドを生成しおいる堎合 gofmtは、これをかなり䜎く蚭定するのに圹立ちたす、コンパむル時の゚ラヌチェックで十分です。 ずにかく、ゞェネレヌタヌたたはゞェネレヌタヌを呌び出すコヌドのナヌザヌにずっお、本番環境は重芁ではありたせん。 確かに短い時間で、䞀般的なアルゎリズムをマクロずしお䜜成するように求められたした。いく぀かのナニットテスト通垞はfloat、string、およびpointer-to-struct —ハヌドコヌドされたタむプがある堎合ハヌドコヌディングしないでください。これら3぀のうちの1぀は互換性がありたせん。これらの3぀のうちのいずれかが汎甚アルゎリズムで䜿甚できない堎合、それは汎甚アルゎリズムではありたせん、マクロが適切に機胜するこずを保蚌するのに十分でした。

swapは悪い䟋です。 申し蚳ありたせんが、そうです。 これはすでにGoのワンラむナヌであり、ゞェネリック関数でラップする必芁はなく、プログラマヌが自明でない゚ラヌを犯す䜙地もありたせん。

*y, *x = *x, *y

たた、暙準ラむブラリにはすでにむンプレヌスsortがありたす。 むンタヌフェむスを䜿甚したす。 タむプに固有のバヌゞョンを䜜成するには、以䞋を定矩したす。

type myslice []mytype
func (s myslice) Len() int { return len(s) }
func (s myslice) Less(i, j int) bool { return s[i].whatWouldAlsoBeNeededInAGenericImpl(s[j]) }
func (s myslice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

確かに、入力するバむト数はSortableList<mytype>(myThings).Sort()よりも数バむト倚くなりたすが、読み取り密床が_lot_䜎く、アプリケヌションの残りの郚分党䜓で「途切れ」する可胜性は䜎く、バグが発生した堎合はほずんどありたせん。原因を芋぀けるためにスタックトレヌスず同じくらい重いものが必芁です。 珟圚のアプロヌチにはいく぀かの利点があり、ゞェネリックスに頌りすぎるずそれらが倱われるのではないかず心配しおいたす。

@ jesse-amano
'min / max'の問題は、安定゜ヌトの必芁性を理解しおいない堎合でも圓おはたりたす。 たずえば、ある開発者が1぀のモゞュヌルで特定のデヌタ型の最小/最倧を実装するず、仮定を適切にチェックせずに別のチヌムメンバヌによっお゜ヌトたたは他のアルゎリズムで䜿甚され、安定しおいないために奇劙なバグが発生したす。

プログラミングは䞻に暙準アルゎリズムを構成しおいるず思いたす。プログラマヌが新しい革新的なアルゎリズムを䜜成するこずはめったにないので、最小/最倧ず䞊べ替えは単なる䟋です。 私が遞んだ特定の䟋で穎を遞ぶこずは、私があたり良い䟋を遞ばなかったこずを瀺しおいるだけであり、それは実際のポむントに察凊しおいたせん。 「スワップ」を遞択したのは、非垞にシンプルで、すばやく入力できるからです。 非垞に䞀般的なアルゎリズムである、他の倚くの゜ヌト、ロヌテヌション、パヌティションを遞択するこずもできたす。 赀黒朚などのコレクションを䜿甚するプログラムを䜜成しおいるずきに、タむプの安党性が必芁なため、コレクションが必芁なさたざたなデヌタ型ごずにツリヌをやり盎す必芁があるこずにうんざりするのにそれほど時間はかかりたせん。空のむンタヌフェむスは、「C」の「void *」よりも少し優れおいたす。 次に、プレオヌダヌ、むンオヌダヌ、ポストオヌダヌの反埩、怜玢など、これらのツリヌのそれぞれを䜿甚するすべおのアルゎリズムに察しお同じこずを再床行う必芁がありたす。これは、Tarjanのネットワヌクアルゎリズム分離などの高床なものに取り掛かる前です。セット、ヒヌプ、最小党域朚、最短経路、フロヌなど

たずえば、json-schemaからバリデヌタヌを生成したり、文法定矩からパヌサヌを生成したりするなど、コヌドゞェネレヌタヌがその圹割を果たしおいるず思いたすが、ゞェネリックスの適切な代替にはならないず思いたす。 ゞェネリックプログラミングの堎合、私は任意のアルゎリズムを䞀床蚘述できるようにし、それを明確、単玔、か぀盎接的にしたいず思っおいたす。

いずれにせよ、「Go」に぀いおは同意したすが、「Go」は最初から優れたゞェネリック蚀語ずしお蚭蚈されたずは思いたせん。ゞェネリックを远加しおも、おそらく優れたゞェネリック蚀語にはならないでしょう。すでに持っおいる盎接性ず単玔さの䞀郚を倱うこずになりたす。 個人的には、コヌドゞェネレヌタヌjson-schemaからのバリデヌタヌや文法ファむルからのパヌサヌの生成などに手を䌞ばす必芁がある堎合は、ずにかく間違った蚀語を䜿甚しおいる可胜性がありたす。

線集「float」、「string」、「pointer-to-struct」を䜿甚したゞェネリックのテストに関しおは、「スワップ」を陀いお、その倚様な型のセットで機胜するゞェネリックアルゎリズムは倚くないず思いたす。 真の「ゞェネリック」関数は実際にはシャッフルに限定されおおり、あたり頻繁には発生したせん。 制玄付きゞェネリックははるかに興味深いものであり、ゞェネリック型はいく぀かのむンタヌフェヌスによっお制玄されたす。 ご芧のずおり、暙準ラむブラリのむンプレヌス゜ヌトの䟋を䜿甚するず、限られた堎合に「Go」でいく぀かの制玄付きゞェネリックを機胜させるこずができたす。 私はGoむンタヌフェヌスの仕組みが奜きで、あなたはそれらを䜿っおたくさんのこずができたす。 私は真の制玄付きゞェネリックがさらに奜きです。 珟圚のゞェネリックスの提案のように、2番目の制玄メカニズムを远加するのは本圓に奜きではありたせん。 むンタヌフェむスが型を盎接制玄する蚀語は、はるかに掗緎されおいたす。

私の知る限り、新しい制玄が導入された唯䞀の理由は、Goでは挔算子をむンタヌフェむスで定矩できないためです。 以前のゞェネリックスの提案では、型をむンタヌフェむスで制玄するこずができたしたが、「+」などの挔算子に察応しおいなかったため、攟棄されたした。

@keean
おそらく、長匕く議論のためのより良い堎所がありたす。 おそらくそうではありたせん。私は呚りを芋回したしたが、これはGo2のゞェネリックスに぀いお議論する堎所のようです。

安定゜ヌトの必芁性は確かに理解しおいたす sort.Stableが公開されおからそこにあるので、元のGo1暙準ラむブラリの䜜成者もそれを理解しおいるず思いたす。

暙準ラむブラリのsortパッケヌゞの玠晎らしいずころは、スラむスに察しおのみ機胜しないこずです。 レシヌバヌがスラむスの堎合は確かに最も単玔ですが、実際に必芁なのは、コンテナヌ内の倀の数 Len() intメ゜ッドずそれらの比范方法 Less(int, int) bool を知る方法だけです。 Swap(int, int)メ゜ッド。 チャネルを䜿甚しおsort.Interfaceを実装できたす もちろん、チャネルは効率的なむンデックス䜜成甚に蚭蚈されおいないため、䜎速ですが、実行時間の予算が十分にある堎合は、正しいこずが蚌明できたす。

私は぀たむ぀もりはありたせんが、悪い䟋の問題はそれです...それは悪いです。 sortやminのようなものは、ゞェネリックスのような圱響力の倧きい蚀語機胜を支持する点ではありたせん。 これらの䟋の穎を突くず、実際のポむントに察凊しおいるず匷く感じたす。 _my_ポむントは、蚀語に優れた゜リュヌションがすでに存圚する堎合、ゞェネリックは必芁ないずいうこずです。

@ jesse-amano

より良い解決策はすでに蚀語に存圚したす

どれ タむプセヌフな制玄付きゞェネリックよりも優れたものは芋圓たりたせん。 ゞェネレヌタヌはGoではなく、単玔で単玔です。 むンタヌフェむスずリフレクションは、安党ではなく、遅く、パニックになりやすいコヌドを生成したす。 他に䜕もないので、これらの゜リュヌションは十分に優れおいたす。 ゞェネリックスは、ボむラヌプレヌト、安党でない空のむンタヌフェむス構造の問題を解決し、最悪の堎合、実行時のパニックをさらに起こしやすいリフレクションの倚くの䜿甚を排陀したす。 新しい゚ラヌパッケヌゞの提案でさえ、ゞェネリックスの欠劂に悩たされおおり、そのAPIはそれらから倧きな恩恵を受けるでしょう。 䟋ずしおAsを芋るこずができたす-慣甚的ではなく、パニックになりやすく、䜿いにくく、正しく䜿甚するには獣医のチェックが必芁です。 Goにはゞェネリックがないからです。

sort 、 min 、およびその他のゞェネリックアルゎリズムは、ゞェネリックの䞻な利点である構成可胜性を瀺しおいるため、優れた䟋です。 それらは、䞀緒にチェヌンできる䞀般的な倉換ルヌチンの広範なラむブラリを構築するこずを可胜にしたす。 そしお最も重芁なこずは、䜿いやすく、安党で、高速であり少なくずもゞェネリックスで可胜です、他に方法がないずいう理由だけで䜿甚される定型文、ゞェネレヌタヌ、むンタヌフェむス{}、リフレクション、その他のあいたいな蚀語機胜は必芁ありたせん。

@creker

どれ

ものを゜ヌトするために、パッケヌゞsort 。 sort.Interfaceを実装するものはすべお䞊べ替えるこずができたす遞択した安定たたは䞍安定なアルゎリズムを䜿甚したす。䞀郚のむンプレヌスバヌゞョンはsortパッケヌゞを介しお提䟛されたすが、類䌌たたは異なるAPI。 暙準ラむブラリsort.Sortずsort.Stableはどちらも匕数リストを介しお枡された倀で動䜜するため、返される倀は最初に取埗した倀ず同じです。したがっお、必然的にタむプ返されるのは、最初に䜿甚したタむプず同じです。 これは完党にタむプセヌフであり、コンパむラヌは、タむプが必芁なむンタヌフェヌスを実装しおいるかどうかを掚枬するすべおの䜜業を行い、ゞェネリックススタむルのsort<T>関数で可胜な限り倚くのコンパむル時の最適化が可胜です。 。

ものを亀換するために、ワンラむナヌx, y = y, x 。 繰り返したすが、タむプアサヌション、むンタヌフェむスキャスト、たたはリフレクションは必芁ありたせん。 2぀の倀を亀換するだけです。 コンパむラヌは、操䜜がタむプセヌフであるこずを簡単に確認できたす。

すべおの堎合においおゞェネリックよりも優れた゜リュヌションであるず私が考える特定のツヌルは1぀ではありたせんが、ゞェネリックが解決するはずの特定の問題に぀いおは、より優れた゜リュヌションがあるず思いたす。 私はここで間違っおいるかもしれたせん。 私は、既存のすべおの゜リュヌションがひどいものであった堎合にゞェネリックスが実行できるこずの䟋をただ芋おいたす。 しかし、私がそれに穎を開けるこずができれば、それはそれらの䟋の1぀ではありたせん。

xerrorsパッケヌゞもあたり奜きではありたせんが、 xerrors.Asは非慣甚的であるずは思われたせん。 結局のずころ、これjson.Unmarshalず非垞によく䌌たAPIです。 より良いドキュメントやサンプルコヌドが必芁な堎合もありたすが、それ以倖の堎合は問題ありたせん。

しかし、いいえ、 sortずminは、それ自䜓、かなりひどい䟋です。 前者はすでにGoに存圚し、完党に構成可胜であり、すべおゞェネリックを必芁ずしたせん。 埌者は、最も広い意味でsort すでに解決枈みの出力の1぀であり、より専門的たたは最適化された゜リュヌションが必芁になる可胜性がある堎合は、ずにかく専門的な゜リュヌションを䜜成したす。ゞェネリック。 繰り返しになりたすが、暙準ラむブラリのsortパッケヌゞで䜿甚されるゞェネレヌタ、むンタヌフェむス{}、リフレクション、たたは「あいたいな」蚀語機胜はありたせん。 空でないむンタヌフェヌスがありたすAPIで明確に定矩されおいるため、誀っお䜿甚するずコンパむル時゚ラヌが発生し、キャストが䞍芁であるず掚枬され、コンパむル時にチェックされるため、必芁ありたせん。アサヌション。 ゜ヌトしおいるコレクションがスラむスである堎合、定型的なものがあるかもしれたせんが、それが構造䜓バむナリ怜玢ツリヌのルヌトノヌドを衚すものなどである堎合は、 sort.Interfaceを満たすようにするこずができたす。

@ jesse-amano

私のポむントは、蚀語にもっず良い解決策がすでに存圚する堎合、ゞェネリックは必芁ないずいうこずです

私は芪切に、より良い解決策は実際にはあなたがそれをどのように芋るかに基づいおいるず思いたす。 より良い蚀語があれば、より良い解決策が埗られる可胜性がありたす。そのため、この蚀語をより良くしたいず考えおいたす。 たずえば、より優れたゞェネリックが存圚する堎合、stdlibにsortを含めるこずができたす。少なくずも、䞊べ替えむンタヌフェむスを実装する珟圚の方法は、私にずっお優れたナヌザヌ゚クスペリ゚ンスではありたせん。それでも、同様のコヌドをたくさん入力する必芁がありたす。それを抜象化できるず匷く感じおいたす。

@ jesse-amano

暙準ラむブラリの゜ヌトパッケヌゞの玠晎らしいずころは、スラむスだけで機胜しないこずだず思いたす。

私は同意したす、私は暙準的な皮類が奜きです。

前者はすでにGoに存圚し、完党に構成可胜であり、すべおゞェネリックを必芁ずしたせん。

これは誀った二分法です。 Goのむンタヌフェヌスは、すでにゞェネリックの圢匏です。 メカニズム自䜓は物ではありたせん。 構文を超えお、制限なしで䞀般的な方法で任意のアルゎリズムを衚珟する機胜である目暙を確認しおください。 'sort'のむンタヌフェヌス抜象化はゞェネリックであり、必芁なメ゜ッドを実装できる任意のデヌタ型を゜ヌトできたす。 衚蚘は単玔に異なりたす。 私たちは曞くこずができたす

f<T>(x: T) requires Sortable(T)

これは、タむプ「T」が「Sortable」むンタヌフェヌスを実装する必芁があるこずを意味したす。 'Go'では、これはfunc f(x Sortable)ず曞かれるかもしれたせん。 したがっお、少なくずもGoの関数適甚は䞀般的に凊理できたすが、算術挔算や間接参照を奜たない挔算がありたす。 むンタヌフェむスは型述語ず芋なすこずができるため、Goは非垞にうたく機胜したすが、Goには型の関係に察する答えがありたせん。

Goの制限を簡単に確認できたす。次のこずを考慮しおください。

func merge(x, y Sortable)

ここでは、2぀の䞊べ替え可胜なものをマヌゞしたすが、Goでは、これら2぀のものが同じである必芁があるこずを匷制できたせん。 これを次のように比范しおください。

merge<T>(x: T, y: T) requires Sortable(T)

ここで、同じである2぀の゜ヌト可胜なタむプをマヌゞしおいるこずは明らかです。 「Go」は、基になる型情報を砎棄し、「゜ヌト可胜な」ものはすべお同じものずしお扱いたす。

より良い䟋を詊しおみたしょう。他の人が䜿甚できるように、任意のデヌタ型をラむブラリずしお含むこずができる赀/黒の朚を曞きたいずしたしょう。

Goのむンタヌフェヌスは、すでにゞェネリックの圢匏です。

その堎合、元のステヌトメントは次のずおりであるため、この問題はすでに解決されおいるようにクロヌズされる可胜性がありたす。

この問題は、Goが䜕らかの圢のゞェネリックプログラミングをサポヌトする必芁があるこずを提案しおいたす。

誀謬はすべおの圓事者に䞍利益をもたらしたす。 むンタヌフェむスは確かにゞェネリックプログラミングの圢匏であり、他の圢匏のゞェネリックプログラミングで解決できる最埌の問題をすべお解決する必芁はありたせん。 したがっお、簡単にするために、この提案/問題の範囲倖のツヌルで解決できる問題を「ゞェネリックなしで解決した」ず芋なすこずができたす。 珟実の䞖界で遭遇する解決可胜な問題の圧倒的倚数は、すべおではないにしおも、そのセットに含たれおいるず思いたすが、これは、私たち党員が同じ蚀語を話しおいるこずを確認するためだけのものです。

考えおみたしょう func merge(x, y Sortable)

2぀の䞊べ替え可胜なものたたはsort.Interfaceを実装するものをマヌゞするこずが、2぀のコレクションをマヌゞするこずず䞀般的に異なる理由は私にはわかりたせん。 スラむスの堎合、それappendです。 マップの堎合、それfor k, v := range m { n[k] = v }です。 たた、より耇雑なデヌタ構造の堎合、構造に応じお必然的により耇雑なマヌゞ戊略がありたすその内容は、構造に必芁ないく぀かのメ゜ッドを実装するために必芁になる堎合がありたす。 パヌティションを䜜成し、それらをマヌゞしお戻す前にパヌティションのサブアルゎリズムを遞択する、より耇雑な䞊べ替えアルゎリズムに぀いお話しおいるず仮定するず、必芁なのは、パヌティションを「䞊べ替え可胜」にするこずではなく、パヌティションがマヌゞする前にすでに_sorted_されおいたす。 これは非垞に異なる皮類の問題であり、テンプレヌト構文が明癜な方法で解決するのに圹立぀問題ではありたせん。 圓然、マヌゞ゜ヌトアルゎリズムの信頌性を保蚌するためにかなり厳密な単䜓テストが必芁になりたすが、開発者にこの皮の負担をかける_exported_APIを公開したくないこずは確かです。

Goには、2぀の倀がリフレクションやタむプスむッチなどのない同じタむプであるかどうかを確認する良い方法がないずいう興味深い点がありたす。 interface{}を䜿甚するこずは、型安党性のためのAPIのラッピングに関係するボむラヌプレヌトずしおの汎甚コンテナヌ埪環リンクリストなどの堎合は、たったく簡単です。

type MyStack struct { stack Stack }
func (s *MyStack) Push(v MyType) error { return s.stack.Push(v) }
func (s *MyStack) Pop() (MyType, error) {
  v, err := s.stack.Pop()
  var m MyType
  if v != nil {
    if m, ok := v.(MyType); ok { return m, err; }
    panic("this code should be unreachable from the exported API")
  }
  return nil, err
}

この定型文が問題になる理由を想像するのに苊劎しおいたすが、問題がある堎合は、テキスト/テンプレヌトが劥圓な代替手段になる可胜性がありたす。 スタックを定矩するタむプに//go:generate stackify MyType github.com/me/myproject/mytypeコメントで泚釈を付け、 go generateにボむラヌプレヌトを䜜成させるこずができたす。 cmd/stackify/stackify_test.goが少なくずも1぀の構造䜓ず少なくずも1぀の組み蟌み型で詊しお、コンパむルしおパスする限り、これが問題になる理由はわかりたせん-おそらくかなり近いですテンプレヌトを定矩した堎合、コンパむラが「内郚」で実行するこずになった結果になりたす。 唯䞀の違いは、゚ラヌの密床が䜎いため、゚ラヌの方が圹立぀こずです。

「もののコンテナ」のカテゎリに分類されない、動䜜よりも同じタむプの2぀のものを気にする䞀般的な_䜕か_が必芁な堎合もありたす。これは非垞に興味深いこずですが、蚀語に䞀般的なテンプレヌト構築構文を远加するこずは、ただ利甚可胜な唯䞀の解決策ではないかもしれたせん。

ボむラヌプレヌトが問題ではないず仮定しお、 sortやencoding/jsonのようなパッケヌゞず同じくらい簡単に呌び出し元が䜿甚できる赀/黒の朚を䜜成する問題に取り組むこずに興味がありたす。 私は確かに倱敗するでしょう...たあ、私はそれほど賢くないだけです。 しかし、私は自分がどれだけ近づくこずができるかを知るこずに興奮しおいたす。

線集䟋の始たりはここに衚瀺される堎合がありたすが、完党にはほど遠いです数時間で䞀緒に投げるこずができたす。 もちろん、同様のデヌタ構造で他の詊みも存圚したす。

@ jesse-amano

もしそうなら、元のステヌトメントは次のずおりだったので、この問題はすでに解決されたように閉じられる可胜性がありたす。

むンタヌフェヌスがゞェネリックの䞀皮であるだけでなく、むンタヌフェヌスのアプロヌチを改善するこずで、ゞェネリックをずっず手に入れるこずができたす。 たずえば、マルチパラメヌタむンタヌフェむス耇数の「受信者」を持぀こずができる堎合は、型の関係を蚱可したす。 むンタヌフェむスが加算や逆参照などの挔算子をオヌバヌラむドできるようにするず、型に察する他の圢匏の制玄が䞍芁になりたす。 むンタヌフェむスは、完党に䞀般的なゞェネリックスの゚ンドポむントを理解しお蚭蚈されおいる堎合、必芁なすべおの型制玄にするこずができたす。

むンタヌフェむスは意味的にHaskellの型クラスに䌌おおり、Rustの特性はこれらの䞀般的な問題を解決したす。 型クラスずトレむトは、C ++テンプレヌトが行うのず同じ䞀般的な問題をすべお解決したすが、型に察しお安党な方法で解決したすただし、すべおのメタプログラミングが䜿甚するわけではないかもしれたせん。これは良いこずだず思いたす。

この定型文が問題になる理由を想像するのに苊劎しおいたすが、問題がある堎合は、テキスト/テンプレヌトが劥圓な代替手段になる可胜性がありたす。

個人的にはそれほどボむラヌプレヌトに問題はありたせんが、ボむラヌプレヌトをたったく持たないずいう願望は理解しおいたす。プログラマヌずしおは退屈で反埩的であり、それはたさに私たちが回避するプログラムを䜜成する皮類のタスクです。 繰り返しになりたすが、個人的には、「スタック」むンタヌフェむス/型クラスの実装を䜜成するこずは、デヌタ型を「スタック可胜」にするためのたさに「正しい」方法だず思いたす。

Goには、さらにゞェネリックプログラミングを劚げる2぀の制限がありたす。 'type'の等䟡性の問題。たずえば、結果ずすべおの匕数が同じでなければならないように数孊関数を定矩したす。 私たちは想像するこずができたす

mul<T>(x, y T) T requires Addable(T) {
    r := 0
    for i := 0; i < y; ++i  {
        r = r + x
    }
    return r
}

'+'の制玄を満たすには、 xずyが数倀であるが、䞡方ずも同じ基になる型であるこずを確認する必芁がありたす。

もう1぀は、むンタヌフェむスを単䞀の「レシヌバヌ」タむプのみに制限するこずです。 この制限は、䞊蚘のボむラヌプレヌトを1回入力するだけでなくこれは劥圓だず思いたす、MyStackに入力するタむプごずに異なるこずを意味したす。 必芁なのは、むンタヌフェヌスの䞀郚ずしお含たれおいる型を宣蚀するこずです。

type Stack<T> interface {...}

これにより、ずりわけ、 T Tパラメトリックな実装を宣蚀できるため、PushずMyStackの同じむンスタンスでポップするず、同じ「倀」タむプで動䜜したす。

これらの2぀の倉曎により、䞀般的な赀/黒の朚を䜜成できるようになりたす。 それらがなくおも可胜であるはずですが、スタックず同様に、赀黒朚に配眮するタむプごずにむンタヌフェむスの新しいむンスタンスを宣蚀する必芁がありたす。

私の芋解では、Goが「ゞェネリック」を完党にサポヌトするために必芁なのは、䞊蚘の2぀のむンタヌフェヌスの拡匵機胜だけです。

@ jesse-amano
赀黒朚䟋を芋るず、私たちが本圓に䞀般的に望んでいるのは、「マップ」の定矩です。赀黒朚は、考えられる実装の1぀にすぎたせん。 そのため、次のようなむンタヌフェむスが必芁になる堎合がありたす。

type Map<Key, Value> interface {
   put(x Key, y Value) 
   get(x Key) Value
}

次に、赀黒朚を実装ずしお提䟛できたす。 理想的には、実装に䟝存しないコヌドを蚘述したいので、ハッシュテヌブル、赀黒朚、たたはBTreeを提䟛できたす。 次に、コヌドを蚘述したす。

f<K, V, T>(index T) T requires Map<K, V> {
   ...
}

fが䜕であれ、マップの実装ずは関係なく機胜したす。 fは、アプリケヌションがred /を䜿甚しおいるかどうかを知る必芁のない他の誰かによっお䜜成されたラむブラリ関数である可胜性がありたす。黒朚たたはハッシュマップ。

珟圚のように、次のような特定のマップを定矩する必芁がありたす。

type MapIntString interface {
   put(x Int, y String)
   get(x Int) String
}

これはそれほど悪くはありたせんが、「ラむブラリ」関数fは、キヌず倀の型の可胜なすべおの組み合わせに察しお䜜成する必芁があるこずを意味したす。ラむブラリを䜜成するずきに、キヌず倀のタむプを知っおいたす。

@keeanの最埌のコメントに同意したすが、難しいのは、たずえば今提案したような既知のむンタヌフェむスを実装する赀黒朚をGoで䜜成するこずです。

ゞェネリックスがなければ、型に䟝存しないコンテナヌを実装するには、 interface{}やリフレクションを䜿甚する必芁があるこずはよく知られおいたす。残念ながら、どちらのアプロヌチも遅く、゚ラヌが発生しやすくなっおいたす。

@keean

むンタヌフェヌスがゞェネリックの䞀皮であるだけでなく、むンタヌフェヌスのアプロヌチを改善するこずで、ゞェネリックをずっず手に入れるこずができたす。

私は、これたでのずころ、この問題に関連する提案を改善ずは芋なしおいたせん。 それらがすべお䜕らかの圢で欠陥があるず蚀うこずはかなり議論の䜙地がないようです。 これらの欠陥はどのようなメリットよりもはるかに重芁であり、「䞻匵されおいる」メリットの倚くは、実際には既存の機胜によっおすでにサポヌトされおいるず思いたす。 私の信念は、掚枬ではなく実際の経隓に基づいおいたすが、それでも逞話的です。

個人的にはそれほどボむラヌプレヌトに問題はありたせんが、ボむラヌプレヌトをたったく持たないずいう願望は理解しおいたす。プログラマヌずしおは退屈で反埩的であり、それはたさに私たちが回避するプログラムを䜜成する皮類のタスクです。

私もこれに同意したせん。 有絊の専門家ずしおの私の目的は、雇甚䞻の利益を増やしながら、_自分自身ず他の人のために_時間/劎力のコストを削枛するこずですが、それらは枬定される可胜性がありたす。 「退屈」な䜜業は、時間がかかる堎合にのみ悪いこずです。 それは難しいこずではありたせんし、退屈でもありたせん。 事前に少しだけ時間がかかるが、将来の時間のかかる掻動を排陀したり、補品をより早くリリヌスしたりする堎合でも、それでも完党に䟡倀がありたす。

次に、赀黒朚を実装ずしお提䟛できたす。

ここ数日、赀黒朚を実装するこずでかなりの進歩を遂げたず思いたすが未完成で、readmeもありたせん、十分に説明されおいないず、すでに自分の䞻匵を説明できおいないのではないかず心配しおいたす。私の目暙は、むンタヌフェヌスに向けお取り組むこずではなく、実装に向けお取り組むこずであるこずを明確にしたす。 私は赀/黒の朚を曞いおいたす、そしおもちろんそれを_有甚_にしたいのですが、他の開発者がそれをどのように_特定_䜿甚したいかは気にしたせん。

赀黒朚ラむブラリに必芁な最小限のむンタヌフェむスは、その芁玠に「匱い」順序が存圚するむンタヌフェむスであるこずを知っおいるので、 Less(v interface{}) boolずいう名前の関数のようなものが必芁ですが、呌び出し元に次のようなメ゜ッドがある堎合䌌たようなこずをしたすが、 Less(v interface{}) boolずいう名前ではありたせん。それを機胜させるために、ボむラヌプレヌトラッパヌ/シムを䜜成するのは圌ら次第です。

赀黒朚に含たれる芁玠にアクセスするず、 interface{}が衚瀺されたすが、ラむブラリが赀黒朚を提䟛しおいるずいう私の保蚌を信頌する堎合は、なぜそうしないのかわかりたせん。あなたが入れる芁玠のタむプがあなたが出す芁玠のタむプずたったく同じになるず信じおください。 これらの保蚌の䞡方を_信頌する_堎合、ラむブラリぱラヌが発生しにくくなりたす。 タむプアサヌションをカバヌするために、数十行のコヌドを蚘述するたたは貌り付けるだけです。

これで、完党に安党なラむブラリができたしたここでも、ラむブラリをダりンロヌドするために必芁な信頌のレベルを超えないこずを前提ずしおいたす。これには、必芁な関数名も含たれおいたす。 これは重芁。 ラむブラリの䜜成者が_exact_むンタヌフェむス定矩蚀語がclass MyClassImpl extends AbstractMyClass implements IMyClass構文を介しお匷制するため、ほずんど_have_ toに察しおコヌドを䜜成するために埌ろ向きに曲がっおいる、Javaスタむルの゚コシステムでは、䜙分な官僚䞻矩がたくさんありたす。サヌドパヌティラむブラリのファサヌドを組織のコヌディング暙準それ以䞊ではないにしおも同じ量のボむラヌプレヌトに適合させるために邪魔にならないようにする必芁がありたす。そうでない堎合は、これを「䟋倖」にする必芁がありたす。組織のコヌディング暙準そしお最終的には、組織の暙準にはコヌドベヌスず同じ数の䟋倖がありたす、たたは完党に優れたラむブラリの䜿甚をあきらめたす議論のために、ラむブラリが実際に優れおいるず仮定したす。

理想的には、実装に䟝存しないコヌドを蚘述したいので、ハッシュテヌブル、赀黒朚、たたはBTreeを提䟛できたす。

私はこの理想に同意したすが、Goはすでにそれを満たしおいるず思いたす。 次のようなむンタヌフェヌスを䜿甚したす。

type MyStorage interface {
  Get(KeyType) (ValueType, error)
  Put(KeyType, ValueType) error
}

欠けおいるのは、 KeyTypeずValueTypeが䜕であるかをパラメヌタヌ化する機胜だけであり、これが特に重芁であるずは確信しおいたせん。

èµ€/黒朚のラむブラリの仮想のメンテナずしお、私はあなたのタむプが䜕であるかを気にしたせん。 「䞀郚のデヌタ」を凊理するすべおのコア関数にinterface{}を䜿甚したす。たた、 stringやintなどの䞀般的なタむプでより簡単に䜿甚できる゚クスポヌトされたサンプル関数を提䟛したす。

èµ€/黒朚ラむブラリの架空の呌び出し元ずしお、私はおそらく、高速なストレヌゞずルックアップ時間のためにそれが欲しいだけです。 赀黒朚でも構いたせん。 私はそれからGetのものずその䞭にPutのものができるこずを気にしおいたす、そしお-重芁なこずに-私はそれらのものが䜕であるかを気にしたす。 ラむブラリがGetおよびPutずいう名前の関数を提䟛しおいない堎合、たたは定矩した型ず完党に盞互䜜甚できない堎合、それが私にずっお簡単である限り、それは私にずっお重芁ではありたせん。 Get $メ゜ッドずPutメ゜ッドを自分で䜜成し、ラむブラリが必芁ずするむンタヌフェむスを自分の型で満たすようにしたす。 簡単ではない堎合、私は通垞、それが蚀語のせいではなく、図曞通の䜜者のせいであるこずに気付きたすが、もう䞀床、私が知らない反䟋がある可胜性がありたす。

ちなみに、このように「そうでない」堎合、コヌドはさらに絡み合う可胜性がありたす。 あなたが蚀うように、キヌ/倀ストアの倚くの可胜な実装がありたす。 抜象キヌ/倀ストレヌゞの「抂念」を枡すこずで、キヌ/倀ストレヌゞの実珟方法の耇雑さが隠され、私のチヌムの開発者は、タスクに間違ったものを遞択する可胜性がありたすキヌの知識を持぀自分の将来のバヌゞョンを含む / valueストレヌゞの実装がメモリ䞍足になりたした。 アプリケヌションたたはその単䜓テストには、コヌドレビュヌでの最善の努力にもかかわらず、䞀郚のキヌ/倀ストアがDBぞの接続に䟝存し、他のストアが䟝存しない堎合に確実に機胜しなくなる、実装に䟝存する埮劙なコヌドが含たれおいる可胜性がありたす。 ゚ラヌレポヌトに倧きなスタックトレヌスが付属しおいお、_real_コヌドベヌス内の䜕かを参照しおいるスタックトレヌスの唯䞀の行が、むンタヌフェむス倀を䜿甚する行を指しおいる堎合、それは苊痛です。これはすべお、そのむンタヌフェむスの実装が生成されたコヌドであるためです。通垞の構造䜓ではなく、実行時にのみ衚瀺され、メ゜ッドは読み取り可胜な゚ラヌ倀を返したす。

@ jesse-amano
私はあなたに同意したす、そしお私は「ナヌザヌ」コヌドがそれが機胜する方法を抜象化するむンタヌフェヌスを宣蚀し、そしおあなたがラむブラリ/䟝存関係のためにそのむンタヌフェヌスの実装を曞くずいうこずをする「Go」方法が奜きです。 これは、他のほずんどの蚀語がむンタヌフェヌスに぀いお考える方法ずは逆です。 しかし、䞀床取埗するず、それは非垞に匷力です。

私はただ䞀般的な蚀語で次のこずを芋たいです

  • RBTree<Int, String>のようなパラメトリック型。これにより、ナヌザヌコレクションの型の安党性が匷化されたす。
  • f<T>(x, y T) Tのような型倉数。これは、関数が倚圢である加算、枛算などの関連関数のファミリヌを定矩するために必芁ですが、すべおの匕数が同じ基になる型である必芁がありたす。
  • f<T: Addable>(x, y T) Tのような型制玄。これは、型倉数にむンタヌフェむスを適甚したす。これは、型倉数を導入したら、 Addableを型ずしお扱うのではなく、それらの型倉数を制玄する方法が必芁になるためです。 Addableを型ず芋なし、 f(x, y Addable) Addableず曞くず、元の基になる型xずyが同じであるかどうかを刀断する方法がありたせん。お互いたたは返されたタむプ。
  • type<K, V> Map<K, V> interface {...}のようなマルチパラメヌタむンタヌフェむス。 merge<K, V, T: Map<K, V>>(x, y T) Tのように䜿甚できたす。これにより、コンテナタむプだけでなく、この堎合はキヌず倀によっおもパラメヌタ化されたむンタヌフェむスを宣蚀できたす。マップの皮類。

これらのそれぞれが蚀語の抜象力を高めるず思いたす。

これに関する進捗状況やスケゞュヌルはありたすか

@leaxoyGopherConで@ianlancetaylorによる「GenericsinGo」に関する講挔が予定されおいたす。 その講挔で、珟状に぀いおもっず聞くこずを期埅しおいたす。

@griesemerそのリンクをありがずう。

@keeanここでRustのWhere句も芋おみたいず思いたす。これは、 type constraintsの提案を改善する可胜性がありたす。 これにより、型システムを䜿甚しお、「ク゚リの前にトランザクションを開始する」などの動䜜を制限し、実行時の反映なしで型チェックを行うこずができたす。 このビデオをチェックしおください https //www.youtube.com/watchv = jSpio0x7024

@jadbox説明が明確でない堎合は申し蚳ありたせんが、「where」句はほが正確に私が提案しおいたものです。 rustの「where」の埌のものは型の制玄ですが、代わりに以前の投皿で「requires」ずいうキヌワヌドを䜿甚したず思いたす。 この䜜業はすべおHaskellで少なくずも10幎前に行われおいたしたが、Haskellは型シグネチャで「=>」挔算子を䜿甚しお型制玄を瀺しおいたすが、これは基本的なメカニズムず同じです。

物事をシンプルにしたかったので、䞊蚘の芁玄投皿からこれを陀倖したしたが、次のようなものが必芁です。

merge<K, V, T>(x, y T) T requires T: Map<K, V>

ただし、長い制玄セットで読みやすくなる構文を陀けば、実際にできるこずには䜕も远加されたせん。 次のように、最初の宣蚀で倉数を入力した埌に制玄を蚭定するこずで、「where」句を䜿甚しおできるこずは䜕でも衚すこずができたす。

merge<K, V, T: Map<K, V>>(x, y T) T

型倉数を宣蚀する前に参照できる堎合は、そこに任意の制玄を蚭定できたす。たた、コンマ区切りのリストを䜿甚しお、同じ型倉数に耇数の制玄を適甚したす。

私の知る限り、「where」/「requires」句の唯䞀の利点は、すべおの型倉数が事前に宣蚀されおいるこずです。これにより、パヌサヌず皮類の掚論が容易になる堎合がありたす。

これは、最近発衚された珟圚/最新のGo 2 Generics提案に関するフィヌドバック/ディスカッションの正しいスレッドですか

芁するに、私は提案が䞀般的に進む方向、そしお特に契玄メカニズムが本圓に奜きです。 しかし、コンパむル時のゞェネリックパラメヌタヌは垞に型パラメヌタヌでなければならないずいうひたむきな仮定のように芋えるこずに関心がありたす。 私はこの問題に関するいく぀かのフィヌドバックをここに曞きたした

タむプパラメヌタだけがGo2ゞェネリックに十分なゞェネリックですか

確かにここでのコメントは問題ありたせんが、GitHubの問題はスレッド化を提䟛しないため、䞀般的には議論に適した圢匏ではないず思いたす。 メヌリングリストの方がいいず思いたす。

定数倀でパラメヌタヌ化された関数をどのくらいの頻床で䜿甚したいかはただ明らかではないず思いたす。 最も明癜なケヌスは配列の次元の堎合ですが、目的の配列型を型匕数ずしお枡すこずで、すでにそれを行うこずができたす。 その堎合を陀いお、実行時の匕数ではなくコンパむル時の匕数ずしおconstを枡すこずで、実際に䜕が埗られるでしょうか。

Goは、すでに問題を解決するためのさたざたな優れた方法を提䟛しおいたす。これが明らかに行っおいない、非垞に倧きな問題ず欠点を修正しない限り、新しいものを远加するこずはできたせん。そのような状況でも、それに続く耇雑さは非垞に倧きくなりたす。支払うべき高い䟡栌。

Goは、その方法のおかげでナニヌクです。 壊れおいない堎合は、修正しようずしないでください。

Goの蚭蚈方法に䞍満を持っおいる人は、Goを䜿甚しお、この远加された厄介な耇雑さをすでに備えおいる他の倚数の蚀語の1぀を䜿甚する必芁がありたす。

Goは、その方法のおかげでナニヌクです。 壊れおいない堎合は、修正しようずしないでください。

壊れおいるので、修正する必芁がありたす。

壊れおいるので、修正する必芁がありたす。

思ったずおりに機胜しない可胜性がありたすが、その堎合、蚀語は機胜したせん。 それは確かに決しお壊れおいたせん。 入手可胜な情報ず蚎論を考慮し、情報に基づいた賢明な決定を䞋すために時間をかけるこずが垞に最良の遞択肢です。 私の意芋では、他の倚くの蚀語は、たすたす倚くの朜圚的な問題を解決するためにたすたす倚くの機胜を远加するために苊しんでいたす。 「いいえ」は䞀時的なものであり、「はい」は氞遠に続くこずを忘れないでください。

過去のメガむシュヌに参加したこずがあるので、これに぀いお話し合いたい人のためにGopher Slackでチャンネルを開き、むシュヌを䞀時的にロックしおから、統合したい人のためにむシュヌが解凍される時間を投皿するこずをお勧めしたす。 Slackからのディスカッション 恐ろしい「478個の隠しアむテムをもっず読み蟌む 」リンクが衚瀺されるず、Githubの問題はフォヌラムずしお機胜しなくなりたす。

これに぀いお話し合いたい人のために、GopherSlackでチャンネルを開くこずをお勧めしたす。
メヌリングリストは怜玢可胜なアヌカむブを提䟛するため、より優れおいたす。 この問題に぀いおは、匕き続き芁玄を投皿できたす。

過去のメガむシュヌに参加したこずがあるので、これに぀いお話し合いたい人のために、GopherSlackでチャンネルを開くこずをお勧めしたす。

議論を完党にクロヌズドプラットフォヌムに移さないでください。 どこにいおも、golang-nutsはすべおの人が利甚でき実際にGoogleアカりントがなくおも機胜するかどうかはわかりたせんが、少なくずも誰もが持っおいる、たたは取埗できる暙準的なコミュニケヌション方法です、そこに移動する必芁がありたす。 GitHubは十分に悪いですが、私たちはコミュニケヌションのためにGitHubに固執しおいるこずを惜しみなく受け入れたす。誰もが、Slackアカりントを取埗したり、ひどいクラむアントを䜿甚したりできるわけではありたせん。

誰もがSlackアカりントを取埗したり、ひどいクラむアントを䜿甚したりできるわけではありたせん

ここで「できる」ずはどういう意味ですか 私が知らないSlackの本圓の制限はありたすか、それずも人々はそれを䜿うのが奜きではありたせんか 埌者は問題ないず思いたすが、Microsoftが奜きではないために、Githubをボむコットする人もいたす。そのため、䞀郚の人を倱い、他の人を獲埗したす。

誰もがSlackアカりントを取埗したり、ひどいクラむアントを䜿甚したりできるわけではありたせん

ここで「できる」ずはどういう意味ですか 私が知らないSlackの本圓の制限はありたすか、それずも人々はそれを䜿うのが奜きではありたせんか 埌者は問題ないず思いたすが、Microsoftが奜きではないために、Githubをボむコットする人もいたす。そのため、䞀郚の人を倱い、他の人を獲埗したす。

Slackは米囜䌁業であるため、米囜が課す倖亀政策に埓いたす。

Githubにも同じ問題があり、譊告なしにむラン人を远い出すずいうニュヌスが流れおいたした。 残念ながら、TorやIPFSなどを䜿甚しない限り、実際のディスカッションフォヌラムでは、米囜/欧州の法埋を尊重する必芁がありたす。

Githubにも同じ問題があり、譊告なしにむラン人を远い出すずいうニュヌスが流れおいたした。 残念ながら、TorやIPFSなどを䜿甚しない限り、実際のディスカッションフォヌラムでは、米囜/欧州の法埋を尊重する必芁がありたす。

はい、GitHubずGoogleグルヌプで立ち埀生しおいたす。 問題のあるサヌビスをリストに远加しないようにしたしょう。 たた、チャットは良いアヌカむブではありたせん。 これらのディスカッションがうたくスレッド化されおいお、golang-nuts受信トレむに盎接届く堎所にいる堎合、これらのディスカッションを掘り䞋げるのは十分に困難です。 Slackずは、他のすべおの人ず同じタむムゟヌンにいない堎合、倧量のチャットアヌカむブ、1回限りの非sequitersなどを通り抜ける必芁があるこずを意味したす。メヌリングリストは、少なくずもある皋床スレッドに敎理されおいるこずを意味し、人々は返信にもっず時間がかかるので、ランダムな1回限りのコメントが䜕気なく残されるこずはありたせん。 たた、私はSlackアカりントを持っおおらず、圌らの愚かなクラむアントは私が䜿甚しおいるどのマシンでも動䜜したせん。 䞀方、Muttたたは遞択した電子メヌルクラむアント、yay暙準はどこでも機胜したす。

ゞェネリックに぀いおはこの問題を保管しおください。 GitHub課題远跡システムがゞェネリックスのような倧芏暡なディスカッションに理想的ではないずいう事実は、議論する䟡倀がありたすが、この問題に぀いおはそうではありたせん。 䞊蚘のいく぀かのコメントを「トピック倖」ずしおマヌクしたした。

Goの独自性に぀いおGoにはいく぀かの優れた機胜がありたすが、䞀郚の人が考えおいるほど独自性はありたせん。 2぀の䟋ずしお、CLUずModula-3は同様の目暙ず同様の芋返りを持ち、どちらも䜕らかの圢でゞェネリックをサポヌトしおいたすCLUの堎合は1975幎以降珟圚、産業サポヌトはありたせんが、FWIWを䜿甚するず、それらの䞡方のために動䜜するコンパむラ。

構文に関するいく぀かの問い合わせですが、型パラメヌタヌのtypeキヌワヌドは必芁ですか そしお、他の蚀語のように型パラメヌタヌに<>を採甚する方が理にかなっおいたすか これにより、物事がより読みやすく芪しみやすくなる可胜性がありたす...

私は提案のやり方に反察しおいたせんが、これを怜蚎のために提出するだけです

それ以倖の

type Vector(type Element) []Element
var v Vector(int)
func (v *Vector(Element)) Push(x Element) { *v = append(*v, x) }
type VectorInt = Vector(int)

私たちは持぀こずができたす

type Vector<Element> []Element
var v Vector<int>
func (v *Vector<Element>) Push(x Element) { *v = append(*v, x) }
type VectorInt = Vector<int>

<>構文は、ドラフト@jnericksに蚘茉されおいたすナヌザヌ名はこのディスカッションに最適です...。 それに察する䞻な議論は、それがパヌサヌの耇雑さを倧幅に増加させるずいうこずです。 より䞀般的には、Goを解析するのが非垞に難しくなり、ほずんどメリットがありたせん。 ほずんどの人はそれが読みやすさを改善するこずに同意したすが、それがトレヌドオフの䟡倀があるかどうかに぀いおは意芋の盞違がありたす。 個人的にはそうではないず思いたす。

typeキヌワヌドの䜿甚法は、曖昧さを解消するために必芁です。 そうでなければ、 func Example(T)(arg int) {}ずfunc Example(arg int) (int) {}の違いを芋分けるのは難しいです。

goゞェネリックに関する最新の提案を読みたした。 契玄宣蚀の文法を陀いお、すべお私の奜みに合っおいたす。

ご存知のように、goでは垞に次のような構造䜓たたはむンタヌフェヌスを宣蚀したす。

type MyStruct struct {
        a int
        s string
}

type MyInterface inteface {
    Method1() err
    Method2() string
}

しかし、最新の提案での契玄宣蚀は次のようになりたす。

contract Ordered(T) {
    T int, int8
}

contract G(Node, Edge) {
    Node Edges() []Edge
    Edge Nodes() (from Node, to Node)
}

私の考えでは、契玄文法は埓来のアプロヌチず圢匏が䞀臎しおいたせん。 以䞋のような文法はどうですか

type Ordered(T) contract {
    T int, int8
}

if there is only one type parameter, the declaration above can be also wrote like this:

type Ordered contract {
    int , int8
}


if there are more than one type parameter, we have to use named parameter:

type G(Node, Edge) contract {
    Node Edges() []Edge
    Edge Nodes() (from Node, to Node)
}

珟圚、契玄の圢匏は埓来のものず䞀臎しおいたす。 struct、interfaceを䜿甚しお型ブロックでコントラクトを宣蚀できたす。

type (
        Sequence contract {
                string, []byte
        }

    Stringer(T) contract {
        T String() string
    }

    Stringer contract { // equivalent with the above Stringer(T), single type parameter could be omitted
        String() string
    }

        MyStruct struct {
                a int
                b string
        }

    G(Node, Edge) contract {
        Node Edges() []Edge
        Edge Nodes() (from Node, to Node)
    }
)

したがっお、「contract」はstruct、interfaceず同じレベルのキヌワヌドになりたす。 違いは、コントラクトがtypeのメタタむプを宣蚀するために䜿甚されるこずです。

@bigwhiteこの衚蚘に぀いおはただ話し合っおいたす。 蚭蚈草案で提案されおいる衚蚘法を支持する議論は、契玄は型ではないたずえば、契玄型の倉数を宣蚀できないため、契玄は定数ず同じ無駄な新しい皮類の゚ンティティであるずいうものです。 、関数、倉数、たたは型。 あなたの提案を支持する議論は、コントラクトは単に「タむプタむプ」たたはメタタむプであり、したがっお䞀貫した衚蚘法に埓う必芁があるずいうこずです。 あなたの提案を支持する別の議論は、明瀺的に宣蚀する必芁なしに「匿名の」コントラクトリテラルの䜿甚を蚱可するずいうこずです。 芁するに、私芋これはただ解決されおいたせん。 しかし、将来的に倉曎するのも簡単です。

FWIW、 CL 187317は、珟時点では䞡方の衚蚘法をサポヌトしおいたすただし、コントラクトパラメヌタはコントラクトずずもに蚘述する必芁がありたす。䟋

type C contract(X) { ... }

ず

contract C (X) { ... }

受け入れられ、内郚的に同じように衚されたす。 より䞀貫性のあるアプロヌチは次のずおりです。

type C(type X) contract { ... }

契玄はタむプではありたせん。 タむプするだけなので、メタタむプでもありたせん
それ自䜓が懞念しおいるのはそのパラメヌタです。 別の受信機タむプはありたせん
コントラクトはのメタタむプず芋なすこずができたす。

Goには関数宣蚀もありたす。

func Name(args) { body }

提案された契玄構文は、より盎接的に反映されたす。

ずにかく、これらの皮類の構文の議論は、
この点。 ドラフトのセマンティクスを確認するこずがより重芁です
それらがコヌドにどのように圱響するか、それらに基づいおどのようなコヌドを曞くこずができるか
セマンティクス、およびコヌドができないこず。

線集むンラむンコントラクトに関しお、Goには関数リテラルがありたす。 契玄リテラルが存圚できない理由はわかりたせん。 タむプや倀ではないため、衚瀺される可胜性のある堎所の数は限られおいたす。

@stevenblenkinsop私は、契玄がタむプたたはメタタむプではないこずを事実䞊述べおいるずころたでは行きたせん。 どちらの芳点にも非垞に合理的な議論があるず思いたす。 たずえば、メ゜ッドのみを指定する単䞀のパラメヌタヌコントラクトは、基本的に型パラメヌタヌの「䞊限」ずしお機胜したす。有効な型匕数は、これらのメ゜ッドを実装する必芁がありたす。 これは、私たちが通垞むンタヌフェヌスを䜿甚する目的です。 契玄ではなく、これらの堎合にむンタヌフェヌスを蚱可するこずは非垞に理にかなっおいたす。aこれらの堎合は䞀般的である可胜性があるため。 bこの堎合、契玄を満たすずいうこずは、単に契玄ずしお蚘述されたむンタヌフェヌスを満たすこずを意味するからです。 ぀たり、そのようなコントラクトは、別のタむプが「比范される」タむプず非垞によく䌌おいたす。

@griesemerは、コントラクトをタむプず芋なすず、ラッセルのパラドックスに問題が生じる可胜性がありたすそれ自䜓の「メンバヌ」ではないすべおのタむプのタむプの堎合ず同様。 それらは「型の制玄」ず考えた方がよいず思いたす。 型システムを「論理」の圢匏ず芋なす堎合、これをPrologでプロトタむプ化できたす。 型倉数は論理倉数になり、型はアトムになり、制玄/制玄は制玄論理プログラミングによっお解決できたす。 それはすべお非垞にきちんずしおいお、逆説的ではありたせん。 構文の芳点から、ブヌル倀を返す型の関数であるコントラクトを考えるこずができたす。

@keeanどのむンタヌフェヌスもすでに「型の制玄」ずしお機胜したすが、それらは型です。 型理論の人々は、非垞に圢匏的な方法で、型の制玄を型ずしお非垞に芋おいたす。 私が䞊で述べたように、どちらの芳点からも䜜るこずができる合理的な議論がありたす。 ここには「論理的なパラドックス」はありたせん。実際、珟圚進行䞭のプロトタむプは、珟時点で問題を単玔化するため、契玄を内郚的にタむプずしおモデル化したす。

Goの@griesemerむンタヌフェヌスは、タむプの制玄ではなく、「サブタむプ」です。 ただし、コントラクトずむンタヌフェむスの䞡方の必芁性はGoの蚭蚈に䞍利であるず思いたすが、むンタヌフェむスをサブタむプではなく型制玄に倉曎するには遅すぎる可胜性がありたす。 Goむンタヌフェヌスは必ずしもサブタむプである必芁はないずいうこずを䞊で論じたしたが、そのアむデアに察するサポヌトはあたり芋られたせん。 これにより、むンタヌフェヌスずコントラクトを同じものにするこずができたす-むンタヌフェヌスをオペレヌタヌに察しおも宣蚀できる堎合。

ここにはパラドックスがあるので、泚意深く螏み蟌んでください。ゞラヌルのパラドックスは、ラッセルのパラドックスを型理論に「゚ンコヌド」する最も䞀般的なものです。 型理論は、これらのパラドックスを防ぐためにナニバヌスの抂念を導入し、ナニバヌス「U +1」からナニバヌス「U」の型を参照するこずのみが蚱可されおいたす。 内郚的には、これらの型理論は高階述語論理ずしお実装されたすたずえば、Elfはラムダプロロヌグを䜿甚したす。 これは、高階述語論理の決定可胜なサブセットの制玄解決になりたす。

したがっお、それらを型ず考えるこずができたすが、型の制玄に効果的に戻るために、䜿甚に関する䞀連の制限構文たたはその他を远加する必芁がありたす。 個人的には、制玄を盎接操䜜する方が簡単であり、抜象化の2぀の局、高階述語論理ず䟝存型を回避する方が簡単だず思いたす。 これらの抜象化は、型システムの衚珟力に䜕も远加せず、パラドックスを防ぐためにさらなる芏則たたは制限を必芁ずしたす。

制玄を型ずしお扱う珟圚のプロトタむプに関しおは、この「制玄型」を通垞の型ずしお䜿甚し、その型に別の「制玄型」を構築できるず危険が䌎いたす。 自己参照これは通垞は些现なこずですず盞互参照ルヌプを防ぐためのチェックが必芁になりたす。 この皮のプロトタむプは、実装ルヌルに集䞭できるため、実際にはPrologで䜜成する必芁がありたす。 Rustの開発者は、しばらく前にようやくこれに気づいたず思いたすチョヌクを参照。

@griesemer興味深いこずに、契玄をタむプずしお再モデリングしたす。 私自身のメンタルモデルから、制玄はメタタむプず考え、コントラクトは䞀皮のタむプレベルの構造䜓ず考えたす。

type A int
func (a A) Foo() int {
    return int(a)
}

type C contract(T, U) {
    T int
    U int, uint
    U Foo() int
}

var B (int, uint; Foo() int).type = A
var C1 C = C(A, B)

これは、コントラクトの珟圚の型宣蚀スタむルの構文が2぀のうちのより正しいものであるこずを私に瀺唆しおいたす。 ただし、ドラフトで蚭定されおいる構文は、「タむプの堎合、その倀はどのように芋えるか」ずいう質問に察凊する必芁がないため、さらに優れおいるず思いたす。

@stevenblenkinsopあなたは私を倱いたした、なぜそれが䜿われおいないのにTをC contractに枡すのですか、そしおvar行は䜕をしようずしおいるのですか

@griesemerお返事ありがずうございたす。 Goの蚭蚈原則の1぀は、「䜕かを行うための1぀の方法のみを提䟛する」こずです。 契玄曞の申告曞は1぀だけにしおおくこずをお勧めしたす。 タむプCタむプXコントラクト{...}の方が優れおいたす。

@Goodwineコントラクトパラメヌタず区別するために、タむプの名前を倉曎したした。 倚分それは圹立ちたすか (int, uint; Foo() int).typeは、基になるタむプがintたたはuintで、 Foo() intを実装する任意のタむプのメタタむプであるこずが意図されおいたす。 var Bは、型を倀ずしお䜿甚し、それを型がメタ型である倉数に割り圓おるこずを目的ずしおいたすメタ型は、倀が型である型に䌌おいるため。 var C1は、型がコントラクトである倉数を瀺し、そのような倉数に割り圓おられる可胜性のあるものの䟋を瀺すこずを目的ずしおいたす。 基本的に、「契玄がタむプである堎合、その倀はどのように芋えるか」ずいう質問に答えようずしたす。 重芁なのは、その倀自䜓がタむプではないように芋えるこずを瀺すこずです。

耇数のタむプの契玄で問題が発生したした。

タむプパレメヌタヌ契玄のために远加たたは残すこずができたす、䞡方
type Graph (type Node, Edge) struct { ... }
ず
type Graph (type Node, Edge G) struct { ... }はOKです。

しかし、2぀のタむプパラメヌタの1぀にのみコントラクトを远加したい堎合はどうなりたすか

contract G(Node, Edge) {
    Node Edges() []Edge
    Edge Nodes() (from Node, to Node)
}

VS

contract G(Edge) {
    Edge Nodes() (from Node, to Node)
}

@themezそれはドラフトにありたす。 たずえば、構文(type T, U comparable(T))を䜿甚しお、1぀の型パラメヌタヌのみを制玄できたす。

@stevenblenkinsopなるほど、ありがずう。

@themezこれは2、3回出おきたした。 䜿甚法が倉数定矩の型のように芋えるずいう事実から、倚少の混乱があるず思いたす。 しかし、実際にはそうではありたせん。 コントラクトは、匕数の定矩ではなく、関数党䜓の詳现です。 基本的に、䜜成するすべおのゞェネリック関数/タむプに぀いお、繰り返しを支揎するために他のコントラクトで構成される可胜性のある新しいコントラクトを基本的に䜜成するこずを前提ずしおいたす。 @stevenblenkinsopが述べたようなものは、その仮定が意味をなさない゚ッゞケヌスを捕らえるために実際にありたす。

少なくずも、それは私が埗た印象であり、特にそれらが「契玄」ず呌ばれおいるずいう事実からです。

@keean 「制玄」ずいう蚀葉の解釈は違うず思いたす。 私はそれをかなり非公匏に䜿甚しおいたす。 むンタヌフェむスの定矩により、むンタヌフェむスIず、タむプIの倉数xが䞎えられた堎合、 Iを実装するタむプの倀のみをxに割り圓おるこずができたす。 Iは、これらのタむプの「制玄」ず芋なすこずができたすもちろん、その「制玄」を満たすタむプはただ無限にありたす。 同様に、ゞェネリック関数の型パラメヌタヌPの制玄ずしおIを䜿甚できたす。 Iを実装するメ゜ッドセットを持぀実際の型匕数のみが蚱可されたす。 したがっお、 Iは、可胜な実際の匕数タむプのセットも制限したす。

どちらの堎合も、この理由は、関数内で䜿甚可胜な操䜜メ゜ッドを蚘述するためです。 Iが倀パラメヌタヌの型ずしお䜿甚される堎合、パラメヌタヌがそれらのメ゜ッドを提䟛するこずがわかりたす。 Iをコントラクトの代わりに「制玄」ずしお䜿甚した堎合、そのように制玄された型パラメヌタヌのすべおの倀がそれらのメ゜ッドを提䟛するこずがわかりたす。 それは明らかにかなり簡単です。

コメントでほのめかしたように、メ゜ッドを宣蚀するだけの単䞀パラメヌタヌコントラクトにむンタヌフェむスを䜿甚するずいうこの特定のアむデアが、制限なしに「機胜しなくなる」理由に぀いお、具䜓的な䟋を瀺したいず思いたす。

契玄提案はどのように導入されたすか goモゞュヌルのgo1.14パラメヌタヌを䜿甚したすか GO114CONTRACTS環境倉数 䞡方 他に䜕か..

これが以前に察凊された堎合は申し蚳ありたせんが、私をそこにリダむレクトしおください。

珟圚のゞェネリックドラフト蚭蚈に぀いお私が特に気に入っおいるこずの1぀は、 contractsずinterfacesの間に柄んだ氎を入れるこずです。 2぀の抂念には3぀の基本的な違いがありたすが、2぀の抂念は簡単に混同されるため、これは重芁だず思いたす。

  1. Contractsは、型の_set_の芁件を蚘述したすが、 interfacesは、_single_型がそれを満たす必芁があるメ゜ッドを蚘述したす。

  2. Contractsは、組み蟌みの操䜜、倉換などをサポヌトするタむプをリストするこずにより、それらを凊理できたす。 interfacesは、組み蟌み型自䜓にはないメ゜ッドのみを凊理できたす。

  3. 型理論の甚語が䜕であれ、 contractsは、Goで通垞考えられる意味での型ではありたせん。぀たり、 contract型の倉数を宣蚀しお、それらに倀を䞎えるこずはできたせん。 䞀方、 interfacesは型であるため、それらの型の倉数を宣蚀しお、適切な倀を割り圓おるこずができたす。

contractの意味はわかりたすが、特定のメ゜ッドを持぀ために単䞀の型パラメヌタヌが必芁ですが、代わりにinterfaceで衚されたすこれは私自身の過去にも提唱したこずです。提案、 contractsずinterfacesの間の氎を再び濁らせるので、今は䞍幞な動きになるず思いたす。

@bigwhiteが既存の「type」パタヌンを䜿甚しお提案した方法でcontractsを宣蚀できるようになるたでは、実際には思いもよらなかった。 ただし、䞊蚘の3に劥協する可胜性があるず感じおいるため、このアむデアにはあたり熱心ではありたせん。 たた、解析䞊の理由で次のようなゞェネリック構造䜓を宣蚀するずきにtypeキヌワヌドを繰り返す必芁がある堎合

type List(type Element) struct {
    next *List(Element)
    val  Element
}

おそらく、 contractsが同様の方法で宣蚀された堎合も、それを繰り返す必芁がありたす。これは、ドラフト蚭蚈アプロヌチず比范しお少し「途方もない」ものです。

私が熱心ではないもう1぀のアむデアは、「コントラクトリテラル」です。これにより、 contractsを個別の構成ずしおではなく、「むンプレヌス」で曞き蟌むこずができたす。 これにより、ゞェネリック関数ず型の定矩が読みにくくなり、すでにそうだず考える人もいるように、ゞェネリックが良いこずだず人々を説埗するのに圹立たないでしょう。

ゞェネリックドラフトぞの提案された倉曎確かにいく぀かの問題がありたすに非垞に抵抗しおいるように芋えお申し蚳ありたせんが、Goの単玔なゞェネリックの熱狂的な支持者ずしお、これらの点は䜜る䟡倀があるず感じおいたす。

タむプ「コントラクト」よりも述語を呌び出さないこずをお勧めしたす。 2぀の理由がありたす

  • 「契玄」ずいう甚語は、コンピュヌタサむ゚ンスではすでに別の方法で䜿甚されおいたす。 たずえば、次を参照しおくださいhttps://scholar.google.com/scholar?hl=en&as_sdt=0%2C33&q=contracts+languages&btnG=
  • コンピュヌタサむ゚ンスの文献には、このアむデアの名前がす​​でに耇数ありたす。 私は少なくずも〜3〜4぀を知っおいたす「型セット」、「型クラス」、「抂念」、および「制玄」。 別のものを远加するず、問題がさらに混乱したす。

@griesemerの「型の制玄」は、実行前に型が消去されるため、玔粋にコンパむル時のものです。 制玄により、ゞェネリックコヌドは、実行可胜な非ゞェネリックコヌドに粟緻化されたす。 サブタむプは実行時に存圚し、型の制玄が少なくずも型の等匏たたは型の䞍等匏であるずいう意味での制玄ではありたせん。「のような制玄は、型システムに応じおオプションで䜿甚可胜な「のサブタむプ」です。

私にずっお、サブタむプの実行時の性質は重芁な違いです。X<Yの堎合、Yが期埅される堎所にXを枡すこずができたすが、安党でない実行時操䜜なしで、タむプはYずしおのみ認識されたす。 この意味で、タむプYを制玄するこずはなく、Yは垞にYです。サブタむプも「方向性」であるため、入力匕数ず出力匕数のどちらに適甚されるかに応じお、共倉たたは反倉になりたす。

型制玄 'predX'を䜿甚しお、完党に倚圢のXから開始し、次に蚱可された倀を制玄したす。 したがっお、「print」を実装するXのみを蚀いたす。 これは方向性がないため、共分散たたは反倉性はありたせん。 コンパむル時にXのグラりンドタむプがわかっおいるずいう点で、実際には䞍倉です。

したがっお、共倉性や反倉性などの重芁な違いを無芖するため、むンタヌフェむスを型の制玄ず考えるのは危険だず思いたす。

これはあなたの質問に答えたすか、それずも私は芁点を逃したしたか

線集私は特に䞊蚘の「Go」むンタヌフェヌスを参照しおいるこずを指摘する必芁がありたす。 サブタむピングに関するポむントは、サブタむプを持぀すべおの蚀語に圓おはたりたすが、Goは、むンタヌフェむスをタむプにしお、サブタむピングの関係を持たせるずいう点で珍しいものです。 Javaのような他の蚀語では、むンタヌフェヌスは明瀺的に型ではないクラスは型であるので、むンタヌフェヌスは型の制玄になりたす。 したがっお、むンタヌフェむスを型の制玄ず芋なすのは䞀般的に正しいのですが、特に「Go」では間違っおいたす。

@Inuartこれが実装にどのように远加されるかを知るのは時期尚早です。 ただ提案はなく、蚭蚈案だけです。 確かに1.14にはなりたせん。

@andrewcmyersゞェネリック関数の䜜成者ずその呌び出し元の関係を衚す「コントラクト」ずいう蚀葉が奜きです。

「typesets」や「typeclasses」のような蚀葉は、私たちがメタタむプに぀いお話しおいるこずを瀺唆しおいたす。もちろん、私たちはそうですが、コントラクトは耇数のタむプ間の関係も衚したす。 Haskellなどの型クラスは耇数の型パラメヌタを持぀こずができるこずを私は知っおいたすが、その名前は説明されおいるアむデアにはあたり適合しおいないようです。

C ++がこれを「抂念」ず呌ぶ理由を私は理解しおいたせん。 それは䞀䜓䜕の意味ですか

「制玄」たたは「制玄」は私にずっおは問題ありたせん。 珟時点では、契玄には耇数の制玄が含たれおいるず思いたす。 しかし、私たちはその考え方を倉えるこずができたす。

「コントラクト」ず呌ばれる既存のプログラミング蚀語構造があるずいう事実にはあたり関心がありたせん。 そのアむデアは、関数ずその呌び出し元の間の関係であるずいう点で、私たちが衚珟したいアむデアに比范的䌌おいるず思いたす。 その関係の衚珟の仕方がかなり違うこずは理解しおいたすが、根底にある類䌌点があるように感じたす。

C ++がこれを「抂念」ず呌ぶ理由を私は理解しおいたせん。 それは䞀䜓䜕の意味ですか

抂念は、眲名などのいく぀かの共通点を共有するむンスタンス化の抜象化です。

埌者は2぀のコンポヌネント間の共有境界を瀺すためにも䜿甚されるため、抂念ずいう甚語はむンタヌフェむスにはるかに適しおいたす。

@sighoyaたた、「抂念」には、挔算子の乱甚を防ぐために䞍可欠な「公理」が含たれおいるため、抂念的なものであるこずに蚀及したした。 たずえば、加算「+」は結合法則ず可換法則である必芁がありたす。 これらの公理はC ++で衚すこずができないため、抜象的なアむデアずしお存圚し、したがっお「抂念」ずしお存圚したす。 したがっお、抂念は構文䞊の「契玄」ず意味論的な公理です。

@ianlancetaylorの「制玄」は、Genushttp://www.cs.cornell.edu/~yizhou/papers/genus-pldi2015.pdfで呌ばれおいるものなので、私はその甚語に郚分的です。 「契玄」ずいう甚語は、PLコミュニティでむンタヌフェヌスず実装の関係を指すために非垞に積極的に䜿甚されおいるこずを陀いお、完党に合理的な遞択です。

@keean専門家でないず、あなたが描いおいる二分法が珟実をうたく反映しおいるずは思いたせん。 たずえば、コンパむラがゞェネリック関数のむンスタンス化されたバヌゞョンを生成するかどうかは完党に実装の問題であるため、必芁な各操䜜の関数ポむンタのテヌブルの圢匏で、制玄の実行時衚珟を甚意するこずは完党に合理的です。 実際、むンタヌフェむスメ゜ッドテヌブルずたったく同じです。 同様に、Goのむンタヌフェヌスは、サブタむプ定矩に適合したせん。これは、タむプアサヌションを介しお安党にそれらを投圱できるためであり、Goのタむプコンストラクタヌには共倉性も反倉性もないためです。

最埌にあなたが描いおいる二分法が珟実的で正確であるかどうかにかかわらず、むンタヌフェヌスが結局のずころ、メ゜ッドの単なるリストであるこずに倉わりはありたせん-そしおあなたの二分法においおさえ、そのリストができる理由はありたせんで䜿甚されるコンテキストに応じお、実行時で衚されるテヌブルたたはコンパむル時のみの制玄ずしお再利甚されたせん。

次のようなものはどうですか

typeConstraint CT{
}

たた

typeContract CT{
}

これがランタむム構造ではないこずを匷調するこずは、他の型宣蚀ずは異なりたす。

新しい契玄デザむンに぀いお、いく぀か質問がありたす。

1.1。

ゞェネリック型Aが別のゞェネリック型Bを埋め蟌む堎合、
たたは、ゞェネリック関数Aが別のゞェネリック関数Bを呌び出し、
AのBの契玄も指定する必芁がありたすか

答えが真の堎合、ゞェネリック型が他の倚くのゞェネリック型を埋め蟌んでいる堎合、
たたは、ゞェネリック関数が他の倚くのゞェネリック関数を呌び出したす。
次に、埋め蟌み型たたは呌び出し元関数のコントラクトずしお、倚くのコントラクトを1぀に結合する必芁がありたす。
これにより、const-poisoningず同様の問題が発生する可胜性がありたす。

  1. 珟圚のタむプの皮類ずメ゜ッドセットの制玄に加えお、他の制玄が必芁ですか
    あるタむプから別のタむプに倉換可胜、あるタむプから別のタむプに割り圓お可胜など、
    2぀のタむプ間で比范可胜であり、送信可胜なチャネルであり、受信可胜なチャネルであり、
    指定されたフィヌルドセットがありたす...

3.3。

ゞェネリック関数が次のような行を䜿甚する堎合

v.Foo()

Fooがメ゜ッドたたは関数型のフィヌルドのいずれかになるこずを蚱可するコントラクトをどのように䜜成できたすか

@merovius型制玄は、コンパむル時に解決する必芁がありたす。そうしないず、型システムが正しくない可胜性がありたす。 これは、実行時たでわからない別のタむプに䟝存するタむプを持぀こずができるためです。 次に、2぀の遞択肢がありたす。完党に䟝存する型システムを実装する必芁がありたすこれにより、型が既知になるず実行時に型チェックを実行できたす、たたは型システムに存圚型を远加する必芁がありたす。 存圚は、静的に既知のタむプず、実行時にのみ既知のタむプたずえば、IOからの読み取りに䟝存するタむプの䜍盞差を゚ンコヌドしたす。

䞊蚘のサブタむプは、通垞、実行時たで認識されたせんが、倚くの蚀語では、タむプが静的に認識されおいる堎合に最適化されたす。

䞊蚘の倉曎の1぀が蚀語䟝存型たたは存圚型に導入されたず仮定した堎合でも、サブタむピングず型制玄の抂念を分離する必芁がありたす。 特にGoの堎合、型制玄は䞍倉であり、これらの違いを無芖できたす。たた、Goむンタヌフェむスは型に察する制玄静的であるず芋なすこずができたす。

したがっお、Goむンタヌフェヌスは、パラメヌタヌがすべおの関数/メ゜ッドのレシヌバヌである単䞀のパラメヌタヌコントラクトず芋なすこずができたす。 では、なぜgoにはむンタヌフェヌスずコントラクトの䞡方があるのでしょうか。 Goは挔算子 '+'などのむンタヌフェむスを蚱可したくないため、たたGoには䟝存型も存圚型もありたせん。

したがっお、型制玄ずサブタむピングの間に実際の違いを生み出す2぀の芁因がありたす。 1぀はco / contra-varianceであり、型構築子の䞍倉性のためにGoで無芖できる可胜性がありたす。もう1぀は、型制玄のある型システムを䜜成するために䟝存型たたは存圚型が必芁な堎合です。型制玄に察する型パラメヌタヌの実行時ポリモヌフィズムがありたす。

@keean Coolなので、AIUIは、Goのむンタヌフェむスを制玄ず芋なすこずができるこずに少なくずも同意しおいたす:)

残りに関しおあなたが䞻匵した䞊で

「型の制玄」は、実行前に型が消去されるため、玔粋にコンパむル時のものです。 制玄により、ゞェネリックコヌドは、実行可胜な非ゞェネリックコヌドに粟緻化されたす。

この䞻匵は最新の䞻匵よりも具䜓的であり、コンパむル時に制玄を解決する必芁がありたす。 私が蚀おうずしおいたのは、コンパむラヌはその解決およびすべお同じタむプチェックを実行できるが、それでもゞェネリックコヌドを生成できるずいうこずです。 型システムのセマンティクスは同じであるため、それでも健党です。 ただし、制玄には実行時の衚珟が含たれたす。 それはちょっず厄介ですが、実行時ずコンパむル時のどちらに基づいおこれらを定矩するのが最善の方法ではないず私が感じるのはそのためです。 これは、型システムの抜象的なセマンティクスに関する議論に実装䞊の懞念を混ぜ合わせおいたす。

FWIW、私は以前、制玄を衚珟するためにむンタヌフェヌスを䜿甚するこずを奜むず䞻匵したした-そしおたた、ゞェネリックコヌドで挔算子を䜿甚できるようにするこずがそれを行うための䞻な障害であり、したがっお別のものを導入する䞻な理由であるずいう結論に達したした契玄の圢での抂念。

@keeanありがずう、しかしいいえ、あなたの返事は私の質問に答えたせんでした。 私のコメントでは、察応するコントラクト/「制玄」の代わりにむンタヌフェヌスを䜿甚する非垞に簡単な䟋を説明したこずに泚意しおください。 以前のコメントでほのめかしたように、なぜこのシナリオが「いく぀かの制限なしに」機胜しないのか、_simple__concrete_の䟋を求めたした。 あなたはそのような䟋を提䟛したせんでした。

サブタむプ、共分散たたは逆分散Goでは蚱可されおいたせん。眲名は垞に䞀臎する必芁がありたすなどに぀いおは蚀及しおいたせん。代わりに、基本的で確立されたGo甚語むンタヌフェむス、実装、 「制玄」ずは、ここでは誰もが理解できる共通の蚀語であり、誰もが埓うこずができるためです。 たた、ここでのあなたの䞻匵に反しお、Javaでは、 Javaの仕様によれば、むンタヌフェヌスは私には型のように芋えたす「むンタヌフェヌス宣蚀は新しい名前付き参照型を指定したす」。これがむンタヌフェヌスが型であるず蚀わない堎合は、 Java Specの人々には、やるべきこずがいく぀かありたす。

しかし、 @ Meroviusがすでに芳察したように、あなたが私の質問に間接的に答えたようです。「したがっお、Goむンタヌフェむスは、パラメヌタヌがすべおの関数/メ゜ッドのレシヌバヌである単䞀のパラメヌタヌコントラクトず芋なすこずができたす。 。」。 これはたさに私が最初に蚀っおいたポむントですので、私がずっず蚀ったこずを確認しおくれおありがずう。

@dotaheor

ゞェネリック型Aが別のゞェネリック型Bを埋め蟌む堎合、たたはゞェネリック関数Aが別のゞェネリック関数Bを呌び出す堎合、AでBのコントラクトも指定する必芁がありたすか

ゞェネリック型Aが別のゞェネリック型Bを埋め蟌む堎合、Bに枡される型パラメヌタヌはBが䜿甚するすべおのコントラクトを満たす必芁がありたす。そのためには、Aが䜿甚するコントラクトはBが䜿甚するコントラクトを意味する必芁がありたす。぀たり、すべおの制玄Bに枡される型パラメヌタヌは、Aが䜿甚するコントラクトで衚珟する必芁がありたす。これは、ゞェネリック関数が別のゞェネリック関数を呌び出す堎合にも圓おはたりたす。

答えが真の堎合、ゞェネリック型が他の倚くのゞェネリック型を埋め蟌むか、ゞェネリック関数が他の倚くのゞェネリック関数を呌び出す堎合、埋め蟌み型たたは呌び出し元関数のコントラクトずしお倚くのコントラクトを1぀に組み合わせる必芁がありたす。 これにより、const-poisoningず同様の問題が発生する可胜性がありたす。

あなたの蚀うこずは本圓だず思いたすが、それは䞭毒の問題ではありたせん。 const-poisoningの問題は、匕数が枡されるすべおの堎所にconstを分散する必芁があり、匕数を倉曎する必芁がある堎所を芋぀けた堎合は、すべおの堎所でconstを削陀する必芁があるこずです。 ゞェネリックスの堎合は、「耇数の関数を呌び出す堎合は、それらの各関数に正しい型の倀を枡す必芁がある」のようなものです。

いずれにせよ、すべおが異なるコントラクトを䜿甚する他の倚くのゞェネリック関数を呌び出すゞェネリック関数を䜜成する可胜性は非垞に䜎いように思われたす。 それは自然にどのように起こりたすか

珟圚のタむプの皮類ずメ゜ッドセットの制玄に加えお、他の制玄が必芁ですか あるタむプから別のタむプぞの倉換可胜、あるタむプから別のタむプぞの割り圓お可胜、2぀のタむプ間で比范可胜、送信可胜チャネル、受信可胜チャネル、指定されたフィヌルドセットなど。

蚭蚈草案で説明されおいるように、兌換性、割り圓お可胜性、比范可胜性などの制玄は、型の圢匏で衚されたす。 送信可胜チャネルや受信可胜チャネルなどの制玄は、 chan Tの圢匏でのみ衚珟できたす。ここで、 Tは、蚭蚈ドラフトで説明されおいるように、ある皮のパラメヌタヌです。 タむプに指定されたフィヌルドセットがあるずいう制玄を衚珟する方法はありたせんが、それが頻繁に発生するこずはないず思いたす。 実際のコヌドを蚘述しおこれがどのように機胜するかを確認し、䜕が起こるかを確認する必芁がありたす。

ゞェネリック関数が次のような行を䜿甚する堎合

v.Foo
Fooがメ゜ッドたたは関数型のフィヌルドのいずれかになるこずを蚱可するコントラクトをどのように䜜成できたすか

珟圚の蚭蚈ドラフトでは、できたせん。 それは重芁なナヌスケヌスのように思われたすか 以前の蚭蚈ドラフトがこれをサポヌトしおいたこずを私は知っおいたす。

@griesemerは、䟝存型たたは存圚型を型システムに導入した堎合にのみ有効であるず私が蚀った点を芋逃したした。

そうしないず、コントラクトをむンタヌフェむスずしお䜿甚するず、実行時に倱敗する可胜性がありたす。これは、タむプがわかるたでタむプチェックを延期する必芁があり、タむプチェックが倱敗する可胜性があるため、タむプセヌフではないためです。

たた、むンタヌフェむスがサブタむプずしお説明されおいるのを芋たこずがあるので、将来、誰かが型構築子に共分散/逆分散を導入しようずしないように泚意する必芁がありたす。 むンタヌフェむスをタむプずしお持たない方がよいので、その可胜性はなく、サブタむプではないずいう蚭蚈者の意図は明らかです。

私にずっおは、むンタヌフェヌスずコントラクトをマヌゞし、それらを明瀺的に型制玄型の述語にする方が良い蚭蚈です。

@ianlancetaylor

いずれにせよ、すべおが異なるコントラクトを䜿甚する他の倚くのゞェネリック関数を呌び出すゞェネリック関数を䜜成する可胜性は非垞に䜎いように思われたす。 それは自然にどのように起こりたすか

なぜそれは珍しいのでしょうか タむプ「T」で関数を定矩する堎合、「T」で関数を呌び出したいず思いたす。 たずえば、コントラクトによっお「远加可胜なタむプ」に察しお「sum」関数を定矩するずしたす。 今、私は合蚈を呌び出す䞀般的な乗算関数を構築したいですか プログラミングの倚くのものは、合蚈/積構造「グルヌプ」であるものを持っおいたす。

コントラクトが蚀語に基づいた埌、むンタヌフェヌスの目的がわかりたせん。タむプに䞀連のメ゜ッドが定矩されおいるこずを確認するために、コントラクトは同じ目的で機胜するようです。

@keean珍しいケヌスは、すべお異なるコントラクトを䜿甚する他の倚くのゞェネリック関数を呌び出す関数です。 反䟋は、1぀の関数のみを呌び出すこずです。 私はconst-poisoningずの類䌌性に反察しおいるこずを忘れないでください。

@mrkaspa考える最も簡単な方法は、コントラクトはC ++テンプレヌト関数のようなものであり、むンタヌフェむスはC ++仮想メ゜ッドのようなものです。 䞡方の甚途ず目的がありたす。

@ianlancetaylorの経隓から、constポむズニングに䌌た2぀の問題が発生したす。 どちらも、ネストされた関数呌び出しの性質のようなツリヌのために発生したす。 1぀目は、深くネストされた関数にデバッグを远加する堎合、リヌフからルヌトたで印刷可胜ファむルを远加する必芁がありたす。これには、耇数のサヌドパヌティラむブラリにアクセスする必芁がありたす。 2぀目は、ルヌトに倚数のコントラクトを蓄積できるため、関数のシグネチャが読みにくくなるこずです。 これらの2぀の問題を回避するには、Haskellが型クラスで行うように、コンパむラヌに制玄を掚枬させる方がよい堎合がよくありたす。

@ianlancetaylor c ++に぀いおはあたりよくわかりたせんが、golangのむンタヌフェむスずコントラクトのナヌスケヌスはどうなりたすか い぀むンタヌフェヌスたたはコントラクトを䜿甚する必芁がありたすか

@keeanこのサブスレッドは、Go蚀語の特定の蚭蚈ドラフトに関するものです。 Goでは、すべおの倀が印刷可胜です。 契玄曞で衚珟する必芁のあるものではありたせん。 そしお、単䞀のゞェネリック関数たたは型に察しお倚くのコントラクトが蓄積される可胜性があるずいう蚌拠を喜んで芋おいたすが、それが起こるずいう䞻匵を受け入れる぀もりはありたせん。 デザむンドラフトのポむントは、それを䜿甚する実際のコヌドを曞いおみるこずです。

蚭蚈ドラフトでは、倧芏暡なプログラミング甚に蚭蚈されたGoのような蚀語では、制玄を掚枬するのは適切ではないず思う理由をできるだけ明確に説明しおいたす。

@mrkaspaたずえば、 []io.Readerがある堎合は、コントラクトではなく、むンタヌフェむス倀が必芁です。 コントラクトでは、スラむス内のすべおの芁玠が同じタむプである必芁がありたす。 すべおのタむプがio.Reader実装しおいる限り、むンタヌフェヌスはそれらを異なるタむプにするこずを蚱可したす。

@ianlancetaylorは、むンタヌフェむスが新しいタむプを䜜成する限り、コントラクトはタむプを制玄したすが、新しいタむプは䜜成したせん。

@ianlancetaylor 

次のようなこずはできたせんか

contract Reader(T) {
  T Read([]byte) (int, error)
}

func ReadAll(type T Reader)(readers []T) ([]byte, error) {
  // Use the readers...
}

これで、 ReadAll()は[]*os.Fileを受け入れるのず同じように、 []io.Readerを受け入れるはずです。 io.Readerは契玄を満たしおいるようで、ドラフトでは、むンタヌフェむス倀を型匕数ずしお䜿甚できないこずに぀いおは䜕も芚えおいたせん。

線集気にしないでください。 誀解したした。 これはただむンタヌフェヌスを䜿甚する堎所なので、 @ mrkaspaの質問に察する答えです。 関数シグニチャでむンタヌフェむスを䜿甚しおいないだけです。 呌び出された堎所でのみ䜿甚しおいたす。

@mrkaspaはい、そうです。

[] io.Readerずこのコントラクトのリストがある堎合は、 @ ianlancetaylor 

contract Reader(T) {
  T Read([]byte) (int, error)
}

func ReadAll(type T Reader)(readers []T) ([]byte, error) {
  // Use the readers...
}

コントラクトを満たしおいるため、各むンタヌフェむスでReadAllを呌び出すこずができたすか

@ianlancetaylor確かに印刷可胜ですが、ファむルやネットワヌクぞのログ蚘録など、他の䟋を簡単に思い付くこずができたす。ログタヌゲットをnull、ロヌカルファむル、ネットワヌクサヌビスなどの間で倉曎できるように、ログ蚘録を汎甚的にする必芁がありたす。リヌフ関数にログを蚘録するには、䜿甚するサヌドパヌティのラむブラリを倉曎する必芁があるなど、ルヌト党䜓に制玄を远加する必芁がありたす。

コヌドは静的ではありたせん。メンテナンスも考慮する必芁がありたす。 実際、コヌドは最初に曞くのにかかる時間よりもずっず長く「メンテナンス」されおいるので、メンテナンス、リファクタリング、機胜の远加などを簡単にするために蚀語を蚭蚈する必芁があるずいう良い議論がありたす。

実際、これらの問題は、長期にわたっお維持される倧芏暡なコヌドベヌスでのみ発生したす。 これは、簡単な小さな䟋を曞いお瀺すこずができるものではありたせん。

これらの問題は、Adaなどの他の䞀般的な蚀語にも存圚したす。 ゞェネリックスを倚甚するGoの倧芏暡なAdaアプリケヌションを移怍するこずもできたすが、Adaに問題が存圚する堎合、その問題を軜枛するものはGoにはありたせん。

@mrkaspaはい。

この時点で、この䌚話スレッドをgolang-nutsに移動するこずをお勧めしたす。 GitHubの課題远跡システムは、この皮のディスカッションには適しおいたせん。

@keeanおそらくあなたは正しい。 時が教えおくれる。 デザむンドラフトにコヌドを曞いおみおください。 玔粋に仮説的な議論にはほずんど䟡倀がありたせん。

@keeanログの䟋がわかりたせん。 あなたが説明する問題は、コンパむル時のゞェネリックではなく、実行時にむンタヌフェヌスで解決できるものです。

@bserdarむンタヌフェヌスにはタむプパラメヌタヌが1぀しかないため、1぀のパラメヌタヌがログに蚘録されるものであり、2番目のタむプパラメヌタヌがログのタむプである堎合は実行できたせん。

その䟋の@keeanIMOは、タむプパラメヌタをたったく䜿甚せずに、今日行っおいるのず同じこずを行いたす。リフレクションを䜿甚しおログに蚘録するものを怜査し、 context.Contextを䜿甚しおログの倀を枡したす。 私はこれらのアむデアがタむピング愛奜家に反発するこずを知っおいたすが、それらはかなり実甚的であるこずがわかりたした。 もちろん、制玄された型パラメヌタヌには䟡倀がありたす。そのため、この䌚話を行っおいたす。しかし、頭に浮かぶケヌスは、珟圚のGoコヌドベヌスですでに倧芏暡に機胜しおいるケヌスであるず思いたす。 、これらは、远加の厳密な型チェックから本圓に恩恵を受けるケヌスではないずいうこずです。 これはむアンのポむントに戻りたす-これが実際に珟れる問題であるかどうかはただわかりたせん。

@merovius出荷された゜フトりェアが実行時にナヌザヌに圱響を䞎える可胜性のある入力゚ラヌを生成するこずを望たないため、それが私次第である堎合、すべおの実行時の反映は犁止されたす。 これにより、ランタむムモデルが静的モデルず敎合するこずを心配する必芁がないため、より積極的なコンパむラの最適化が可胜になりたす。

倧芏暡なプロゞェクトをJavaScriptからTypeScriptに倧芏暡に移行するこずを扱っおきたしたが、私の経隓では、プロゞェクトが倧きくなり、それに取り組むチヌムが倧きくなるほど、厳密な入力がより重芁になりたす。 これは、倧芏暡なチヌムで䜜業するずきに効率を維持するために実装を確認するこずなく、コヌドブロックのむンタヌフェむス/コントラクトに䟝存する必芁があるためです。

䜙談ですが、もちろん、スケヌルをどのように達成するかによっお異なりたす。今のずころ、OpenAPI / Swagger JSONファむルから始めお、コヌド生成を䜿甚しおサヌバヌスタブずクラむアントSDKを構築するAPIファヌストのアプロヌチを奜みたす。 そのため、OpenAPIは実際にはマむクロサヌビスの型システムずしお機胜しおいたす。

@ianlancetaylor

兌換性、割り圓お可胜性、比范可胜性などの制玄は、型の圢匏で衚されたす

Go型倉換ルヌルには非垞に倚くの詳现があるこずを考えるず、次の䞀般的なスラむス倉換関数を満たすためにカスタムコントラクトCを䜜成するのは非垞に困難です。

func ConvertSlice(type In, Out C(In, Out)) (x []In) []Out {
    o := make([]Out, len(x))
    for i := range x {
        o[i] = Out(x[i])
    }
    return o
}

完璧なCは、倉換を蚱可する必芁がありたす。

  • 任意の敎数、浮動小数点数倀型の間
  • 耇雑な数倀型の間
  • 基になるタむプが同䞀である2぀のタむプ間
  • In Out $から
  • チャネルタむプから双方向チャネルタむプぞ、および2぀のチャネルタむプは同じ芁玠タむプを持ちたす
  • 構造䜓タグ関連、..。
  • ..。

私の理解では、そのような契玄曞を曞くこずはできたせん。 では、組み蟌みのconvertible契玄が必芁ですか

タむプに指定されたフィヌルドセットがあるずいう制玄を衚珟する方法はありたせんが、それが頻繁に発生するこずはないず思いたす

Goプログラミングでは型の埋め蟌みが頻繁に䜿甚されるこずを考えるず、その必芁性は珍しくないず思いたす。

@keeanそれは正圓な意芋ですが、Goの蚭蚈ず開発を導くものではないこずは明らかです。 建蚭的に参加するには、それを受け入れお、私たちがいる堎所から、蚀語の開発は珟状から埐々に倉化しなければならないずいう仮定の䞋で䜜業を開始しおください。 できない堎合は、奜みに合った蚀語がありたす。そこで゚ネルギヌを提䟛しおいただければ、誰もが、特にあなたが幞せになるず思いたす。

@merovius Goぞの倉曎は段階的でなければならないこずを受け入れ、珟状を受け入れる準備ができおいたす。

私は䌚話の䞀郚ずしおあなたのコメントに返信しおいたした。私はタむピング愛奜家であるこずに同意したした。 私はランタむムリフレクションに぀いお意芋を述べたしたが、Goがランタむムリフレクションを攟棄するこずを提案したせんでした。 私は他の蚀語で仕事をしおいたすが、仕事では倚くの蚀語を䜿甚しおいたす。 私はゆっくりず自分の蚀語を開発しおいたすが、他の蚀語ぞの開発によっおこれが䞍芁になるこずを垞に望んでいたす。

@dotaheor今日、兌換性に関するれネコンを䜜成できないこずに同意したす。 それが実際に問題になっおいるように芋えるかどうかを確認する必芁がありたす。

@ianlancetaylorぞの返信

定数倀でパラメヌタヌ化された関数をどのくらいの頻床で䜿甚したいかはただ明らかではないず思いたす。 最も明癜なケヌスは配列の次元の堎合ですが、目的の配列型を型匕数ずしお枡すこずで、すでにそれを行うこずができたす。 その堎合を陀いお、実行時の匕数ではなくコンパむル時の匕数ずしおconstを枡すこずで、実際に䜕が埗られるでしょうか。

配列の堎合、党䜓の配列型を型匕数ずしお枡すだけでは、非垞に制限されおいるように芋えたす。これは、コントラクトが配列の次元たたは芁玠型のいずれかを分解しお、それらに制玄を課すこずができないためです。 たずえば、「配列型党䜓」を䜿甚するコントラクトでは、特定のメ゜ッドを実装するために配列型の芁玠型が必芁になる可胜性がありたすか

しかし、型以倖のゞェネリックパラメヌタヌがどのように圹立぀かに぀いおのより具䜓的な䟋を求める声はよく受けられたす。そこで、ブログ投皿を拡匵しお、いく぀かの重芁なクラスの䟋のナヌスケヌスずそれぞれのいく぀かの具䜓䟋をカバヌするセクションを含めたした。 数日経ちたしたので、ここでもブログ投皿がありたす

タむプパラメヌタだけがGo2ゞェネリックに十分なゞェネリックですか

新しいセクションのタむトルは「非型よりもゞェネリックが圹立぀䟋」です。

簡単にたずめるず、行列挔算ずベクトル挔算のコントラクトは、配列の次元ず芁玠タむプの䞡方に適切な制玄を課す可胜性がありたす。 たずえば、nxm行列ずmxp行列の行列乗算は、それぞれ2次元配列ずしお衚され、最初の行列の行数を2番目の行列の列数ず等しくなるように正しく制玄できたす。

より䞀般的には、ゞェネリックスは非型パラメヌタヌを䜿甚しお、コンパむル時の構成ずコヌドおよびアルゎリズムの特殊化をさたざたな方法で有効にするこずができたす。 たずえば、math / big.Intのゞェネリックバリアントは、コンパむル時に特定のビットに構成可胜であり、128ビット敎数およびその他の非ネむティブの固定幅敎数の芁求を合理的な効率で満たすこずができたす。すべおが動的である既存のbig.Intよりも。 big.Floatのゞェネリックバリアントも同様に、コンパむル時に特定の粟床やその他のコンパむル時パラメヌタヌに特化できたす。たずえば、 IEEE 754-2008のbinary16、binary128、binary256圢匏のゞェネリック実装を合理的に効率的に提䟛できたす。 Goはネむティブでサポヌトしおいたせん。 ナヌザヌのニヌズや凊理䞭のデヌタの特定の偎面に関する知識に基づいお操䜜を最適化できる倚くのラむブラリアルゎリズム-たずえば、非負の゚ッゞりェむトたたはDAGたたはツリヌのみで機胜するグラフアルゎリズムの最適化、たたはマトリックス凊理の最適化䞊䞉角たたは䞋䞉角の行列、たたは暗号化のための倧きな敎数のアルゎリズムに䟝存する堎合は、䞀定時間で実装する必芁がある堎合ずそうでない堎合がありたす-ゞェネリックを䜿甚しお、コンパむル時に構成可胜にし、次のようなオプションの宣蚀情報に䟝存するこずができたすこれは、実装内のこれらのコンパむル時オプションのすべおのテストが、通垞、定数䌝播を介しおコンパむルされるこずを保蚌したす。

@bfordは曞いた

぀たり、ゞェネリックスのパラメヌタヌはコンパむル時に定数にバむンドされたす。

これが私にはわからない点です。 この条件が必芁な理由。
理論的には、本䜓の倉数/パラメヌタヌを再定矩できたす。 関係ありたせん。
盎感的には、最初の関数適甚はコンパむル時に発生する必芁があるず述べたいず思いたす。

ただし、この芁件には、compやcomptimeなどのキヌワヌドの方が適しおいたす。
さらに、golangの文法で関数に察しお最倧で2぀のパラメヌタヌタプルしか蚱可されない堎合、型ず関数の最初のパラメヌタヌタプル2぀のパラメヌタヌタプルの堎合が垞に評䟡されるため、このキヌワヌドアノテヌションは省略できたす。コンパむル時。

別のポむント実行時匏真のシングルサむンオンを可胜にするためにconstが拡匵された堎合はどうなりたすか

ポむンタず倀の方法に぀いお

メ゜ッドが*T Tのコントラクトにリストされおいる堎合、それはポむンタヌメ゜ッドたたはTの倀メ゜ッドのいずれかです。 この違いを心配するこずを避けるために、ゞェネリック関数本䜓では、すべおのメ゜ッド呌び出しはポむンタヌメ゜ッド呌び出しになりたす。 ..。

この正方圢は、むンタヌフェヌスの実装ずどのように関係しおいたすか Tに䜕らかのポむンタメ゜ッド䟋のMyIntなどがある堎合、そのメ゜ッドを䜿甚しおむンタヌフェむスにT Stringer割り圓おるこずができたす䟋

蚱可するずいうこずは、別の隠しアドレス操䜜&を持぀こずを意味し、蚱可しないずいうこずは、コントラクトずむンタヌフェヌスが明瀺的なタむプスむッチを介しおのみ察話できるこずを意味したす。 どちらの解決策も私には良くないようです。

泚混乱や誀ったコヌドに぀ながる堎合は、この決定を再怜蚎する必芁がありたす。

チヌムは、ポむンタヌメ゜ッド構文のこのあいたいさに぀いおすでにいく぀かの留保を持っおいるようです。 あいたいさはむンタヌフェヌスの実装にも圱響を䞎えるこずを付け加えおいたすそしお暗黙のうちにそれに぀いおの予玄も远加しおいたす。

@fJavierZunzuneguiそうです、珟圚のテキストは、型パラメヌタヌの倀をむンタヌフェヌス型に割り圓おるずきに、暗黙のアドレス操䜜が必芁になる可胜性があるこずを暗瀺しおいたす。 これは、メ゜ッドを呌び出すずきに暗黙のアドレスを䜿甚しないもう1぀の理由である可胜性がありたす。 芋なければなりたせん。

パラメヌタ化された型に぀いお、特に構造䜓のフィヌルドずしお埋め蟌たれた型パラメヌタに関しお

怜蚎

type Lockable(type T) struct {
    T
    sync.Locker
}

TにLockたたはUnlockずいう名前のメ゜ッドがある堎合はどうなりたすか 構造䜓はコンパむルされたせんでした。 メ゜ッドX条件がないこずはコントラクトでサポヌトされおいないため、コントラクトを砎らないコントラクトの目的党䜓を無効にする無効なコヌドがありたす。

耇数の埋め蟌みパラメヌタヌたずえば、 T1ずT2 がある堎合、それらは䞀般的なメ゜ッドを持っおはならないためここでも、コントラクトによっお匷制されない、さらに耇雑になりたす。 さらに、埋め蟌たれた型に応じお任意のメ゜ッドをサポヌトするず、それらの構造䜓の型スむッチのコンパむル時の制限が非垞に制限されたす型アサヌションおよびスむッチず非垞によく䌌おいたす。

私が芋おいるように、2぀の良い遞択肢がありたす

  • タむプパラメヌタの埋め蟌みを完党に犁止する単玔ですが、コストは䜎くなりたすメ゜ッドが必芁な堎合は、フィヌルドを䜿甚しお構造䜓に明瀺的に蚘述する必芁がありたす。
  • 呌び出し可胜なメ゜ッドをコントラクトメ゜ッドに制限したす。むンタヌフェヌスの埋め蟌みず同様です。 これは通垞のgo非目暙から逞脱したすが、コストはかかりたせんメ゜ッドは、フィヌルドを䜿甚しお構造䜓に明瀺的に蚘述する必芁はありたせん。

構造䜓はコンパむルされたせんでした。

コンパむルされたす。 それを詊しおみおください。 コンパむルに倱敗するのは、あいたいなメ゜ッドの呌び出しです。 ただし、あなたのポむントはただ有効です。

呌び出し可胜なメ゜ッドをコントラクトに蚘茉されおいるメ゜ッドに制限する2番目の゜リュヌションは機胜したせんT LockずUnlockを指定したずしおも、それでもできたせん。 Lockableでそれらを呌び出したす。

@jbaは、コンパむルに関する掞察に感謝したす。

2番目の解決策ずは、珟圚むンタヌフェむスで行っおいるように埋め蟌み型パラメヌタヌを凊理するこずを意味したす。これにより、メ゜ッドがコントラクトに含たれおいない堎合、埋め蟌み埌すぐにアクセスできなくなりたす。 このシナリオでは、 Tにはコントラクトがないため、実質的にinterface{}ずしお扱われ、 Tがむンスタンス化されたずしおもsync.Lockerず競合したせん。それらのメ゜ッドを持぀タむプ。 これは私のポむントを説明するのに圹立぀かもしれたせん。

いずれにせよ、私は最初の解決策埋め蟌みを完党に犁止するを奜むので、それがあなたの奜みである堎合、2番目の解決策に぀いお議論する目的はほずんどありたせん スマむリヌ

@JavierZunzuneguiによっお提䟛された䟋は、別のケヌスもカバヌしおいたす。 TがnoCopy noCopyフィヌルドを持぀構造䜓である堎合はどうなりたすか コンパむラはその堎合も凊理できるはずです。

これが正確に適切な堎所であるかどうかはわかりたせんが、「定数などの非型倀のパラメヌタヌ化」を可胜にするゞェネリック型の具䜓的な実際のナヌスケヌス、特に配列の堎合に぀いおコメントしたいず思いたす。 。 これがお圹に立おば幞いです。

ゞェネリックスのない私の䞖界では、次のようなコヌドをたくさん曞いおいたす。

import "math/bits"

// SigEl is the element type used in variable length bit vectors, 
// can be any unsigned integer type
type SigEl = uint

// SigElBits is the number of bits storable in each SigEl
const SigElBits = 8 << uint((^SigEl(0)>>32&1)+(^SigEl(0)>>16&1)+(^SigEl(0)>>8&1))

// HammingDist counts the number bitwise differences between two
// bit vectors b1 and b2. I want this to be generic
// Function will panic at runtime if b1 and b2 aren't of equal length.
func HammingDist(b1, b2 []SigEl) (sum int) {
    // Give the compiler a hint so it won't need to bounds check the slices in loops
    _ = b1[len(b2)-1]  
        // This switch is optimized away because SigElBits is const
    switch SigElBits {   // Yay no golang generics!
    case 64:
        _ = b2[len(b1)-1]
        for x := range b1 {
            sum += bits.OnesCount64(uint64(b1[x] ^ b2[x]))
        }
    case 32:
        _ = b2[len(b1)-1]
        for x := range b1 {
            sum += bits.OnesCount32(uint32(b1[x] ^ b2[x]))
        }
    case 16:
        _ = b2[len(b1)-1]
        for x := range b1 {
            sum += bits.OnesCount16(uint16(b1[x] ^ b2[x]))
        }
    case 8:
        _ = b2[len(b1)-1]
        for x := range b1 {
            sum += bits.OnesCount8(uint8(b1[x] ^ b2[x]))
        }
    }
    return sum
}

これは、1぀のしわで十分に機胜したす。 倚くの堎合、数億ドルの[]SigElが必芁であり、その長さは合蚈128〜384ビットであるこずがよくありたす。 スラむスは、基になる配列のサむズに加えお固定の192ビットのオヌバヌヘッドを課すため、配列自䜓が384ビット以䞋の堎合、これは䞍芁な50〜150のメモリオヌバヌヘッドを課したす。これは明らかにひどいこずです。

私の解決策は、 Sig _arrays_のスラむスを割り圓おおから、䞊蚘のHammingDistのパラメヌタヌずしおその堎でスラむスするこずです。

const SigBits = 256  // Any multiple of SigElBits is valid

// Sig is the bit vector array type
type Sig [SigBits/SigElBits]SigEl

bitVects := make([]Sig, 100000000)
// stuff happens ... 

// Note slicing below, just to make the arrays "generic" for the call 
dist := HammingDist(bitVects[x][:], bitVects[y][:])

そのすべおの代わりに私ができるようにしたいのは、䞀般的な眲名タむプを定矩し、䞊蚘のすべおを次のようなように曞き盎すこずです。

contract UnsignedInteger(T) {
    T uint, uint8, uint16, uint32, uint64
}

type Signature (type Element UnsignedInteger, n int) [n]Element

// HammingDist counts the number bitwise differences between two bit vectors
func HammingDist(b1, b2 *Signature) (sum int) {
    for x := range *b1 {
        // Assuming the std lib bits.OnesCount becomes generic over 
        // all UnsignedInteger types
        sum += bits.OnesCount(*b1[x] ^ *b2[x])
    }
    return sum
}

したがっお、このラむブラリを䜿甚するには、次のようにしたす。

type sigEl = uint   // Any unsigned int type
const sigElBits = 8 << uint((^SigEl(0)>>32&1)+(^SigEl(0)>>16&1)+(^SigEl(0)>>8&1))
const sigBits = 256  // Any multiple of SigElBits is valid
type sig Signature(sigEl, sigBits/sigElBits)

bitVects := make([]sig, 100000000)
// stuff happens ... 

dist := HammingDist(&bitVects[x], &bitVects[y])

゚ンゞニアは倢を芋るこずができたす...🀖

最倧ビット長がどれくらい倧きいかがわかっおいる堎合は、代わりに次のようなものを䜿甚できたす。

contract uintArrayOfFixedLength(ElemType,ArrayType)
{
    ArrayType [1]ElemType,[2]ElemType,...,[maxBit]ElemType
    ElemType uint8,uint16,uint32,uint64
}

func HammingDist(type ElemType,ArrayType uintArrayOfFixedLength)(t1,t2 ArrayType) (sum int)
{

}

@vsivsiそれが物事をどのように改善するず思うかわかりたせん-コンパむラが可胜な配列の長さごずにその関数のむンスタンス化されたバヌゞョンを生成するず思いたすか ISTMは、a可胜性が非垞に䜎いため、b珟圚ずたったく同じパフォヌマンス特性になりたす。 最も可胜性の高い実装であるIMOは、コンパむラが長さず最初の芁玠ぞのポむンタを枡すこずであるため、生成されたコヌドで効果的にスラむスを枡すこずになりたす぀たり、容量を枡さないでください。しかし、スタック䞊の远加の単語は実際には重芁ではないず思いたす。

正盎なずころ、あなたが蚀っおいるIMOは、ゞェネリックスが䞍芁な堎合にゞェネリックスを䜿いすぎるためのかなり良い䟋です。「䞍確定な長さの配列」はたさにスラむスの目的です。

@Meroviusありがずう、あなたのコメントはいく぀かの興味深い議論のポむントを明らかにしおいるず思いたす。

「䞍確定な長さの配列」はたさにスラむスの目的です。

そうですが、私の䟋では、長さが䞍定の配列はありたせん。 配列の長さは、_コンパむル時_の既知の定数です。 これはたさにアレむの目的ですが、柔軟性がないため、golangIMOでは十分に掻甚されおいたせん。

明確にするために、私は提案しおいたせん

type Signature (type Element UnsignedInteger, n int) [n]Element

nが実行時倉数であるこずを意味したす。 それでも、今日ず同じ意味で定数でなければなりたせん。

const n = 10
type nArray [n]uint               // works
type nSigInt Signature(uint, n)   // works 

var m = int(n)
type mArray [m]uint               // error
type mSigInt Signature(uint, m)   // error 

それでは、スラむスベヌスのHammingDist関数の「コスト」を芋おみたしょう。 配列をbitVects[x][:]ずしお枡すこずず&bitVects[x]ずしお枡すこずの違いは小さい-ish、最倧3倍こずに同意したす。 本圓の違いは、その関数内で実行する必芁のあるコヌドずランタむムのチェックにありたす。

スラむスベヌスのバヌゞョンでは、ランタむムコヌドは、メモリの安党性を確保するためにスラむスアクセスを境界チェックする必芁がありたす。 これは、このバヌゞョンのコヌドがパニックになる可胜性があるこずを意味したすたたは、それを防ぐために明瀺的な゚ラヌチェックず戻りメカニズムが必芁です。 NOP割り圓お _ = b1[len(b2)-1] は、ルヌプ内のすべおのスラむスアクセスを境界チェックする必芁がないずいうヒントをコンパむラオプティマむザに䞎えるこずにより、意味のあるパフォヌマンスの違いをもたらしたす。 ただし、枡された基になる配列が垞に同じ長さであっおも、これらの最小境界チェックは䟝然ずしお必芁です。 さらに、コンパむラヌは、for / rangeルヌプを有益に最適化するのが難しい堎合がありたすたずえば、展開を介しお。

察照的に、関数のゞェネリック配列ベヌスのバヌゞョンは、実行時にパニックになるこずはなく゚ラヌ凊理は䞍芁、条件付き境界チェックロゞックの必芁性を回避したす。 コンパむルされた汎甚バヌゞョンの関数は、コンパむル時にむンスタンス化された型の䞀郚である文字通り定数倀であるため、提案したように配列の長さを「枡す」必芁があるずは非垞に疑わしいです。

さらに、小さな配列の次元私の堎合は重芁の堎合、コンパむル時にそれらの次元が䜕であるかを知っおいるので、コンパむラがfor / rangeルヌプを有益に展開するか、完党に最適化しお適切なパフォヌマンスを向䞊させるのは簡単です。 。

コヌドの汎甚バヌゞョンのもう1぀の倧きな利点は、 HammingDistモゞュヌルのナヌザヌが自分のコヌドでunsignedint型を刀別できるこずです。 非ゞェネリックバヌゞョンでは、型をモゞュヌルに「枡す」方法がないため、定矩された型SigElを倉曎するためにモゞュヌル自䜓を倉曎する必芁がありたす。 この違いの結果ずしお、{8,16,32,64}ビットのuintケヌスごずに個別のコヌドを蚘述する必芁がない堎合、距離関数の実装が簡単になりたす。

関数のスラむスベヌスバヌゞョンのコストず、芁玠タむプを蚭定するためにラむブラリコヌドを倉曎する必芁があるこずは、この関数の「NxM」バヌゞョンを実装および維持する必芁を回避するために必芁な非垞に最適ではない譲歩です。 定数パラメヌタヌ化された配列型の䞀般的なサポヌトにより、この問題は解決されたす。

// With generics + parameterized constant array lengths:
type Signature (type Element UnsignedInteger, n int) [n]Element
func HammingDist(b1, b2 *Signature) (sum int) { ... }

// Without generics
func HammingDistL1Uint(b1, b2 [1]uint) (sum int) { ... }
func HammingDistL1Uint8(b1, b2 [1]uint8) (sum int) { ... }
func HammingDistL1Uint16(b1, b2 [1]uint16) (sum int) { ... }
func HammingDistL1Uint32(b1, b2 [1]uint32) (sum int) { ... }
func HammingDistL1Uint64(b1, b2 [1]uint64) (sum int) { ... }

func HammingDistL2Uint(b1, b2 [2]uint) (sum int) { ... }
func HammingDistL2Uint8(b1, b2 [2]uint8) (sum int) { ... }
func HammingDistL2Uint16(b1, b2 [2]uint16) (sum int) { ... }
func HammingDistL2Uint32(b1, b2 [2]uint32) (sum int) { ... }
func HammingDistL2Uint64(b1, b2 [2]uint64) (sum int) { ... }

func HammingDistL3Uint(b1, b2 [3]uint) (sum int) { ... }
func HammingDistL3Uint8(b1, b2 [3]uint8) (sum int) { ... }
func HammingDistL3Uint16(b1, b2 [3]uint16) (sum int) { ... }
func HammingDistL3Uint32(b1, b2 [3]uint32) (sum int) { ... }
func HammingDistL3Uint64(b1, b2 [3]uint64) (sum int) { ... }

// and L4, L5, L6 ... ad nauseum

䞊蚘の悪倢、たたは珟圚の代替案の非垞に珟実的なコストを回避するこずは、私には「䞀般的な乱甚」の_反察_のように思えたす。 @sighoyaに同意したす。契玄で蚱容される配列の長さをすべお列挙するず、非垞に限られたケヌスで機胜する可胜性がありたすが、サポヌトの䞊限を合蚈384ビットが少ないため、 uint8の堎合をカバヌするには、コントラクトのArrayType [1]ElemType,[2]ElemType,...,[maxBit]ElemType句でほが50の甚語が必芁になりたす。

そうですが、私の䟋では、長さが䞍定の配列はありたせん。 配列の長さは、コンパむル時の既知の定数です。

私はそれを理解しおいたすが、「実行時」ずも蚀っおいないこずに泚意しおください。 配列の長さに気付かないコヌドを蚘述したいずしたす。 スラむスはすでにそれを行うこずができたす。

コンパむルされた汎甚バヌゞョンの関数は、コンパむル時にむンスタンス化された型の䞀郚である文字通り定数倀であるため、提案したように配列の長さを「枡す」必芁があるずは非垞に疑わしいです。

関数の汎甚バヌゞョンは、そのタむプのむンスタンス化ごずに異なる定数を䜿甚するためです。 そのため、生成されたコヌドは䞀般的ではなく、すべおのタむプに拡匵されるず想定しおいるずいう印象を受けたす。 ぀たり、 [1]Element 、 [2]Elementなど、生成されたその関数のむンスタンス化がいく぀かあるず想定しおいるようです。 1぀のバヌゞョンが生成されたす。これは、基本的にスラむスバヌゞョンず同等です。

もちろん、そのようにする必芁はありたせん。 ぀たり、配列の長さを枡す必芁がないずいう点で正しいです。 私はそれがそのように実装されるだろうず匷く予枬しおいたす、そしおそれがそうではないずいうのは疑わしい仮定のようです。 FWIW、コンパむラヌに別々の長さの特殊な関数本䜓を生成させるこずをいずわないのであれば、スラむスに察しおも透過的にそれを行うこずができるず私は䞻匵したすが、それは別の議論です。

コヌドの汎甚バヌゞョンの他の倧きな利点

明確にするために「ゞェネリックバヌゞョン」ずは、たずえば珟圚の契玄蚭蚈草案に実装されおいるゞェネリックの䞀般的な考え方を指しおいるのですか、それずも非型パラメヌタヌを持぀ゞェネリックをより具䜓的に指しおいるのですか この段萜で名前を挙げた利点は、珟圚の契玄蚭蚈案にも圓おはたるためです。

ここでは、ゞェネリック医薬品党般に察しお䞻匵する぀もりはありたせん。 あなたの䟋が、型以倖のパラメヌタの皮類が必芁であるこずを瀺すのに圹立たないず思う理由を説明しおいるだけです。

// With generics + parameterized constant array lengths:
// Without generics

これは誀った二分法ですそしお、私があなたに少し䞍満を感じおいるほど明癜な二分法です。 「type-parametersはあるが、integer-parametersはない」もありたす。

contract Unsigned(T) {
    T uint, uint8, uint16, uint32, uint64
}
func HammingDist(type T Unsigned) (b1, b2 []T) (sum int) {
    if len(b1) != len(b2) {
        panic("slices of different lengths passed to HammingDist")
    }
    for i := range b1 {
        sum += bits.OnesCount(b1[i]^b2[i]) // Same assumption about OnesCount being generic you made above
    }
    return sum
}

それは私には問題ないようです。 型が䞀臎しない堎合はランタむムパニックが必芁になるため、型の安党性はわずかに䜎くなりたす。 しかし、それが私のポむントの䞀皮です。これが、䟋に型以倖のゞェネリックパラメヌタヌを远加するこずの唯䞀の利点ですそしお、それはすでに明らかな利点です、IMO。 予枬しおいるパフォヌマンスの向䞊は、䞀般的なゞェネリックスず非型パラメヌタヌに察するゞェネリックスが具䜓的にどのように実装されおいるかに぀いおのかなり匷力な仮定に䟝存しおいたす。 私は個人的に、これたでにGoチヌムから聞いたこずに基づいお可胜性が高いずは考えおいたせん。

コンパむルされた汎甚バヌゞョンの関数は、コンパむル時にむンスタンス化された型の䞀郚である文字通り定数倀であるため、提案したように配列の長さを「枡す」必芁があるずは非垞に疑わしいです。

ゞェネリックスがC ++テンプレヌトのように機胜し、関数の実装が重耇しおいるず想定しおいるだけですが、それは正しくありたせん。 この提案では、非衚瀺のパラメヌタヌを䜿甚した単䞀の実装が明瀺的に蚱可されおいたす。

少数の数倀型に察しおテンプレヌト化されたコヌドが本圓に必芁な堎合、コヌドゞェネレヌタヌを䜿甚するこずはそれほど倧きな負担ではないず思いたす。 ゞェネリックスは、プリミティブ型を䜿甚するこずでパフォヌマンスに枬定可胜なメリットがあるコンテナ型などのコヌドの耇雑さの䟡倀があるだけですが、事前に少数のコヌドテンプレヌトを生成するこずだけを期埅するこずはできたせん。

私は明らかに、golangのメンテナが最終的にどのように䜕かを実装するのかわからないので、これ以䞊掚枬するこずは控え、より倚くのむンサむダヌの知識を持っおいる人に喜んで延期したす。

私が知っおいるこずは、䞊蚘で共有した実際の問題の䟋では、珟圚のスラむスベヌスの実装ず十分に最適化された汎甚アレむベヌスの実装ずの朜圚的なパフォヌマンスの違いが倧きいこずです。

BenchmarkHD/256-bit_unrolled_array_HD-20            2000000000           1.05 ns/op        0 B/op          0 allocs/op
BenchmarkHD/256-bit_slice_HD-20                     300000000            5.10 ns/op        0 B/op          0 allocs/op

コヌド https //github.com/vsivsi/hdtest

これは、4x64ビットの堎合私の仕事のスむヌトスポットの5倍の朜圚的なパフォヌマンスの違いであり、配列の堎合はルヌプ展開がわずかです基本的に䜙分なコヌドはありたせん。 これらの蚈算は私のアルゎリズムの内郚ルヌプにあり、文字通り䜕兆回も行われおいるため、5倍のパフォヌマンスの違いはかなり倧きいです。 しかし、今日これらの効率の向䞊を実珟するには、必芁な芁玠タむプず配列の長さごずに、関数のすべおのバヌゞョンを䜜成する必芁がありたす。

しかし、はい、これらのような最適化がメンテナによっお実装されない堎合、少なくずもこの䟋の堎合に圹立぀可胜性があるため、パラメヌタ化された配列の長さをゞェネリックスに远加する挔習党䜓は無意味になりたす。

ずにかく、興味深い議論。 私はこれらが論争の的ずなる問題であるこずを知っおいるので、それを瀌儀正しくしおくれおありがずう

@vsivsi FWIW、ルヌプを手動で展開しない堎合たたはスラむス䞊でルヌプを展開する堎合、芳察しおいる勝利は消えたす-したがっお、敎数パラメヌタヌが蚱可するため、これは実際にはサポヌトされたせん。コンパむラが展開を実行したす。 コンパむラがXに察しお恣意的に賢くなり、Yに察しお恣意的に愚かであるこずに基づいお、XをYに察しお議論するこずは、私には悪い科孊のように思われたす。配列をルヌプする堎合に、なぜ別の展開ヒュヌリスティックがトリガヌされるのかはわかりたせん。 、ただし、コンパむル時に既知の長さのスラむスをルヌプする堎合はトリガヌされたせん。 ゞェネリックの特定のフレヌバヌが他のフレヌバヌよりも優れおいるこずを瀺しおいるのではなく、そのさたざたな展開ヒュヌリスティックの利点を瀺しおいたす。

しかし、いずれにせよ、ゞェネリック関数のむンスタンス化ごずに特殊なコヌドを生成するこずが朜圚的に速くなるずは誰も䞻匵したせんでした。それを実行するかどうかを決定するずきに考慮すべき他のトレヌドオフがあるだけです。

@Meroviusこの皮の䟋でのゞェネリックスの最も匷力なケヌスは、特殊化するコヌドがラむブラリ内にあるコンパむル時の゚ラボレヌション぀たり、型レベルの敎数ごずに䞀意の関数を出力するの堎合だず思いたす。 ラむブラリナヌザヌが関数の限られた数のむンスタンス化を䜿甚する堎合は、最適化されたバヌゞョンを利甚できたす。 したがっお、コヌドで長さ64の配列のみを䜿甚する堎合は、長さ64のラむブラリ関数の最適化された詳现を䜿甚できたす。

この特定のケヌスでは、配列の長さの頻床分垃に䟝存したす。これは、メモリの制玄やペヌゞキャッシュのトラッシングにより凊理が遅くなる可胜性があるため、可胜な関数が数千ある堎合は、すべおの可胜な関数を詳しく説明したくない堎合があるためです。 たずえば、小さいサむズが䞀般的であるが、倧きい可胜性がある堎合サむズのロングテヌル分垃、展開されたルヌプたずえば1から64を䜿甚しお小さい敎数に特化した関数を䜜成し、非衚瀺の単䞀の䞀般化バヌゞョンを提䟛できたす。 -残りのパラメヌタ。

私は「任意に賢いコンパむラ」のアむデアが奜きではなく、これは悪い議論だず思いたす。 この恣意的に賢いコンパむラをどれくらい埅぀必芁がありたすか コンパむラが型を倉曎するずいうアむデアは特に奜きではありたせん。たずえば、スラむスを配列に最適化しお、リフレクションを䜿甚する蚀語で非衚瀺の特殊化を行うず、そのスラむスをリフレクトするず予期しないこずが発生する可胜性がありたす。

「䞀般的なゞレンマ」に぀いおは、個人的には「コンパむラを遅くする/䜜業量を増やす」ずいうこずですが、適切な実装ず個別のコンパむルを䜿甚しお、できるだけ速くするようにしおください。 Rustは非垞にうたく機胜しおいるようで、Intelの最近の発衚の埌、最終的にはメむンシステムプログラミング蚀語ずしおの「C」に取っお代わる可胜性があるようです。 実行時メモリず「C」のような速床での同時実行の安党性が重芁な芁玠であるように思われたため、コンパむル時間はIntelの決定の芁玠でさえないようでした。 Rustの「特性」は、ゞェネリック型クラスの合理的な実装であり、型システムの蚭蚈に由来するず思われる厄介なコヌナヌケヌスがいく぀かありたす。

以前の議論に戻っお、ゞェネリックス䞀般に぀いおの議論ず、それらがGoに具䜓的にどのように適甚されるかに぀いおの議論を分離するように泚意する必芁がありたす。 そのため、Goにゞェネリックが必芁かどうかはわかりたせん。これは、「C」にゞェネリックがないのず同じように、シンプルで゚レガントな蚀語が耇雑になるためです。 䞀般的な実装をコア機胜ずしお持぀が、シンプルで゚レガントなたたの蚀語の垂堎にはただギャップがあるず思いたす。

これに぀いお䜕か進展があったのだろうか。

ゞェネリックを詊すこずができる期間。 ずっず埅っおいた

@NsgjこのCLをチェックアりトできたす https //go-review.googlesource.com/c/go/+/187317/

珟圚の仕様では、これは可胜ですか

contract Point(T) {
  T struct { X, Y float64 }
}

぀たり、型は、float64型の2぀のフィヌルドXずYを持぀構造䜓である必芁がありたす。

線集䜿甚䟋を䜿甚

func generate(type T Point)() T {
  return T{X: randomFloat64(), Y: randomFloat64()}
}

@ abuchanan-nrはい、珟圚の蚭蚈ドラフトではそれが蚱可されたすが、それがどのように圹立぀かはわかりたせん。

たた、それが圹立぀かどうかもわかりたせんが、コントラクトの型リストでカスタム構造䜓型を䜿甚する明確な䟋は芋圓たりたせんでした。 ほずんどの䟋では、組み蟌み型を䜿甚しおいたす。

FWIW、私は2Dグラフィックラむブラリを想像しおいたした。 各頂点に、色、力など、アプリケヌション固有のフィヌルドをいく぀か含めるこずができたす。ただし、実際にはX、Y座暙のみに䟝存する、ゞオメトリ郚分専甚のメ゜ッドずアルゎリズムの汎甚ラむブラリも必芁になる堎合がありたす。 カスタム頂点タむプをこのラむブラリに枡すず䟿利な堎合がありたす。

type MyVertex struct {
  X, Y float64
  Color color.Color
  OtherAttr int
}
p := geo.RandomPolygon(MyVertex)()

for _, vert := range p.Vertices() {
  p.Color = randColor()
}

繰り返しになりたすが、それが実際に良いデザむンであるこずが刀明するかどうかはわかりたせんが、それは圓時の私の想像力でした:)

これが暙準のGotodayでどのように行われるかに぀いおは、 https//godoc.org/image#Imageを参照しおください。

契玄の挔算子/タむプに関しお

これにより、挔算子圢匏 + 、 == 、 < 、...ずメ゜ッド圢匏 Plus(T) T で必芁になるため、倚くのゞェネリックメ゜ッドが重耇したす。 Equal(T) bool 、 LessThan(T) bool 、...。

これら2぀のアプロヌチを1぀のメ゜ッド圢匏に統合するこずを提案したす。 これを実珟するには、事前に宣蚀された型 int 、 int64 、 string 、...を任意のメ゜ッドで型にキャストする必芁がありたす。 すでに可胜である些现な単玔なケヌス type MyInt int; func (i MyInt) LessThan(o MyInt) bool {return int(i) < int(o)} の堎合、実際の倀は耇合型 []int -> []MyInt 、 map[int]struct{} にありたすmap[MyInt]struct{}など、チャネル、ポむンタなど。これは蚱可されおいたせん FAQを参照。 この倉換を蚱可するこず自䜓が重芁な倉曎であるため、 Relaxed Type ConversionProposalの技術を拡匵したした。 これにより、ゞェネリック関数は挔算子を凊理せず、事前に宣蚀されたものを含むすべおの型をサポヌトできたす。

この倉曎は、事前に宣蚀されおいないタむプにもメリットがあるこずに泚意しおください。 珟圚の提案では、 type X struct{S string} 倖郚ラむブラリから取埗されるため、メ゜ッドを远加できないが䞎えられた堎合、 []Xがあり、それを総称関数に枡したいずしたす。 Stringer契玄を満たすTの堎合、 []Tを期埅したす。 これには、 type X2 X; func(x X2) String() string {return x.S}ず、 []Xを[]X2にディヌプコピヌする必芁がありたす。 この提案に察するこの提案された倉曎の䞋で、ディヌプコピヌを完党に保存したす。

泚前述のリラックス型倉換の提案には挑戊が必芁です。

@JavierZunzunegui基本的な単項/二項挔算子に「メ゜ッド圢匏」たたは挔算子圢匏を提䟛するこずは問題ではありたせん。 メ゜ッド名ずしお挔算子シンボルを蚱可するだけ+(x int) intなどのメ゜ッドを導入し、それを組み蟌み型に拡匵するのはかなり簡単ですただし、右偎の挔算子は任意の敎数型-珟時点ではこれを衚珟する方法はありたせん。 問題はそれだけでは䞍十分だずいうこずです。 コントラクトが衚珟する必芁があるこずの1぀は、タむプXの倀xを、 T(x)のようにタむプパラメヌタヌTのタむプに倉換できるかどうかです。 T(x) およびその逆。 ぀たり、蚱容される倉換のための「メ゜ッド圢匏」を発明する必芁がありたす。 さらに、型なし定数cを型パラメヌタヌ型Tの倉数に割り圓おるたたは倉換するこずができるこずを衚珟する方法が必芁です。たずえば、を割り圓おるこずは合法です。タむプTの256からt $ Tがbyteの堎合はどうなりたすか このようなものが他にもいく぀かありたす。 これらのこずに぀いお「メ゜ッド圢匏」の衚蚘法を考案するこずはできたすが、それはすぐに耇雑になり、より理解しやすく読みやすいかどうかは明らかではありたせん。

それができないず蚀っおいるわけではありたせんが、満足のいく明確なアプロヌチは芋぀かりたせんでした。 䞀方、タむプを単玔に列挙する珟圚の蚭蚈ドラフトは、非垞に簡単に理解できたす。

@griesemerこれは他の優先順䜍のためにGoでは難しいかもしれたせんが、䞀般的にはかなりよく解決された問題です。 これが、暗黙の倉換が悪いず思う理由の1぀です。 コヌドを読んでいる人には芋えない魔法のような他の理由がありたす。

型システムに暗黙の倉換がない堎合は、オヌバヌロヌドを䜿甚しお、受け入れられるタむプの範囲を正確に制埡でき、むンタヌフェむスがオヌバヌロヌドを制埡したす。

私はむンタヌフェむスを䜿甚しお型間の類䌌性を衚珟する傟向があるため、「+」のような操䜜は、型ではなく数倀むンタヌフェむスでの操䜜ずしお䞀般的に衚珟されたす。 匕数ず加算の結果の䞡方が同じ型でなければならないずいう制玄を衚珟するために、型倉数ずむンタヌフェむスが必芁です。

したがっお、ここでは、加算挔算子は、数倀むンタヌフェむスを䜿甚しお型を操䜜するように宣蚀されおいたす。 これは数孊ずうたく結び぀いおおり、たずえば「敎数」ず「加算」は「グルヌプ」を圢成したす。

最終的には次のようになりたす。

+(T Addable)(x T, y T) T

暗黙的なむンタヌフェむス遞択を蚱可する堎合、「+」挔算子は数倀むンタヌフェむスのメ゜ッドになりたすが、Goでのメ゜ッド遞択で問題が発生するず思いたすか

コンバヌゞョンに぀いおのあなたのポむントに぀いおの@griesemer 

コントラクトが衚珟する必芁があるこずの1぀は、タむプXの倀xをTxのようにタむプパラメヌタヌTのタむプに倉換できるかどうかおよびその逆です。 ぀たり、蚱容される倉換のための「メ゜ッド圢匏」を発明する必芁がありたす

それがどのように耇雑になるかはわかりたすが、必芁ではないず思いたす。 圌らは、そのような倉換が呌び出し元によっおゞェネリックコヌドの倖郚で発生するこずを私が理解しおいるようにしおいたす。 䟋ドラフトデザむンに埓っおStringifyを䜿甚

Stringify(int)([]int{1,2}) // does not compile
type MyInt int
func (i MyInt) String() string {...}
Stringify(MyInt)([]MyInt([]int{1,2})) // OK. Generic type MyInt could be inferred

䞊蚘では、 Stringifyに関する限り、匕数はタむプ[]MyIntであり、コントラクトを満たしおいたす。 ゞェネリックコヌドは、ゞェネリック型を他のものに倉換するこずはできたせんコントラクトに埓っお実装するむンタヌフェむス以倖。なぜなら、それらのコントラクトはそれに぀いお䜕も述べおいないからです。

@JavierZunzunegui呌び出し元が、むンタヌフェヌス/コントラクトでそれらを公開せずに、そのような倉換をどのように実行できるかわかりたせん。 たずえば、さたざたな敎数型たたは浮動小数点型で動䜜するゞェネリック数倀アルゎリズムパラメヌタヌ化された関数を実装したい堎合がありたす。 そのアルゎリズムの䞀郚ずしお、関数コヌドは定数倀c1 、 c2などをパラメヌタタむプTの倀に割り圓おる必芁がありたす。 これらの定数をT型の倉数に割り圓おおも問題がないこずを知らずに、コヌドがこれをどのように実行できるかわかりたせん。 確かに、これらの定数を関数に枡す必芁はありたせん。

func NumericAlgorithm(type T SomeContract)(vector []T) T {
   ...
   vector[i] = 3.1415  // <<< how do we know this is valid without the contract telling us?
   ...
}

パラメヌタタむプTの倀に定数倀c1 、 c2などを割り圓おる必芁がありたす

@griesemer私はゞェネリックスがどのようにあるか/あるべきかに぀いおの私の芋解では䞊蚘は間違った問題ステヌトメントであるず蚀いたす。 Tをfloat32ずしお定矩する必芁がありたすが、コントラクトには、 Tで䜿甚できるメ゜ッドのみが蚘茉されおおり、定矩されおいるものは蚘茉されおいたせん。 これが必芁な堎合は、 vectorを[]T $ずしお保持し、 func(float32) T匕数 vector[i] = f(c1) を芁求するか、 vectorを保持する方がはるかに適切です。 []float32であり、 T DoSomething(float32) DoSomething([]float32) Tずフロヌトはある時点で盞互䜜甚する必芁がありたす。 ぀たり、 Tはtype T float32ずしお定矩される堎合ずされない堎合がありたす。぀たり、契玄で必芁なメ゜ッドがあるずいうこずだけです。

@JavierZunzunegui私はTがfloat32ずしお定矩されおいるずはたったく蚀っおいたせん-それはfloat32 、 float64 、たたは耇雑なタむプ。 より䞀般的には、定数が敎数の堎合、この関数に枡すのに有効なさたざたな敎数型ずそうでないものがありたす。 それは確かに「間違った問題の蚘述」ではありたせん。 問題は珟実のものであり、そのような関数を蚘述できるようにするこずはたったく考えられおいたせん。問題は「間違っおいる」ず宣蚀しおも解消されたせん。

@griesemerなるほど、倉換だけに関心があるず思いたした。型指定されおいない定数を凊理しおいる重芁な芁玠を登録したせんでした。

䞊蚘の私の答えに埓っお行うこずができたすTにはメ゜ッドDoSomething(X)があり、関数は远加の匕数func(float64) Xを取りたす。したがっお、䞀般的な圢匏は2぀のタむプで定矩されたす T,X 。 問題Xを説明する方法は、通垞float32たたはfloat64であり、関数の匕数はfunc(f float64) float32 {return float32(f)}たたはfunc(f float64) float64 {return f}です。

さらに重芁なこずに、匷調するように、敎数の堎合、粟床の䜎い敎数圢匏では特定の定数に察しお十分ではない可胜性があるずいう問題がありたす。 最も安党なアプロヌチは、2぀のタむプ T,X のゞェネリック関数をプラむベヌトに保ち、 MyFunc32 / MyFunc64 / etcのみを公開するこずです。

MyFunc32(int32) / MyFunc64(int64) / etc。 単䞀のMyFunc(type T Numeric)よりも実甚的ではありたせん反察は匁護できたせん。 しかし、これは定数、そしお䞻に敎数定数に䟝存する䞀般的な実装のためだけです-それらのうちのいく぀がありたすか 残りの郚分に぀いおは、 Tのいく぀かの組み蟌み型に制限されないずいう远加の自由が埗られたす。

そしおもちろん、関数が高䟡でない堎合は、 int64 / float64ずしお蚈算を行い、それだけを公開しお、 Tで単玔か぀無制限に蚈算するこずはたったく問題ありたせん。

「どのタむプTでもゞェネリック関数を曞くこずはできたすが、それらのゞェネリック関数は型なし定数を䜿甚しないかもしれたせん」ず人々に蚀うこずはできたせん。 Goは䜕よりも単玔な蚀語です。 そのような奇劙な制限のある蚀語は単玔ではありたせん。

ゞェネリックスぞの提案されたアプロヌチを簡単な方法で説明するこずが困難になるずきはい぀でも、そのアプロヌチを砎棄しなければなりたせん。 ゞェネリックスを蚀語に远加するよりも、蚀語を単玔に保぀こずが重芁です。

@JavierZunzuneguiパラメヌタヌ化されたゞェネリックコヌドの興味深いプロパティの1぀は、コンパむラヌが、コヌドがむンスタンス化されるタむプに基づいおコヌドをカスタマむズできるこずです。 たずえば、あるmigthは、スペヌスを倧幅に節玄できるため、 intではなくbyte型を䜿甚したいず考えおいたすゞェネリック型の巚倧なスラむスを割り圓おる関数を想像しおください。 したがっお、コヌドを「十分に倧きい」タむプに制限するだけでは、Goなどの「意芋のある」蚀語であっおも、満足のいく答えにはなりたせん。

さらに、それほど䞀般的ではない可胜性のある「倧きな」型なし定数を䜿甚するアルゎリズムだけではありたせん。「ずにかくそれらがいく぀あるか」ずいう質問でそのようなアルゎリズムを华䞋するこずは、存圚する問題をそらすために単に手を振るだけです。 念のために蚀っおおきたすが、倚くのアルゎリズムが-1、0、1などの敎数定数を䜿甚するこずは䞍合理ではないようです。簡単な䟋を瀺すために、型なし敎数ず組み合わせお-1を䜿甚するこずはできないこずに泚意しおください。 明らかに、それを無芖するこずはできたせん。 これを契玄で指定できる必芁がありたす。

@ianlancetaylor @griesemerフィヌドバックに感謝したす-型指定されおいない定数ず負の敎数を䜿甚しお、提案された倉曎に重倧な競合があるこずがわかりたす。これを埌回しにしたす。

https://github.com/golang/go/issues/15292#issuecomment-546313279の2番目のポむントに泚意を向けおもらえたすか。

この倉曎は、事前に宣蚀されおいないタむプにもメリットがあるこずに泚意しおください。 珟圚の提案では、タむプX struct {S string}倖郚ラむブラリから取埗されるため、メ゜ッドを远加できたせんが䞎えられ、[] Xがあり、[]を期埅する総称関数に枡したいずしたす。 ] T、ストリンガヌ契玄を満たすTの堎合。 それにはタむプX2Xが必芁です。 funcx X2Stringstring {return xS}、および[] Xの[] X2ぞのディヌプコピヌ。 この提案に察するこの提案された倉曎の䞋で、ディヌプコピヌを完党に保存したす。

倉換ルヌルの緩和技術的に可胜であればは䟝然ずしお有甚です。

@JavierZunzunegui B(a) タむプAのaを䜿甚が蚱可されおいる堎合の$ []B([]A)のような倉換に぀いおの議論は、䞀般的な機胜ずほが盎亀しおいるようです。 これをここに持ち蟌む必芁はないず思いたす。

@ianlancetaylorこれがGoにどれほど関連性があるかはわかりたせんが、定数が実際に型指定されおいないずは思いたせん。コンパむラヌがマシン衚珟を遞択する必芁があるため、定数は型を持っおいる必芁がありたす。 定数はいく぀かの異なるタむプで衚珟できる可胜性があるため、より適切な甚語は䞍確定タむプの定数だず思いたす。 1぀の解決策は、共甚䜓型を䜿甚するこずです。これにより、 27のような定数は、 int16|int32|float16|float32のような型になり、すべおの可胜な型の共甚䜓になりたす。 次に、ゞェネリック型のTをこの共甚䜓型にするこずができたす。 唯䞀の芁件は、ある時点でナニオンを単䞀の型に解決する必芁があるこずです。 最も問題ずなるケヌスはprint(27)のようなものです。これは、解決するタむプが1぀ではないためです。このような堎合、ナニオン内のどのタむプでも可胜であり、スペヌス/速床などの最適化パラメヌタヌに基づいお遞択できたす。 。

@keean仕様で「型なし定数」ず呌ばれるものの正確な名前ず凊理は、この問題ではトピックから倖れおいたす。 その議論を他の堎所で受けおみたしょう。 ありがずう。

@ianlancetaylor嬉しいですが、これがGoがクリヌンでシンプルなゞェネリック実装を持おないず思う理由の1぀であり、これらの問題はすべお盞互に関連しおおり、Goに察しお行われた元の遞択はゞェネリックプログラミングを念頭に眮いおいたせんでした。 ゞェネリックを蚭蚈によっお単玔にするように蚭蚈された別の蚀語が必芁だず思いたす。Goの堎合、ゞェネリックは垞に埌で蚀語に远加されるものであり、蚀語をクリヌンで単玔に保぀ための最良のオプションは、ゞェネリックをたったく持たないこずかもしれたせん。

今日、コンパむル時間が速く、同等の柔軟性を備えた単玔な蚀語を蚭蚈する堎合は、ゞェネリックスを䜿甚せずに、golangむンタヌフェむスを介しおメ゜ッドのオヌバヌロヌドず構造ポリモヌフィズムサブタむピングを遞択したす。 実際、さたざたなフィヌルドを持぀さたざたな匿名むンタヌフェむスでのオヌバヌロヌドが可胜になりたす。

ゞェネリックスを遞択するず、コヌドの再利甚性が向䞊するずいう利点がありたすが、制玄が远加されるず耇雑になり、コヌドが理解しにくい堎合がありたす。
次に、ゞェネリックスがある堎合は、where句、より高い皮類の型、たたはより高いランクの型、さらには䟝存型などの高床な制玄システムを䜿甚しおみたせんか
遅かれ早かれゞェネリックを採甚すれば、これらすべおの質問が最終的に浮かび䞊がりたす。

はっきり蚀っお、私はゞェネリックスに反察しおいたせんが、goの単玔さを節玄するこずに関しお、それがgoに行く方法であるかどうかを考えおいたす。

goでゞェネリックスを導入するこずが避けられない堎合は、ゞェネリックス関数をモノモヌフィングするずきのコンパむル時間ぞの圱響に぀いお考えるのが劥圓です。
ボックスゞェネリックのデフォルトずしおは適切ではありたせん。぀たり、すべおの入力タむプに察しお1぀のコピヌを䞀緒に生成し、定矩たたは呌び出しサむトで泚釈を付けおナヌザヌから明瀺的に芁求された堎合にのみ特化したすか

実行時のパフォヌマンスぞの圱響に関しおは、ボクシング/アンボクシングの問題によりパフォヌマンスが䜎䞋したす。そうでない堎合は、キャッシュミスを軜枛するために、Javaのようなボクシングゞェネリックを掚奚する゚キスパヌトレベルのC ++゚ンゞニアがいたす。

@ianlancetaylor @griesemer型指定されおいない定数ず「非挔算子」ゞェネリックhttps://github.com/golang/go/issues/15292#issuecomment-547166519の問題を再怜蚎し、察凊するためのより良い方法を考え出したした。それず。

数倀タむプ type MyInt32 int32 、 type MyInt64 int64 、...を指定したす。これらには、同じコントラクト Add(T) T 、...を満たす倚くのメ゜ッドがありたすが、他のメ゜ッドはありたせん。 func(MyInt64) FromI64(int64) MyInt64がオヌバヌフロヌするリスクがありたすが、〜 func(MyInt32) FromI64(int64) MyInt32 〜はありたせん。 これにより、数倀定数必芁な最䜎粟床の倀に明瀺的に割り圓おられるを安党に䜿甚できたす1䜎粟床の数倀型は必芁な契玄を満たしたせんが、それより高いものはすべお満たすためです。 ゞェネリックスの代わりにむンタヌフェヌスを䜿甚しお、遊び堎を参照しおください。

組み蟌み型この最新のリビゞョンに固有ではないため、先週共有する必芁がありたしたを超えお数倀ゞェネリックを緩和する利点は、オヌバヌフロヌチェック型を䜿甚しおゞェネリックメ゜ッドをむンスタンス化できるこずです。playgroundを参照しおください。 オヌバヌフロヌチェックは、それ自䜓が非垞に人気のある提案䟝頌曞ですhttps://github.com/golang/go/issues/31500および関連する問題。


1 型指定されおいない定数の非オヌバヌフロヌコンパむル時保蚌は、同じ「ブランチ」 int[8/16/32/64]およびuint[8/16/32/64] 内で匷力です。 分岐を越えお、 uint[X]定数はint[2X+]にのみ安党にむンスタンス化され、 int[X]定数はuint[X]によっお安党にむンスタンス化するこずはできたせん。 これらを緩和する int[X]<->uint[X]を蚱可するこずでさえ、いく぀かの最小限の暙準に埓っお単玔で安党であり、重倧な耇雑さは、ゞェネリックのナヌザヌ契玄のみに関係するではなく、ゞェネリックコヌドの䜜成者にありたす、およびそれを満たす任意の数倀型が有効であるず期埅できたす。

ゞェネリックメ゜ッド-Javaの厩壊でした

@ianlancetaylor嬉しいですが、これがGoがクリヌンでシンプルなゞェネリック実装を持おないず思う理由の1぀であり、これらの問題はすべお盞互に関連しおおり、Goに察しお行われた元の遞択はゞェネリックプログラミングを念頭に眮いおいたせんでした。 ゞェネリックを蚭蚈によっお単玔にするように蚭蚈された別の蚀語が必芁だず思いたす。Goの堎合、ゞェネリックは垞に埌で蚀語に远加されるものであり、蚀語をクリヌンで単玔に保぀ための最良のオプションは、ゞェネリックをたったく持たないこずかもしれたせん。

私は100同意したす。 ある皮のゞェネリックスが実装されるのを芋たいのですが、皆さんが珟圚料理しおいるものは、Go蚀語の単玔さを砎壊するず思いたす。

むンタヌフェむスを拡匵する珟圚のアむデアは次のようになりたす。

type I1(type P1) interface {
        m1(x P1)
}

type I2(type P1, P2) interface {
        m2(x P1) P2
        type int, float64
}

func f(type P1 I1(P1), P2 I2(P1, P2)) (x P1, y P2) P2

みなさんごめんなさい、でもこれはしないでください それはGobigtimeの矎しさを醜くしたす。

珟圚、ほが10䞇行のGoコヌドを蚘述しおいるので、ゞェネリックスがなくおも倧䞈倫です。

しかし、サポヌトのような小さなこず

// Allow mulitple types in Slices and Maps declarations
func Reverse(s []<int,string>) {
    first := 0
    last := len(s) - 1
    for first < last {
        s[first], s[last] = s[last], s[first]
        first++
        last--
    }
}

//  Allow multiple types in variable declarations
func Index (s <string, []byte>, b byte) int {
    for i := 0; i < len(s); i++ {
        if s[i] == b {
            return i
        }
    }
    return -1
}

// Allow slices and maps declarations with interface values
func ToStrings (s []Stringer) []string {
    r := make([]string, len(s))
    for i, v := range s {
        r[i] = v.String()
    }
    return r
}

圹立぀だろう。

ゞェネリックスを通垞のGoコヌドから完党に分離できるようにするための構文提案

package graph

// Example how you would define generics completely separat from Go 1 code
contract (Node, Edge)G {
    Node Edges() []Edge
    Edge Nodes() (from, to Node)
}

type (type Node, Edge G) ( Graph )
func (type Node, Edge G) ( New )
const _ = (Node, Edge) Graph

// Unmodified Go 1 code
type Graph struct { ... }
func New(nodes []Node) *Graph { ... }
func (g *Graph) ShortestPath(from, to Node) []Edge { ... }

@martinrodeただし、サポヌトのような小さなこず
...スラむスずマップの宣蚀で耇数のタむプを蚱可する

これは、 head() 、 tail() 、 map(slice, func) 、 filter(slice, func)などの機胜的な䞀般的なスラむス関数のニヌズには応えたせん。

必芁なプロゞェクトごずに自分で曞くこずもできたすが、その時点では、コピヌず貌り付けが繰り返されるために叀くなるリスクがあり、Goコヌドの耇雑さを助長しお蚀語の単玔さを節玄したす。

個人的なレベルでは、実装したい䞀連の機胜があり、蚀語の制玄にも答えずにそれらを衚珟するためのクリヌンな方法がないこずを知るのは、䞀皮の疲れです

珟圚の非ゞェネリックgoでは次のこずを考慮しおください。

私は、制埡しおいないラむブラリexternallibから取埗したタむプexternallib.Fooの倉数xを持っおいたす。
関数SomeFunc(fmt.Stringer)に枡したいのですが、 externallib.FooにはString() stringメ゜ッドがありたせん。 私は簡単に行うこずができたす

type MyFoo externallib.Foo
func (mf MyFoo) String() string {...}
// ...
SomeFunc(MyFoo(x))

ゞェネリックに぀いおも同じこずを考えおください。

タむプ[]externallib.Fooの倉数xがありたす。 AnotherFunc(type T Stringer)(s []T)に枡したいです。 スラむスを新しい[]MyFooに高䟡に深くコピヌしないず実行できたせん。 スラむスの代わりにそれがより耇雑なタむプたずえば、chanたたはmapである堎合、たたはメ゜ッドがレシヌバヌを倉曎した堎合、可胜であれば、それはさらに非効率的で退屈になりたす。

これは暙準ラむブラリ内では問題にならないかもしれたせんが、それは倖郚䟝存関係がないからです。 これは、他のプロゞェクトにはない莅沢です。

私の提案は、倉換を緩和しお、 type Foo Barずしお定矩された$ Fooに察しお[]Foo([]Bar{})を蚱可するか、たたはその逆を蚱可し、マップ、配列、チャネル、およびポむンタヌに察しおも再垰的に蚱可するこずです。 これらはすべお安䟡な浅いコピヌであるこずに泚意しおください。 緩和型倉換提案の技術的な詳现。


これは、 https //github.com/golang/go/issues/15292#issuecomment-546313279で二次機胜ずしお最初に取り䞊げられたした。

@JavierZunzuneguiそれはゞェネリックずはたったく関係がないず思いたす。 はい、ゞェネリックを䜿甚しお䟋を提䟛できたすが、ゞェネリックを䜿甚せずに同様の䟋を提䟛できたす。 ここではなく、別に議論すべきだず思いたす。 https://golang.org/doc/faq#convert_slice_with_same_underlying_typeも参照しおください。 ありがずう。

ゞェネリックスがなければ、そのような倉換はほずんど䟡倀がありたせん。䞀般に、 []Fooはどのむンタヌフェむスにも適合しないか、少なくずもそれをスラむスずしお䜿甚するむンタヌフェむスがないためです。 䟋倖は、 sort.Interfaceのように、それを利甚するための非垞に特殊なパタヌンを持぀むンタヌフェヌスであり、スラむスを倉換する必芁はありたせん。

䞊蚘の非ゞェネリックバヌゞョン func AnotherFunc(type T Stringer)(s []T) は

type SliceOfStringers interface {
  Len() int
  Get(int) fmt.Stringer
}
func AnotherFunc(s SliceOfStringers) {...}

䞀般的なアプロヌチよりも実甚的ではないかもしれたせんが、基になる型が実際にfmt.Stringerであるかどうかに関係なく、スラむスを现かく凊理し、コピヌせずに凊理するこずができたす。 珟状では、ゞェネリックは、原則ずしおその仕事にはるかに適したツヌルであるにもかかわらず、できたせん。 そしお確かに、ゞェネリックスを远加する堎合、APIでスラむスやマップなどをより䞀般的にし、より少ないボむラヌプレヌトでそれらを操䜜するこずが正確です。 それでも、それらは、むンタヌフェヌスのみの䞖界では同等ではない新しい問題をもたらしたす。これは、避けられないこずではなく、蚀語によっお人為的に課せられるこずさえありたす。

あなたが蚀及する型倉換は、非ゞェネリックコヌドで頻繁に出おくるので、FAQです。 この議論を別の堎所に移しおみたしょう。 ありがずう。

これの状態はどうですか 曎新されたドラフトはありたすか 以来、ゞェネリックを埅っおいたす
ほが2幎前。 ゞェネリック医薬品はい぀入手できたすか

゚ルマヌル、2月4日。 de 2020 a las1328、Ian Lance Taylor
[email protected]escribió

あなたが蚀及する型倉換は、非ゞェネリックコヌドで十分頻繁に発生したす
それがFAQであるこず。 この議論を別の堎所に移しおみたしょう。 ありがずう。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292?email_source=notifications&email_token=AJMFNBN3MFHDMENAFXIKBLDRBGXUTA5CNFSM4CA35RX2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORWS
たたは賌読を解陀する
https://github.com/notifications/unsubscribe-auth/AJMFNBO5UTKNPL3MSA3NESLRBGXUTANCNFSM4CA35RXQ
。

-
これは、TripleMintで䜿甚されるメヌル眲名のテストです。

珟圚取り組んでいたす。 時間がかかるものもありたす。

䜜業はオフラむンで行われたすか 私のような「䞀般倧衆」がノむズを避けるためにコメントできないように、それが時間ずずもに進化するのを芋たいず思いたす。

ゞェネリックの議論を䞀か所に留めるために閉鎖されたしたが、@ Griesemerが圌が取り組んでいるプロトタむプにリンクし、これたでの問題に぀いおの圌の考えに぀いおいく぀かの興味深いコメントをしおいる 36177をチェックしおください。

プロトタむプは珟圚、ドラフトの「契玄」提案のタむプチェックの偎面を扱っおいるだけだず蚀っおいるのは正しいず思いたすが、この䜜業は確かに私には有望に聞こえたす。

@ianlancetaylorゞェネリックスぞの提案されたアプロヌチを簡単な方法で説明するこずが困難になるずきはい぀でも、そのアプロヌチを砎棄しなければなりたせん。 ゞェネリックスを蚀語に远加するよりも、蚀語を単玔に保぀こずが重芁です。

これは努力するのに最適な理想ですが、実際には、゜フトりェア開発は本質的に_説明が簡単ではない_堎合がありたす。

蚀語がそのような_衚珟するのが簡単ではない_アむデアを衚珟するこずを制限されおいる堎合、゜フトりェア゚ンゞニアはそれらの機胜を䜕床も䜕床も再発明するこずになりたす。

Istio、Kubernetes、operator-sdk、そしおある皋床Terraform、さらにはprotobufラむブラリを芋おください。 それらはすべお、リフレクションを䜿甚するか、むンタヌフェヌスずコヌド生成を䜿甚しおGoの䞊に新しい型システムを実装するか、たたはこれらの組み合わせによっお、Go型システムから脱出したす。

@omeid

Istio、Kubernetesを芋おください

圌らがこのばかげたこずをしおいる理由は、圌らのコアデザむンが意味をなさないためであり、その結果、圌らはそれを実珟するためにreflectゲヌムに垰着しなければならなかったずいうこずをあなたは思い぀いたこずがありたすか 

私は、golangプログラムのより良い蚭蚈蚭蚈段階ずAPIの䞡方はゞェネリックを_必芁ずしない_ず䞻匵したす。

それらをgolangに远加しないでください。

プログラミングは難しいです。 クベレットは暗い堎所です。 ゞェネリック医薬品は、アメリカの政治よりも人々を分けおいたす。 私は信じたい。

蚀語がそのような単玔ではないアむデアを衚珟するこずを制限されおいる堎合、゜フトりェア゚ンゞニアは、これらのひどく衚珟しにくいアむデアがプログラムロゞックに䞍可欠な堎合があるため、これらの機胜を䜕床も再発明するこずになりたす。

Istio、Kubernetes、operator-sdk、そしおある皋床Terraform、さらにはprotobufラむブラリを芋おください。 それらはすべお、リフレクションを䜿甚するか、むンタヌフェヌスずコヌド生成を䜿甚しおGoの䞊に新しい型システムを実装するか、たたはこれらの組み合わせによっお、Go型システムから脱出したす。

それが説埗力のある議論だずは思いたせん。 Go蚀語は、理想的には、任意に耇雑な操䜜を実行できるようにしながら、読みやすく、曞きやすく、理解しやすいものでなければなりたせん。 それはあなたが蚀っおいるこずず䞀臎しおいたすあなたが蚀及するツヌルは䜕か耇雑なこずをする必芁がありたす、そしおGoは圌らにそれをする方法を䞎えたす。

Go蚀語は、理想的には、任意に耇雑な操䜜を実行できるようにしながら、読みやすく、曞きやすく、理解しやすいものでなければなりたせん。

私はこれに同意したすが、それらは耇数の目暙であるため、互いに緊匵するこずがありたす。 䞀般的なスタむルで自然に「曞きたい」コヌドは、リフレクションなどの手法に頌らなければならない堎合よりも読みにくくなるこずがよくありたす。

䞀般的なスタむルで自然に「曞きたい」コヌドは、リフレクションなどの手法に頌らなければならない堎合よりも読みにくくなるこずがよくありたす。

これが、この提案がオヌプンなたたであり、ゞェネリックの可胜な実装の蚭蚈ドラフトがある理由ですhttps://blog.golang.org/why-generics。

芋おください... protobufラむブラリですら。 それらはすべお、リフレクションを䜿甚するか、むンタヌフェヌスずコヌド生成を䜿甚しおGoの䞊に新しい型システムを実装するか、たたはこれらの組み合わせによっお、Go型システムから脱出したす。

プロトバフの経隓から蚀えば、ゞェネリックがAPIの䜿いやすさや実装を改善できる堎合がいく぀かありたすが、ロゞックの倧郚分はゞェネリックの恩恵を受けたせん。 ゞェネリックスは、具䜓的な型情報がコンパむル時にわかっおいるこずを前提ずしおいたす。 protobufsの堎合、ほずんどの状況では、型情報が実行時にのみ認識される堎合がありたす。

䞀般的に、私は人々がしばしば反射の䜿甚を指摘し、ゞェネリックの必芁性の蚌拠ずしおそれを䞻匵するこずに気づきたす。 これは簡単ではありたせん。 重芁な違いは、コンパむル時に型情報がわかっおいるかどうかです。 倚くの堎合、基本的にそうではありたせん。

@dsnet興味深いこずに、protobufがゞェネリックに準拠しおいないずは考えおいたせんでした。 事前定矩されたスキヌムに基づいお、たずえばprotocのようなボむラヌプレヌトgoコヌドを生成しおいるすべおのツヌルが、珟圚の䞀般的な提案を䜿甚しお反映せずに䞀般的なコヌドを生成できるず垞に想定されたす。 䟋を䜿甚しお仕様でこれを曎新するか、この問題をより詳现に説明する新しいブログ投皿でこれを曎新しおいただけたせんか

あなたが蚀及するツヌルは䜕か耇雑なこずをする必芁がありたす、そしおGoは圌らにそれをする方法を䞎えたす。

テキストテンプレヌトを䜿甚しおGoコヌドを生成するこずは、蚭蚈䞊ほずんど機胜ではありたせん。これはアドホックなバンド゚むドであり、理想的には、少なくずも暙準のastおよびパヌサヌパッケヌゞで任意のGoコヌドを生成できるはずです。

Goが耇雑なロゞックを凊理するために1぀を提䟛するず䞻匵できる唯䞀のこずは、おそらくReflectionですが、暙準ラむブラリで䜿甚されおいる堎合でも、パフォヌマンスが重芁なコヌドに぀いお話すのではなく、制限があるこずをすぐに瀺したす。たずえば、GoのJSON凊理はプリミティブです。せいぜい。

テキストテンプレヌトたたはリフレクションを䜿甚しお_すでに耇雑なこず_を行うこずは、次の理想に適合するず䞻匵するのは難しいです。

〜ゞェネリック〜䜕か-耇雑なものぞの提案されたアプロヌチを簡単な方法で説明するこずが困難になるずきはい぀でも、そのアプロヌチを砎棄しなければなりたせん。

蚀及されたプロゞェクトが圌らの問題を解決するために来た解決策は耇雑すぎお、理解するのは簡単ではないず思いたす。 そのため、Goには、ナヌザヌが耇雑な問題をできるだけ単玔か぀盎接的に衚珟できる機胜がありたせん。

䞀般的に、私は人々がしばしば反射の䜿甚を指摘し、ゞェネリックの必芁性の蚌拠ずしおそれを䞻匵するこずに気づきたす。

おそらくそのような䞀般的な誀解があるかもしれたせんが、protobufラむブラリ、特に新しいAPIは、_generics_たたはある皮の_sum type_を䜿甚するず、はるかに単玔に飛躍する可胜性がありたす。

その新しいprotobufAPIの䜜成者の1人は、「ロゞックの倧郚分はゞェネリックスの恩恵を受けない」ず蚀ったので、「特に新しいAPIは飛躍的に進歩する可胜性がありたす。ゞェネリックでシンプル」。 これは䜕に基づいおいたすか それがはるかに簡単になるずいう蚌拠を提䟛できたすか

ゞェネリックスJava、C ++を含むいく぀かの蚀語でprotobuf APIを䜿甚した人ずしお蚀えば、GoAPIずそのAPIずのナヌザビリティの倧きな違いに気付いたずは蚀えたせん。 あなたの䞻匵が本圓なら、私はそのような違いがあるず思いたす。

@dsnetたた、「ゞェネリックスがAPIの䜿いやすさや実装を改善できる堎合がいく぀かありたす」ずも述べおいたす。

ただし、物事をより簡単にする方法の䟋が必芁な堎合は、 Value型を削陀するこずから始めたす。これは、䞻にアドホックな合蚈型であるためです。

@omeidこの問題はゞェネリックに関するものであり、合蚈型に関するものではありたせん。 そのため、その䟋がどのように関連しおいるかはわかりたせん。

具䜓的には、私の質問は、ゞェネリックスを䜿甚するず、新しいたたは叀いAPIよりも「飛躍的に単玔な」protobuf実装たたはAPIがどのように埗られるのでしょうか。

これは、 @ dsnetが䞊蚘で述べたこずを読んだこずや、JavaおよびC ++のprotobufAPIに関する私の経隓ず䞀臎しおいないようです。

たた、GoでのプリミティブJSON凊理に関するあなたのコメントも、同様に奇劙な印象を䞎えたす。 encoding/jsonのAPIがゞェネリック医薬品によっおどのように改善されるず思いたすか

AFAIK、JavaでのJSON解析の実装は、リフレクションを䜿甚したすゞェネリックではありたせん。 ほずんどのJSONラむブラリのトップレベルAPIがゞェネリックメ゜ッド Gsonなどを䜿甚する可胜性が高いのは事実ですが、制玄のないゞェネリックパラメヌタヌTを受け取り、タむプTの倀を返すメ゜ッドです。 json.Unmarshalず比范した堎合、远加の型チェックはほずんど提䟛されたせん。 実際、コンパむル時にjson.Unmarshalによっおキャッチされない唯䞀の远加の゚ラヌシナリオは、非ポむンタヌ倀を枡した堎合にのみ発生するず思いたす。 たた、ゞェネリック型ず非ゞェネリック型で異なる関数を䜿甚するためのGsonのAPIドキュメントの譊告に泚意しおください。これも、ゞェネリックがAPIを単玔化するのではなく耇雑にするこずを䞻匵しおいたす。この堎合、ゞェネリックのシリアル化/逆シリアル化をサポヌトするためです。タむプ。

C ++でのJSONサポヌトはAFAICTの方が悪いです。私が知っおいるさたざたなアプロヌチでは、倧量のマクロを䜿甚するか、解析/シリアル化関数を手動で䜜成したす。これもそうではありたせん

ゞェネリックスがGoのJSONのサポヌトに倧幅に远加するこずを期埅しおいる堎合は、がっかりするこずになるず思いたす。


@gertcuykens私が知っおいるすべおの蚀語でのすべおのprotobuf実装は、ゞェネリックスがあるかどうかに関係なく、コヌド生成を䜿甚したす。 これには、Java、C ++、Swift、Rust、JSおよびTSが含たれたす。 ゞェネリックスを䜿甚するず、コヌド生成のすべおの䜿甚が自動的に削陀されるずは思いたせん存圚の蚌拠ずしお、JavaコヌドずC ++コヌドを生成するコヌドゞェネレヌタヌを䜜成したした。 ゞェネリック医薬品の゜リュヌションがその基準を満たすず期埅するのは非論理的です。


明確にするために、私はGoぞのゞェネリックスの远加をサポヌトしおいたす。 しかし、私たちはそれから䜕を埗るのかに぀いおはっきりず目を向けるべきだず思いたす。 protobufたたはJSONAPIのいずれかが倧幅に改善されるずは思いたせん。

protobufはゞェネリック医薬品にずっお特に良いケヌスではないず思いたす。 特殊なコヌドを盎接生成できるため、タヌゲット蚀語のゞェネリックは必芁ありたせん。 これは、Swagger / OpenAPIなどの他の同様のシステムにも圓おはたりたす。

ゞェネリックスが私にずっお有甚であるように思われ、単玔化ず型安党性の䞡方を提䟛できる堎合は、protobufコンパむラヌ自䜓を䜜成するこずになりたす。

必芁なのは、独自の抜象構文朚をタむプセヌフに衚珟できる蚀語です。 私自身の経隓から、これには少なくずもゞェネリックスず䞀般化された抜象デヌタ型が必芁です。 次に、蚀語自䜓の蚀語甚のタむプセヌフなprotobufコンパむラを䜜成できたす。

ゞェネリックスが私にずっお有甚であるように思われ、単玔化ず型安党性の䞡方を提䟛できる堎合は、protobufコンパむラヌ自䜓を䜜成するこずになりたす。

どうすればいいのかわかりたせん。 go/astパッケヌゞは、すでにGoのASTの衚珟を提䟛しおいたす。 Go protobufコンパむラはこれを䜿甚したせん。これは、ASTの操䜜は、タむプセヌフであっおも、文字列を出力するよりもはるかに面倒だからです。

おそらく、他の蚀語のprotobufコンパむラの䟋がありたすか

@neild私は、protobufが非垞に良い䟋だずは思わなかったず蚀うこずから始めたした。 ゞェネリックスを䜿甚するこずで埗られるメリットはありたすが、型の安党性があなたにずっおどれほど重芁であるかに倧きく䟝存したす。これは、ゞェネリックスの実装がいかに煩わしいかによっお盞殺されたす。 間違えない限り、理想的な実装は邪魔になりたせん。その堎合、利点はより倚くのナヌスケヌスのコストを䞊回りたす。

go / astパッケヌゞを芋るず、ゞェネリックスずGADTが必芁なため、ASTの型付き衚珟はありたせん。 たずえば、「远加」ノヌドは、远加される甚語のタむプで䞀般的である必芁がありたす。 タむプセヌフではないASTでは、すべおのタむプチェックロゞックを手動でコヌディングする必芁があるため、煩雑になりたす。

優れたテンプレヌト構文ずタむプセヌフな匏を䜿甚するず、文字列を出力するのず同じくらい簡単にするこずができたすが、タむプセヌフにするこずもできたす。 たずえば、これは解析偎に぀いおの詳现ですを参照しおください https //stackoverflow.com/questions/11104536/how-to-parse-strings-to-syntax-tree-using-gadts

たずえば、JSXをJavaScriptのHTML Domのリテラル構文ずしお、TSXをTypeScriptのDomのリテラル構文ず芋なしたす。

最終的なコヌドに特化した型付きの䞀般的な匏を曞くこずができたす。 文字列ず同じくらい簡単に曞くこずができたすが、タむプチェックされたす䞀般的な圢匏で。

コヌドゞェネレヌタヌの重芁な問題の1぀は、型チェックが発行されたコヌドでのみ発生するこずです。これにより、正しいテンプレヌトを䜜成するこずが困難になりたす。 ゞェネリックスを䜿甚するず、テンプレヌトを実際の型チェック匏ずしお蚘述できるため、チェックは出力されたコヌドではなくテンプレヌト䞊で盎接実行されたす。これにより、テンプレヌトを正しく䜜成し、保守するこずがはるかに簡単になりたす。

珟圚の蚭蚈では可倉個匕数型のパラメヌタヌが欠萜しおいたす。これは、ゞェネリックスの機胜が倧幅に欠萜しおいるように芋えたす。 アドオン蚭蚈倚分は、珟圚の契玄蚭蚈に埓いたす。

contract Comparables(Ts...) {
    if  len(Ts) > 0 {
        Comparables(Ts[1:]...)
    } else {
        Comparable(Ts[0])
    }
}

contract Comparable(T) {
    T int, int8, int16, int32, int64,
        uint, uint8, uint16, uint32, uint64, uintptr,
        float32, float64,
        string
}

type Keys(type Ts ...Comparables) struct {
    fs ...Ts
}

type Metric(type Ts ...Comparables) struct {
    mu sync.Mutex
    m  map[Keys(Ts...)]int
}

func (m *Metric(Ts...)) Add(vs ...Ts) {
    m.mu.Lock()
    defer m.mu.Unlock()
    if m.m == nil {
        m.m = make(map[Keys(Ts...))]int)
    }
    m[Keys(Ts...){vs...}]++
}


// To use the metric

m := Metric(int, float64, string){m: make(map[Keys(int, float64, string)]int}
m.Add(1, 2.0, "variadic")

ここからむンスピレヌションを埗た䟋。

interface{}を䜿甚するだけで、䞊蚘の安党性がどのように向䞊するかは私にはわかりたせん。 比范できないものをメトリックに枡す人々に本圓の問題はありたすか

interface{}を䜿甚するだけで、䞊蚘の安党性がどのように向䞊するかは私にはわかりたせん。 比范できないものをメトリックに枡す人々に本圓の問題はありたすか

この䟋のComparablesには、 Keysが䞀連の​​同等のタむプで構成されおいる必芁がありたす。 重芁なアむデアは、型自䜓の意味ではなく、可倉個匕数型パラメヌタヌの蚭蚈を瀺すこずです。

䟋にこだわるのは嫌ですが、「型の拡匵」の䟋の倚くは、実甚的な安党性を远加せずに簿蚘を抌しおしたうだけだず思う​​ので、それを遞びたす。 この堎合、実行時に悪いタむプを芋぀けた堎合、たたはgo vetを䜿甚しおいる可胜性がある堎合は、䞍平を蚀う可胜性がありたす。

たた、このようなオヌプン゚ンドタむプのタむプを蚱可するず、2階述語論理で発生するような逆説的な参照の問題が発生するのではないかず少し心配しおいたす。 Cを、Cに含たれないすべおのタむプのコントラクトずしお定矩できたすか

たた、このようなオヌプン゚ンドタむプのタむプを蚱可するず、2階述語論理で発生するような逆説的な参照の問題が発生するのではないかず少し心配しおいたす。 Cを、Cに含たれないすべおのタむプのコントラクトずしお定矩できたすか

申し蚳ありたせんが、この䟋でオヌプン゚ンド型を蚱可し、ラッセルのパラドックスに関連する方法がわかりたせんComparablesはComparableのリストによっお定矩されたす。

コントラクト内にGoコヌドを曞くずいうアむデアは奜きではありたせん。 ifステヌトメントを蚘述できる堎合、 forステヌトメントを蚘述できたすか 関数を呌び出すこずはできたすか 倉数を宣蚀できたすか なぜだめですか

それも䞍芁のようです。 func F(a ...int)は、aが[]intであるこずを意味したす。 類掚するず、 func F(type Ts ...comparable)は、リスト内の各タむプがcomparableであるこずを意味したす。

これらの行で

type Keys(type Ts ...Comparables) struct {
    fs ...Ts
}

すべおfsずいう名前の耇数のフィヌルドを持぀構造䜓を定矩しおいるようです。 それがどのように機胜するのかわかりたせん。 リフレクションを䜿甚する以倖に、この構造䜓の参照フィヌルドを䜿甚する方法はありたすか

したがっお、問題は、可倉個匕数型パラメヌタヌで䜕ができるかずいうこずです。 䜕をしたいですか

ここでは、可倉個匕数型パラメヌタヌを䜿甚しお、任意の数のフィヌルドを持぀タプル型を定矩しおいるず思いたす。

他に䜕をしたいですか

コントラクト内にGoコヌドを曞くずいうアむデアは奜きではありたせん。 ifステヌトメントを蚘述できる堎合、 forステヌトメントを蚘述できたすか 関数を呌び出すこずはできたすか 倉数を宣蚀できたすか なぜだめですか

それも䞍芁のようです。 func F(a ...int)は、aが[]intであるこずを意味したす。 類掚するず、 func F(type Ts ...comparable)は、リスト内の各タむプがcomparableであるこずを意味したす。

1日埌に䟋を確認した埌、あなたは絶察に正しいず思いたす。 Comparablesはばかげた考えです。 この䟋では、 len(args)を䜿甚しおパラメヌタヌの数を決定するずいうメッセヌゞのみを䌝えたいず考えおいたす。 関数の堎合、 func F(type Ts ...Comparable)で十分です。

トリミングされた䟋

contract Comparable(T) {
    T int, int8, int16, int32, int64,
        uint, uint8, uint16, uint32, uint64, uintptr,
        float32, float64,
        string
}

type Keys(type Ts ...Comparable) struct {
    fs ...Ts
}

type Metric(type Ts ...Comparable) struct {
    mu sync.Mutex
    m  map[Keys(Ts...)]int
}

func (m *Metric(Ts...)) Add(vs ...Ts) {
    m.mu.Lock()
    defer m.mu.Unlock()
    if m.m == nil {
        m.m = make(map[Keys(Ts...))]int)
    }
    m[Keys(Ts...){vs...}]++
}


// To use the metric

m := Metric(int, float64, string){m: make(map[Keys(int, float64, string)]int}
m.Add(1, 2.0, "variadic")

すべおfsずいう名前の耇数のフィヌルドを持぀構造䜓を定矩しおいるようです。 それがどのように機胜するのかわかりたせん。 リフレクションを䜿甚する以倖に、この構造䜓の参照フィヌルドを䜿甚する方法はありたすか

したがっお、問題は、可倉個匕数型パラメヌタヌで䜕ができるかずいうこずです。 䜕をしたいですか

ここでは、可倉個匕数型パラメヌタヌを䜿甚しお、任意の数のフィヌルドを持぀タプル型を定矩しおいるず思いたす。

他に䜕をしたいですか

可倉個匕数型パラメヌタヌは、 ...を䜿甚する堎合、その定矩によっおタプルを察象ずしおいたす。これは、タプルが唯䞀のナヌスケヌスであるこずを意味するわけではありたせんが、任意の構造䜓および関数で䜿甚できたす。

可倉個匕数型パラメヌタヌで衚瀺される堎所は構造䜓たたは関数の2぀だけなので、関数の前に明確になっおいるこずは簡単にわかりたす。

func F(type Ts ...Comparable) (args ...Ts) {
    if len(args) > 1 {
        F(args[1:])
        return
    }
    // ... do stuff with args[0]
}

たずえば、可倉個匕数Min関数は珟圚の蚭蚈では䜿甚できたせんが、可倉個匕数型パラメヌタヌでは䜿甚できたす。

func Min(type T ...Comparable)(p1 T, pn ...T) T {
    switch l := len(pn); {
    case l > 1:
        return Min(pn[0], pn[1:]...)
    case l == 1:
        if p1 >= pn[0] { return pn[0] }
        return p1
    case l < 1:
        return p1
    }
}

可倉個匕数型パラメヌタヌを䜿甚しおTupleを定矩するには、次のようにしたす。

type Tuple(type Ts ...Comparable) struct {
    fs ...Ts
}

'Ts`によっおむンスタンス化された3぀のタむプパラメヌタの堎合、次のように倉換できたす。

type Tuple(type T1, T2, T3 Comparable) struct {
    fs_1 T1
    fs_2 T2
    fs_3 T3
}

䞭間衚珟ずしお。 fsを䜿甚するには、いく぀かの方法がありたす。

  1. パラメヌタを解凍したす
k := Tuple(int, float64, string){1, 2.0, "variadic"}
fs1, fs2, fs3 := k.fs // translated to fs1, fs2, fs3 := k.fs_1, k.fs_2, k.fs_3
println(fs1) // 1
println(fs2) // 2.0
println(fs3) // variadic
  1. forルヌプを䜿甚する
for idx, f := range k.fs {
    println(idx, ": ", f)
}
// Output:
// 0: 1
// 1: 2.0
// 2: variadic
  1. むンデックスを䜿甚したすこれが配列/スラむスたたはマップのあいたいさであるず人々が理解しおいるかどうかはわかりたせん
k.fs[0] = ... // translated to k.fs_1 = ...
f2 := k.fs[1] // translated to f2 := k.fs_2
  1. reflectパッケヌゞを䜿甚し、基本的に配列のように機胜したす
t := Tuple(int, float64, string){1, 2.0, "variadic"}

fs := reflect.ValueOf(t).Elem().FieldByName("fs")
val := reflect.ValueOf(fs)
if val.Kind() == reflect.VariadicTypes {
    for i := 0; i < val.Len(); i++ {
        e := val.Index(i)
        switch e.Kind() {
        case reflect.Int:
            fmt.Printf("%v, ", e.Int())
        case reflect.Float64:
            fmt.Printf("%v, ", e.Float())
        case reflect.String:
            fmt.Printf("%v, ", e.String())
        }
    }
}

配列の䜿甚ず比范しお、本圓に新しいものはありたせん。

たずえば、可倉個匕数の最小関数は珟圚の蚭蚈では䜿甚できたせんが、可倉個匕数の型パラメヌタヌでは䜿甚できたす。

func Min(type T ...Comparable)(p1 T, pn ...T) T {
    switch l := len(pn); {
    case l > 1:
        return Min(pn[0], pn[1:]...)
    case l == 1:
        if p1 >= pn[0] { return pn[0] }
        return p1
    case l < 1:
        return p1
    }
}

これは私には意味がありたせん。 可倉個匕数型パラメヌタヌは、型が異なる型である堎合にのみ意味がありたす。 ただし、さたざたなタむプのリストでMinを呌び出すこずは意味がありたせん。 Goは、さたざたなタむプの倀での>=の䜿甚をサポヌトしおいたせん。 どういうわけかそれを蚱可したずしおも、 Min(int, string)(1, "a")を求められるかもしれたせん。 それには䜕の答えもありたせん。

珟圚の蚭蚈では、異なるタむプの可倉個匕数の数のMinが蚱可されおいないこずは事実ですが、同じタむプの可倉個匕数の数の倀に察しおMinを呌び出すこずはサポヌトされおいたす。 ずにかくMinを䜿甚する唯䞀の合理的な方法だず思いたす。

func Min(type T comparable)(s ...T) T {
    if len(s) == 0 {
        panic("Min of no elements")
    }
    r := s[0]
    for _, v := range s[1:] {
        if v < r {
            r = v
        }
    }
    return r
}

https://github.com/golang/go/issues/15292#issuecomment -599040081の他の䟋のいく぀かに぀いおは、Goではスラむスず配列にすべお同じタむプの芁玠があるこずに泚意するこずが重芁です。 可倉個匕数型パラメヌタヌを䜿甚する堎合、芁玠は異なる型です。 したがっお、実際にはスラむスや配列ず同じではありたせん。

珟圚の蚭蚈では、異なるタむプの可倉個匕数の数のMinが蚱可されおいないこずは事実ですが、同じタむプの可倉個匕数の数の倀に察しおMinを呌び出すこずはサポヌトされおいたす。 ずにかくMinを䜿甚する唯䞀の合理的な方法だず思いたす。

func Min(type T comparable)(s ...T) T {
    if len(s) == 0 {
        panic("Min of no elements")
    }
    r := s[0]
    for _, v := range s[1:] {
        if v < r {
            r = v
        }
    }
    return r
}

本圓です。 Minは悪い䟋でした。 コメントの線集履歎からわかるように、远加が遅れお明確な考えがありたせんでした。 実際の䟋は、無芖したMetricです。

Goでは、スラむスず配列にはすべお同じタむプの芁玠があるこずに泚意するこずが重芁です。 可倉個匕数型パラメヌタヌを䜿甚する堎合、芁玠は異なる型です。 したがっお、実際にはスラむスや配列ず同じではありたせん。

芋る あなたは、これが配列/スラむスたたはマップのあいたいさであるず考える人々です。 https://github.com/golang/go/issues/15292#issuecomment -599040081で述べたように、構文は配列/スラむスずマップに非垞に䌌おいたすが、異なるタむプの芁玠にアクセスしおいたす。 それは本圓に重芁ですか たたは、これがあいたいであるこずを蚌明できたすか Go1で可胜なこずは次のずおりです。

m := map[interface{}]int{1: 2, "2": 3, 3.0: 4}
for i, e := range m {
    println(i, e)
}

iは同じタむプず芋なされたすか どうやら、私たちはinterface{} 、同じタむプだず蚀いたす。 しかし、むンタヌフェヌスは本圓にタむプを衚珟しおいたすか プログラマヌは、可胜なタむプを手動で確認する必芁がありたす。 for 、 []を䜿甚しお解凍する堎合、同じタむプにアクセスしおいないこずはナヌザヌにずっお本圓に重芁ですか これに察する議論は䜕ですか fsに぀いおも同じです

for idx, f := range k.fs {
    switch f.(type) { // compare to interface{}, here is zero overhead.
    case int:
        // ...
    case float64:
        // ...
    case string:
        // ...
    }
}

可倉個匕数のゞェネリック型の芁玠にアクセスするために型スむッチを䜿甚する必芁がある堎合、利点はわかりたせん。 コンパむル手法をいく぀か遞択するず、 interface{}を䜿甚するよりも実行時にわずかに効率が䞊がる可胜性があるこずがわかりたす。 しかし、その違いはかなり小さいず思いたす。なぜそれがタむプセヌフになるのかわかりたせん。 蚀語をより耇雑にする䟡倀があるかどうかはすぐにはわかりたせん。

Metricの䟋を無芖する぀もりはありたせんでした。可倉個匕数のゞェネリック型を䜿甚しお、蚘述を簡単にする方法がただわかりたせん。 Metricの本䜓でタむプスむッチを䜿甚する必芁がある堎合は、 Metric2ずMetric3ず曞くほうがいいず思いたす。

「蚀語をより耇雑にする」の定矩は䜕ですか ゞェネリックスは耇雑なものであり、Go 1よりも蚀語が単玔になるこずは決しおないずいうこずには誰もが同意したす。あなたはすでにゞェネリックスの蚭蚈ず実装に倚倧な努力を払っおいたすが、Goナヌザヌにずっおは非垞に䞍明確です。曞く...行く」 それを枬定するための定量化されたメトリックはありたすか 蚀語の提案は、それが蚀語をより耇雑にしおいないずどのように䞻匵するこずができたすか Go 2蚀語提案テンプレヌトでは、第䞀印象の目暙は非垞に単玔です。

  1. 倚くの人々にずっお重芁な問題に取り組み、
  2. 他のすべおの人ぞの圱響は最小限であり、
  3. 明確でよく理解された゜リュヌションが付属しおいたす。

しかし、質問は次のようになりたす。「倚く」はいく぀ですか。 「重芁」ずは䜕ですか 未知の母集団ぞの圱響を枬定する方法は 問題がよく理解されおいるずきは Goはクラりドを支配しおいたすが、科孊的な数倀コンピュヌティング機械孊習など、グラフィックレンダリング巚倧な3D垂堎などなどの他の分野を支配するこずは、Goのタヌゲットの1぀になりたすか 問題は、「GoでBよりもAを実行したいので、別の方法で実行できるため、ナヌスケヌスはありたせん」たたは「Bが提䟛されおいないため、Goずナヌスケヌスを䜿甚したせん」に圓おはたりたすか蚀語では簡単に衚珟できないので、ただありたせん」 ...これらの質問は苊痛で終わりがなく、時には答える䟡倀がないこずもありたす。

Metricの䟋に戻るず、個人にアクセスする必芁はありたせん。 パラメヌタセットをアンパックするこずは、ここでは実際の必芁性ではないようですが、既存の蚀語ず「䞀臎」する゜リュヌションは[ ]のむンデックス付けず型掚論を䜿甚しお、型セヌフの問題を解決できたす。

f2 := k.fs[1] // f2 is a float64

@changkunどの蚀語機胜が良いか悪いかを決定するための明確で客芳的な指暙があれば、蚀語デザむナヌは必芁ありたせん。プログラムを䜜成しお、最適な蚀語を蚭蚈するこずができたす。 しかし、そうではありたせん-それは垞にあるセットの人々の個人的な奜みに垰着したす。 それはたた、ずころで、蚀語が「良い」かどうかに぀いお議論するこずが意味をなさない理由です-唯䞀の問題は、あなたが個人的にそれを奜きかどうかです。 Goの堎合、奜みが決定するのはGoチヌムの人々であり、あなたが匕甚するものはメトリックではなく、圌らはあなたが圌らを説埗するのを助けるために質問を導きたす。

個人的には、FWIWでは、可倉個匕数型のパラメヌタヌが3぀のうち2぀で倱敗しおいるように感じたす。 倚くの人にずっお重芁な問題に察凊しおいるずは思いたせん。メトリックの䟋はそれらの恩恵を受ける可胜性がありたすが、IMOはほんのわずかであり、非垞に特殊なナヌスケヌスです。 そしお、私は圌らが明確でよく理解された解決策を持っおいるずは思いたせん。 私はこのようなものをサポヌトする蚀語を知りたせん。 しかし、私は間違っおいるかもしれたせん。 誰かがこれをサポヌトする他の蚀語の䟋を持っおいるなら、それは間違いなく圹に立ちたす-それはそれが通垞どのように実装されるか、そしおもっず重芁なこずにそれがどのように䜿われるかに぀いおの情報を提䟛するかもしれたせん。 倚分それは私が想像できるよりも広く䜿われおいたす。

@Merovius Haskellには、HListの論文で瀺したように倚倉量関数がありたす http //okmij.org/ftp/Haskell/polyvariadic.html#polyvar -fn
Haskellでこれを行うのは明らかに耇雑ですが、䞍可胜ではありたせん。

やる気を起こさせる䟋は、タむプセヌフな結合や射圱などを実行できるタむプセヌフなデヌタベヌスアクセスず、その蚀語で宣蚀されたデヌタベヌススキヌマです。

たずえば、デヌタベヌステヌブルは、列の名前ずタむプが存圚するレコヌドによく䌌おいたす。 リレヌショナル結合操䜜は、2぀の任意のレコヌドを取埗し、䞡方のタむプのレコヌドを生成したす。 もちろんこれは手䜜業で行うこずができたすが、間違いが発生しやすく、非垞に面倒で、手䜜業で宣蚀されたすべおのレコヌドタむプでコヌドの意味がわかりにくくなりたす。もちろん、SQLデヌタベヌスの倧きな特城は、アドホックをサポヌトしおいるこずです。ク゚リを実行するたで、必芁なク゚リが必ずしもわからないため、可胜なすべおのレコヌドタむプを事前に䜜成するこずはできたせん。

したがっお、レコヌドずタプルに察するタむプセヌフなリレヌショナル結合挔算子は、適切なナヌスケヌスになりたす。 ここでは、関数のタむプに぀いおのみ考えおいたす。関数が実際に䜕をするか、それがタプルの2぀の配列のメモリ内結合であるか、倖郚DBで実行しお結果をマヌシャリングするSQLを生成するかどうかは、プログラマヌ次第です。タむプセヌフな方法で戻りたす。

この皮のものは、LINQを䜿甚しおCに非垞にうたく埋め蟌むこずができたす。 ほずんどの人はLINQをCにラムダ関数ずモナドを远加するものず考えおいるようですが、同様の機胜がないずタむプセヌフな結合挔算子を定矩できないため、倚倉量なしの䞻なナヌスケヌスでは機胜したせん。

関係挔算子は重芁だず思いたす。 ブヌル型、バむナリ型、敎数型、浮動小数点型、文字列型の基本的な挔算子の埌に、セットが次に来る可胜性があり、次にリレヌションが続きたす。

ずころで、C ++もそれを提䟛したすが、XXXがそれを持っおいるので、Goでこの機胜が欲しいず䞻匵したくはありたせん:)

k.fs[0]ずk.fs[1]のタむプが異なるず、非垞に奇劙だず思いたす。 これは、Goで他のむンデックス可胜な倀がどのように機胜するかではありたせん。

指暙の䟋は、 https //medium.com/@sameer_74231/go-experience-report-for-generics-google-metrics-api-b019d597aaa4に基づいおいたす。 コヌドは倀を取埗するためにリフレクションが必芁だず思いたす。 可倉個匕数ゞェネリックをGoに远加する堎合は、倀を取埗するためにリフレクションよりも優れたものを取埗する必芁があるず思いたす。 そうでなければ、それはそれほど圹に立たないようです。

k.fs[0]ずk.fs[1]のタむプが異なるず、非垞に奇劙だず思いたす。 これは、Goで他のむンデックス可胜な倀がどのように機胜するかではありたせん。

指暙の䟋は、 https //medium.com/@sameer_74231/go-experience-report-for-generics-google-metrics-api-b019d597aaa4に基づいおいたす。 コヌドは倀を取埗するためにリフレクションが必芁だず思いたす。 可倉個匕数ゞェネリックをGoに远加する堎合は、倀を取埗するためにリフレクションよりも優れたものを取埗する必芁があるず思いたす。 そうでなければ、それはそれほど圹に立たないようです。

䞊手。 あなたは䜕かが存圚しないこずを芁求しおいたす。 [``]が気に入らない堎合は、残りの2぀のオプションがありたす。 ( )たたは{``}です。括匧は関数呌び出しのように芋え、䞭括匧は倉数の初期化のように芋えたす。 args.0 args.1は、Goのようには感じられないので、誰も奜きではありたせん。 構文は簡単です。

実際、私は週末に「C ++の蚭蚈ず進化」ずいう本を読んでいたす。1994幎に曞かれたものですが、決定ず教蚓に぀いお倚くの興味深い掞察がありたす。

_ "[...]振り返っおみるず、読みやすさず早期の゚ラヌ怜出における制玄の重芁性を過小評䟡しおいたした。" _ ==>倧契玄の蚭蚈

"_関数の構文も䞀芋するず、䜙分なキヌワヌドがなくおも芋栄えがしたす_

T& index<class T>(vector<T>& v, int i) { /*...*/ }
int i = index(v1, 10);

_この単玔な構文には、やっかいな問題があるようです。 賢すぎる。 [...] <...>括匧は、ナヌザヌが読みやすいず感じたため、括匧よりも優先しお遞択されたため、プログラムでテンプレヌト宣蚀を芋぀けるのは比范的困難です。 [...]たたたた、Tom Pennelloは、括匧の方が解析しやすいこずを蚌明したしたが、それでも人間の読者が<...> _を奜むずいう重芁な芳察結果は倉わりたせん。
"==> func F(type T C)(v T) Tに䌌おいたせんか

_ "ただし、テンプレヌト機胜の指定に関しおは、慎重すぎお保守的すぎたず思いたす。[...]などの機胜を含めるこずもできたす。これらの機胜は、実装者の負担を倧幅に増やすこずはありたせんでした。そしおナヌザヌは助けられたでしょう。」_

なんでこんなに銎染みがあるの

可倉個匕数型パラメヌタヌたたはタプルの玢匕付けは、実行時の玢匕付けおよびコンパむル時の玢匕付けずは別にする必芁がありたす。 ランタむムむンデックスのサポヌトがないこずは、コンパむル時のむンデックスず䞀貫性がないため、ナヌザヌを混乱させる可胜性があるずあなたは䞻匵するかもしれたせん。 コンパむル時のむンデックス䜜成の堎合でも、珟圚のデザむンには型以倖の「テンプレヌト」パラメヌタもありたせん。

すべおの蚌拠をもっお、提案経隓報告を陀くはこの機胜に぀いお議論するこずを避けようずしたす、そしお私はそれがGoに可倉個匕数のゞェネリックを远加するこずではなく、蚭蚈によっお削陀されただけだず信じ始めたす。

C ++の蚭蚈ず進化は良い本であるこずに同意したすが、C ++ずGoの目暙は異なりたす。 そこにある最埌の匕甚は良いものです。 Stroustrupは、蚀語のナヌザヌにずっおの蚀語の耇雑さのコストに぀いおも蚀及しおいたせん。 Goでは、垞にそのコストを考慮しようずしたす。 Goは単玔な蚀語を意図しおいたす。 ナヌザヌに圹立぀すべおの機胜を远加した堎合、それは単玔ではありたせん。 C ++は単玔ではないので。

すべおの蚌拠をもっお、提案経隓報告を陀くはこの機胜に぀いお議論するこずを避けようずしたす、そしお私はそれがGoに可倉個匕数のゞェネリックを远加するこずではなく、蚭蚈によっお削陀されただけだず信じ始めたす。

申し蚳ありたせんが、ここで䜕を意味するのかわかりたせん。

個人的には、可倉個匕数のゞェネリック型の可胜性を垞に考えおきたしたが、それがどのように機胜するかを理解するために時間を割いたこずはありたせん。 C ++での動䜜は非垞に埮劙です。 最初に非可倉個匕数ゞェネリックを機胜させるこずができるかどうかを確認したいず思いたす。 可胜であれば、埌で可倉個匕数ゞェネリックを远加する時間は確かにありたす。

私が以前の考えを批刀するずき、私は可倉個匕数型ができないず蚀っおいるのではありたせん。 解決する必芁があるず思う問題を指摘しおいたす。 それらを解決できない堎合、可倉個匕数タむプがそれに倀するずは確信しおいたせん。

Stroustrupは、蚀語のナヌザヌにずっおの蚀語の耇雑さのコストに぀いおも蚀及しおいたせん。 Goでは、垞にそのコストを考慮しようずしたす。 Goは単玔な蚀語を意図しおいたす。 ナヌザヌに圹立぀すべおの機胜を远加した堎合、それは単玔ではありたせん。 C ++は単玔ではないので。

本圓のIMOではありたせん。 C ++はゞェネリックスを匕き継ぐ最初の実践者であるこずに泚意する必芁がありたすたあMLは最初の蚀語です。 この本を読んだずころ、C ++は単玔な蚀語であるこずが意図されおいたずいうメッセヌゞが衚瀺されたす最初はゞェネリックスを提䟛しおいたせん、蚀語蚭蚈のための実隓-単玔化-出荷ルヌプ、同じ歎史。 C ++には、Goの「TheCompatability Promise」にある機胜凍結フェヌズも、数幎間ありたした。 しかし、倚くの合理的な理由により、時間の経過ずずもに少し制埡䞍胜になりたす。ゞェネリックスのリリヌス埌にC ++の叀いパスをキャッチした堎合、Goは明確ではありたせん。

可胜であれば、埌で可倉個匕数ゞェネリックを远加する時間は確かにありたす。

私にも同じ気持ち。 可倉個匕数ゞェネリックは、テンプレヌトの最初の暙準化バヌゞョンにもありたせん。

解決する必芁があるず思う問題を指摘しおいたす。 それらを解決できない堎合、可倉個匕数タむプがそれに倀するずは確信しおいたせん。

私はあなたの懞念を理解しおいたす。 しかし、問題は基本的に解決されおいたすが、Goに適切に翻蚳する必芁がありたすそしお、「翻蚳する」ずいう蚀葉が奜きな人はいないず思いたす。 私があなたの歎史的なゞェネリック医薬品の提案から読んだこずは、基本的にC ++の初期の提案で倱敗したものに埓い、Stroustrupが埌悔しおいるこずに劥協したものです。 私はこれに぀いおのあなたの反論に興味がありたす。

C ++の目暙に぀いおは意芋が分かれる必芁がありたす。 圓初の目暙はもっず䌌おいたかもしれたせんが、今日のC ++を芋るず、圌らの目暙がGoの目暙ずは倧きく異なるこずは明らかだず思いたす。少なくずも、25幎はそうだったず思いたす。

Goにゞェネリックスを远加するためのさたざたな提案を曞く際に、私はもちろん、C ++テンプレヌトがどのように機胜するか、および他の倚くの蚀語を調べたした結局、C ++はゞェネリックスを発明したせんでした。 Stroustrupが埌悔しおいるこずを芋おいなかったので、同じ堎所に来たら、それは玠晎らしいこずです。 私の考えでは、Goのゞェネリックは、C ++のようなものではなく、AdaたたはDのゞェネリックに䌌おいたす。 今日でも、C ++にはコントラクトがありたせん。コントラクトはコンセプトず呌ばれたすが、蚀語にはただ远加されおいたせん。 たた、C ++はコンパむル時に意図的に耇雑なプログラミングを蚱可し、実際にはC ++テンプレヌト自䜓がチュヌリング完党蚀語ですそれが意図的であったかどうかはわかりたせんが。 耇雑さが極端であるため、私は垞にGoで避けるべきものだず考えおきたしたただし、C ++では、Goにはないメ゜ッドのオヌバヌロヌドず解決のため、Goよりも耇雑です。

珟圚の契玄の実装を玄1か月間詊した埌、既存の組み蟌み関数の運呜は䜕であるか少し疑問に思いたす。 それらはすべお、䞀般的な方法で実装できたす。

func Append(type T)(slice []T, elems ...T) []T {...}
func Copy(type T)(dst, src []T) int {...}
func Delete(type K, V)(m map[K]V, k K) {...}
func Make(type T, I Integer(I))(siz ...I) T {...}
func New(type T)() *T {...}
func Close(type T)(c chan<- T) {...}
func Panic(type T)(v T) {...}
func Recover(type T)() T {...}
func Print(type ...T)(args ...T) {...}
func Println(type ...T)(args ...T) {...}

それらはGo2でなくなりたすか Go 2は、既存のGo1コヌドベヌスぞのこのような倧きな圱響にどのように察凊できるでしょうか。 これらは未解決の質問のようです。

さらに、これら2぀は少し特別です。

func Len(type T C)(t T) int {...}
func Cap(type T C)(t T) int {...}

タむプパラメヌタがゞェネリックスラむス[]Ts 、マップmap[Tk]Tv 、チャネルchan Tcのみになるように、珟圚の蚭蚈でこのようなコントラクトCを実装する方法T Ts Tk Tv Tcはどこが違うのですか

@changkun 「ゞェネリックで実装できる」ずいうのは、それらを削陀する説埗力のある理由ではないず思いたす。 そしお、あなたはそれらが削陀されるべきではないずいうかなり明確で匷力な理由に蚀及したす。 だから私は圌らがそうなるずは思わない。 それで残りの質問は時代遅れになるず思いたす。

@changkun 「ゞェネリックで実装できる」ずいうのは、それらを削陀する説埗力のある理由ではないず思いたす。 そしお、あなたはそれらが削陀されるべきではないずいうかなり明確で匷力な理由に蚀及したす。

はい、私はそれらを削陀するための説埗力がないこずに同意したす、それが私がそれを明瀺的に蚀った理由です。 ただし、ゞェネリックスず䞀緒にそれらを維持するこずは、蚀語機胜が盎亀しおいるGoの既存の哲孊に「違反」したす。 互換性が最倧の関心事ですが、コントラクトを远加するず、珟圚の巚倧な「時代遅れの」コヌドが削陀される可胜性がありたす。

だから私は圌らがそうなるずは思わない。 それで残りの質問は時代遅れになるず思いたす。

質問を無芖しないようにしお、それを実際の契玄のナヌスケヌスず芋なしおみたしょう。 同様の芁件が発生した堎合、珟圚の蚭蚈でどのように実装できたすか

明らかに、既存の事前に宣蚀された関数を削陀する぀もりはありたせん。

delete 、 close 、 panic 、 recover 、 print 、およびprintlnのパラメヌタヌ化された関数シグネチャを蚘述できたす。

https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-contracts.md#appendには、 AppendずCopyの郚分的なバヌゞョンがありたす。 appendずcopyには、珟圚の蚭蚈ドラフトではサポヌトされおいないタむプstringの2番目の匕数の特殊なケヌスがあるため、完党ではありたせん。

䞊蚘のMakeの眲名は、珟圚の蚭蚈ドラフトでは無効であるこずに泚意しおください。 Newはnewずたったく同じではありたせんが、十分に近いです。

珟圚の蚭蚈ドラフトでは、 LenずCapは、タむプinterface{}の匕数を取る必芁があるため、コンパむル時のタむプセヌフではありたせん。

https://go-review.googlesource.com/c/go/+/187317

.go2ファむル拡匵を䜿甚しないでください。この皮のバヌゞョンを実行するモゞュヌルがありたすか 契玄を実隓しおいる間、生掻を楜にするための䞀時的な解決策ずしおそれを行っおいるかどうかはわかりたすが、最終的にgo.modファむルがgoパッケヌゞを混合せずに泚意深く混合するこずを確認しおください.go2ファむル拡匵の必芁性。 モゞュヌルが可胜な限りうたく機胜するこずを確認しようず懞呜に努力しおいるモゞュヌル開発者にずっおは打撃ずなるでしょう。 .go2ファむル拡匵を䜿甚するこずは、蚀うようなものです。10幎前のモゞュヌル前の恐竜goコンパむラを壊したくないので、モゞュヌルの凊理がどうしおも気になりたせん。 。

@ gertcuykens.go2ファむルは実隓専甚です。 ゞェネリックがコンパむラに到達した堎合、これらは䜿甚されたせん。

コメントは実際にはディスカッションに远加されないため、コメントは非衚瀺にしたす。コメントはそのたたで十分な長さです。

最近、私が蚭蚈したK蚀語の新しいゞェネリック構文を調べたした。これは、KがGoから倚くの文法を借甚したためです。したがっお、このゞェネリック文法にはGoの参照倀も含たれおいる可胜性がありたす。

identifier<T>の問題は、比范挔算子やビット挔算子ず競合するこずです。そのため、この蚭蚈には同意したせん。

Scalaのidentifier[T]は以前のデザむンよりもルックアンドフィヌルが優れおいたすが、䞊蚘の競合を解決した埌、むンデックスデザむンidentifier[index]ずの新しい競合が発生したす。
このため、Scalaのむンデックスデザむンはidentifier(index)に倉曎されたした。 これは、すでに[]をむンデックスずしお䜿甚しおいる蚀語ではうたく機胜したせん。

Goのドラフトでは、ゞェネリックスは(type T)を䜿甚するこずが宣蚀されおいたす。これは、 typeがキヌワヌドであるため、競合は発生したせんが、コンパむラヌがidentifier(type)(params)を解決するために呌び出される堎合は、さらに刀断が必芁です。

偶然にも、OCでのメ゜ッド呌び出しの特別な蚭蚈を思い出したした。これは、新しい蚭蚈のむンスピレヌションを䞎えおくれたした。

識別子ずゞェネリックを党䜓ずしお入れお、それらを䞀緒に[]に入れるずどうなりたすか
[identifier T]を取埗できたす。 このデザむンは、スペヌスで区切られた少なくずも2぀の芁玠が必芁であるため、むンデックスず競合したせん。
耇数のゞェネリックが存圚する堎合、このように[identifier T V]ず曞くこずができ、既存の蚭蚈ず競合するこずはありたせん。

このデザむンをGoに眮き換えるず、次の䟋が埗られたす。
䟋えば

type [Item T] struct {
    Value T
}

func (it [Item T]) Print() {
    println(it.Value)
}

func [TestGenerics T V]() {
    var a = [Item T]{}
    a.Print()
    var b = [Item V]{}
    b.Print()
}

func main() {
    [TestGenerics int string]()
}

これは非垞に明確に芋えたす。

[]を䜿甚するもう1぀の利点は、Goの元のスラむスずマップのデザむンからある皋床継承されおおり、断片化の感芚を匕き起こさないこずです。

[]int  ->  [slice int]

map[string]int  ->  [map string int]

より耇雑な䟋を䜜るこずができたす

var a map[int][]map[string]map[string][]string

var b [map int [slice [map string [map string [slice string]]]]]

この䟋でも比范的明確な効果が維持されおいるず同時に、コンパむルにわずかな圱響がありたす。

私はこの蚭蚈をKで実装しおテストしたしたが、うたく機胜したす。

このデザむンには䞀定の参考倀があり、議論する䟡倀があるず思いたす。

最近、私が蚭蚈したK蚀語の新しいゞェネリック構文を調べたした。これは、KがGoから倚くの文法を借甚したためです。したがっお、このゞェネリック文法にはGoの参照倀も含たれおいる可胜性がありたす。

identifier<T>の問題は、比范挔算子やビット挔算子ず競合するこずです。そのため、この蚭蚈には同意したせん。

Scalaのidentifier[T]は以前のデザむンよりもルックアンドフィヌルが優れおいたすが、䞊蚘の競合を解決した埌、むンデックスデザむンidentifier[index]ずの新しい競合が発生したす。
このため、Scalaのむンデックスデザむンはidentifier(index)に倉曎されたした。 これは、すでに[]をむンデックスずしお䜿甚しおいる蚀語ではうたく機胜したせん。

Goのドラフトでは、ゞェネリックスは(type T)を䜿甚するこずが宣蚀されおいたす。これは、 typeがキヌワヌドであるため、競合は発生したせんが、コンパむラヌがidentifier(type)(params)を解決するために呌び出される堎合は、さらに刀断が必芁です。

偶然にも、OCでのメ゜ッド呌び出しの特別な蚭蚈を思い出したした。これは、新しい蚭蚈のむンスピレヌションを䞎えおくれたした。

識別子ずゞェネリックを党䜓ずしお入れお、それらを䞀緒に[]に入れるずどうなりたすか
[identifier T]を取埗できたす。 このデザむンは、スペヌスで区切られた少なくずも2぀の芁玠が必芁であるため、むンデックスず競合したせん。
耇数のゞェネリックが存圚する堎合、このように[identifier T V]ず曞くこずができ、既存の蚭蚈ず競合するこずはありたせん。

このデザむンをGoに眮き換えるず、次の䟋が埗られたす。
䟋えば

type [Item T] struct {
    Value T
}

func (it [Item T]) Print() {
    println(it.Value)
}

func [TestGenerics T V]() {
    var a = [Item T]{}
    a.Print()
    var b = [Item V]{}
    b.Print()
}

func main() {
    [TestGenerics int string]()
}

これは非垞に明確に芋えたす。

[]を䜿甚するもう1぀の利点は、Goの元のスラむスずマップのデザむンからある皋床継承されおおり、断片化の感芚を匕き起こさないこずです。

[]int  ->  [slice int]

map[string]int  ->  [map string int]

より耇雑な䟋を䜜るこずができたす

var a map[int][]map[string]map[string][]string

var b [map int [slice [map string [map string [slice string]]]]]

この䟋でも比范的明確な効果が維持されおいるず同時に、コンパむルにわずかな圱響がありたす。

私はこの蚭蚈をKで実装しおテストしたしたが、うたく機胜したす。

このデザむンには䞀定の参考倀があり、議論する䟡倀があるず思いたす。

すごい

䜕床か䜕床か読み盎した埌、私はGoのContractsの珟圚の蚭蚈ドラフトを党䜓的にサポヌトしたす。 倚倧な時間ず劎力を費やしおいただき、ありがずうございたす。 範囲、抂念、実装、およびほずんどのトレヌドオフは適切に芋えたすが、私の懞念は、読みやすさを向䞊させるために構文をオヌバヌホヌルする必芁があるこずです。

私はこれに察凊するために提案された䞀連の倉曎を曞きたした

重芁なポむントは次のずおりです。

  • コントラクト宣蚀のメ゜ッド呌び出し/タむプアサヌト構文
  • 「空の契玄」
  • 非括匧区切り文字

゚ッセむを先取りするリスクを冒しお、珟圚の契玄蚭蚈ドラフトのサンプルから倉換された構文ず説明をいく぀か瀺したす。 F«T»圢匏の区切り文字は䟋瀺的なものであり、芏範的なものではないこずに泚意しおください。 詳现に぀いおは、蚘事を参照しおください。

type List«type Element contract{}» struct {
    next *List«Element»
    val  Element
}

ず

contract viaStrings«To, From» {
    To.Set(string)
    From.String() string
}

func SetViaStrings«type To, From viaStrings»(s []From) []To {
    r := make([]To, len(s))
    for i, v := range s {
        r[i].Set(v.String())
    }
    return r
}

ず

func Keys«type K comparable, V contract{}»(m map[K]V) []K {
    r := make([]K, 0, len(m))
    for k := range m {
        r = append(r, k)
    }
    return r
}

k := maps.Keys(map[int]int{1:2, 2:4})

ず

contract Numeric«T» {
    T.(int, int8, int16, int32, int64,
        uint, uint8, uint16, uint32, uint64, uintptr,
        float32, float64,
        complex64, complex128)
}

func DotProduct«type T Numeric»(s1, s2 []T) T {
    if len(s1) != len(s2) {
        panic("DotProduct: slices of unequal length")
    }
    var r T
    for i := range s1 {
        r += s1[i] * s2[i]
    }
    return r
}

内郚でコントラクトを実際に倉曎しなくおも、Go開発者ずしおはこれがはるかに読みやすくなりたす。 たた、カリキュラムの埌半ではありたすがGoを孊んでいる人にこのフォヌムを教えるこずに自信がありたす。

@ianlancetaylor https://github.com/golang/go/issues/36533#issuecomment -579484523でのコメントに基づいお、新しい問題を開始するのではなく、このスレッドに投皿しおいたす。 Genericsフィヌドバックペヌゞにも蚘茉されおいたす。 それを「公匏に怜蚎」するために䜕か他のこずをする必芁があるかどうか぀たり、 Go 2提案レビュヌグルヌプ、たたはフィヌドバックがただ積極的に収集されおいるかどうかはわかりたせん。

契玄蚭蚈案から

C ++やJavaのように構文F<T>を䜿甚しおみたせんか
v := F<T>などの関数内のコヌドを解析する堎合、 <が衚瀺される時点で、型のむンスタンス化が衚瀺されおいるのか、 <挔算子を䜿甚した匏が衚瀺されおいるのかがあいたいです。 これを解決するには、効果的に無制限の先読みが必芁です。 䞀般に、Goパヌサヌをシンプルに保぀ように努めおいたす。

私の前回の投皿ず特に矛盟しおいたせん Goコントラクトのアングルブレヌス区切り文字

パヌサヌが混乱するこの点を回避する方法に関するいく぀かのアむデア。 カップルサンプル

// Lifted from the design draft
func New<type K, V>(compare func(K, K) int) *Map<K, V> {
    return &Map{<K, V> compare: compare}
}

// ...

func (m *Map<K, V>) InOrder() *Iterator<K, V> {
    sender, receiver := chans.Ranger(<keyValue<K, V>>)
    var f func(*node<K, V>) bool
    f = func(n *node<K, V>) bool {
        if n == nil {
            return true
        }
        // Stop sending values if sender.Send returns false,
        // meaning that nothing is listening at the receiver end.
        return f(n.left) &&
            sender.Send(keyValue{<K, V> n.key, n.val}) &&
            f(n.right)
    }
    go func() {
        f(m.root)
        sender.Close()
    }()
    return &Iterator{receiver}
}

// ...

基本的に、 <があいたいになる可胜性があるシナリオでは、型パラメヌタヌの䜍眮が異なりたす。

@tooolbox山かっこコメントに぀いお。 おかげで、個人的には、構文は、最初に型パラメヌタヌず型匕数に山かっこを䜿甚する必芁があるずいう決定を䞋し、次にそれらを打ち蟌む方法を考え出すようなものです。Goにゞェネリックスを远加する堎合は、目暙を蚭定する必芁があるず思いたす。既存の蚀語にきれいにそしお簡単に適合する䜕かのために。 䞭かっこ内で山かっこを動かすこずでその目暙が達成されるずは思いたせん。

はい、これは小さな詳现ですが、構文に関しおは、小さな詳现が非垞に重芁だず思いたす。 型匕数ずパラメヌタヌを远加する堎合、それらは単玔で盎感的な方法で機胜する必芁があるず思いたす。

私は確かに、珟圚の蚭蚈ドラフトの構文が完璧であるずは䞻匵しおいたせんが、既存の蚀語に簡単に適合しおいるず䞻匵しおいたす。 ここで行う必芁があるのは、実際にどの皋床うたく機胜するかを確認するために、さらにサンプルコヌドを䜜成するこずです。 重芁な点は、関数宣蚀の倖で実際に型匕数を蚘述しなければならない頻床ず、それらの堎合はどれほど混乱するかずいうこずです。 私たちは知らないず思いたす。

ゞェネリック型には[]を䜿甚し、ゞェネリック関数に()を䜿甚するこずをお勧めしたすか これは、珟圚のコアゞェネリックずより䞀貫性がありたす。

コミュニティはそれに投祚できたすか 個人的には、括匧を远加するよりも_䜕でも_したいのですが、クロヌゞャヌなどの関数定矩を読み取るのはすでに困難です。これにより、雑然ずしたものが远加されたす。

投祚は蚀語をデザむンする良い方法ではないず思いたす。 特に、決定するのが非垞に困難でおそらく䞍可胜、有暩者の数が非垞に倚い堎合はなおさらです。

Goの蚭蚈者ずコミュニティが、最良の゜リュヌションに集䞭し、
ですから、この䌚話で䜕かを怜蚎する必芁性を感じおいたせん。
しかし、私は私がどれほど予期せず喜んでいたかを蚀わなければなりたせんでした
F«T»構文の提案。

その他のUnicodeブラケット
https://unicode-search.net/unicode-namesearch.pl?term=BRACKET。

也杯、

  • ボブ

2020幎5月1日金曜日午埌7時43分[email protected]は次のように曞いおいたす。

䜕床か䜕床か読み盎した埌、私は党䜓的に
Goでの契玄の珟圚の蚭蚈ドラフト。 時間の長さに感謝したす
そしおそれに費やされた努力。 範囲、抂念、
実装、そしおほずんどのトレヌドオフは健党に芋える、私の懞念は
読みやすさを向䞊させるために、構文をオヌバヌホヌルする必芁がありたす。

私はこれに察凊するために提案された䞀連の倉曎を曞きたした

重芁なポむントは次のずおりです。

  • コントラクト宣蚀のメ゜ッド呌び出し/タむプアサヌト構文
  • 「空の契玄」
  • 非括匧区切り文字

゚ッセむを先取りするリスクを冒しお、サポヌトされおいないものをいく぀かあげたす
珟圚の契玄蚭蚈ドラフトのサンプルから倉換された構文。 ノヌト
F«T»圢匏の区切り文字は䟋瀺的なものであり、芏範的なものではありたせん。 芋る
詳现に぀いおは、蚘事をご芧ください。

タむプリスト«タむプ芁玠コントラクト{}»構造䜓{
次の*リスト«芁玠»
val芁玠
}

ず

コントラクトviaStrings«To、From»{
To.Set文字列
From.String文字列
}
func SetViaStrings«typeTo、From viaStrings»s [] From[] To {
r= make[] To、lens
for i、v= range s {
r [i] .Setv.String
}
rを返す
}

ず

func Keys«タむプKに匹敵、Vコントラクト{}»mmap [K] V[] K {
r= make[] K、0、lenm
kの堎合=範囲m {
r = appendr、k
}
rを返す
}
k= maps.Keysmap [int] int {12、24}

ず

契玄数倀«T»{
T.int、int8、int16、int32、int64、
uint、uint8、uint16、uint32、uint64、uintptr、
float32、float64、
complex64、complex128
}
funcDotProduct«typeT Numeric»s1、s2 [] TT {
if lens1= lens2{
panic "内積長さが等しくないスラむス"
}
var r T
for i= range s1 {
r + = s1 [i] * s2 [i]
}
rを返す
}

内郚で契玄を実際に倉曎するこずなく、これははるかに
Go開発者ずしお私には読める。 私もはるかに自信がありたす
Goを孊んでいる人にこのフォヌムを教える
カリキュラム。

@ianlancetaylorhttps //github.com/ianlancetaylorコメントに基づく
36533コメント
https://github.com/golang/go/issues/36533#issuecomment-579484523私は
新しい問題を開始するのではなく、このスレッドに投皿したす。 それもリストされおいたす
ゞェネリックフィヌドバックペヌゞ
https://github.com/golang/go/wiki/Go2GenericsFeedback 。 私かどうかわからない
それを「公匏に怜蚎」するために䜕か他のこずをする必芁がありたす぀たり、Go 2
プロポヌザルレビュヌグルヌプhttps://github.com/golang/go/issues/33892 たたは
フィヌドバックはただ積極的に収集されおいたす。

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-622657596 、たたは
登録を解陀する
https://github.com/notifications/unsubscribe-auth/AACQ2NJRBNLLDGY2XGCCQCLRPOCEHANCNFSM4CA35RXQ
。

私たちは皆、Goのために可胜な限り最高の構文を望んでいたす。 蚭蚈ドラフトでは、構文解析のあいたいさを倧​​幅に発生させるこずなくGoの残りの郚分で機胜するため、括匧を䜿甚しおいたす。 圌らが圓時の私たちの頭の䞭で最良の解決策であり、揚げる魚が倧きかったので、私たちは圌らず䞀緒にいたした。 これたでのずころ、それら括匧はかなりうたく持ちこたえおいたす。

結局のずころ、はるかに優れた衚蚘法が芋぀かった堎合、準拠する互換性の保蚌がない限り、倉曎は非垞に簡単ですパヌサヌは簡単に調敎され、コヌドの任意の本䜓を倉換できたす gofmtで簡単に。

@ianlancetaylor返信ありがずうございたす、ありがずうございたす。

あなたが正しいです; その構文は「型匕数に括匧を䜿甚しない」であり、私が最適だず感じたものを遞択しおから、パヌサヌの実装の問題を緩和するために倉曎を加えたした。

構文が読みにくい堎合䞀目で䜕が起こっおいるのかわかりにくい、既存の蚀語に本圓に簡単に適合したすか そこがスタンスが足りないず思いたす。

觊れおいるように、型掚論によっお、クラむアントコヌドで枡す必芁のある型匕数の量を倧幅に枛らすこずができるのは事実です。 私は個人的に、図曞通の䜜者はコヌドを䜿甚するずきにれロ型の匕数を枡すように努力する必芁があるず信じおいたすが、実際にはそうなりたす。

昚倜、偶然にも、いく぀かの点で驚くほど䌌おいるDのテンプレヌト構文に遭遇したした。

template Square(T) {
    T Square(T t) {
        return t * t;
    }
}

writefln("The square of %s is %s", 3, Square!(int)(3));

template TCopy(T) {
    void copy(out T to, T from) {
        to = from;
    }
}

int i;
TCopy!(int).copy(i, 3);

私が芋る2぀の重芁な違いがありたす

  1. テンプレヌトを䜿甚するためのむンスタンス化挔算子ずしお!がありたす。
  2. それらの宣蚀スタむル耇数の戻り倀がない、クラスにネストされたメ゜ッドは、通垞のコヌドでは括匧がネむティブに少ないこずを意味したす。したがっお、型パラメヌタヌに括匧を䜿甚しおも、同じ芖芚的なあいたいさは生じたせん。

むンスタンス化挔算子

コントラクトを䜿甚する堎合、䞻な芖芚的なあいたいさは、むンスタンス化ず関数呌び出したたは型倉換、たたは...の間にありたす。 これが問題ずなる理由の1぀は、むンスタンス化がコンパむル時であり、関数呌び出しが実行時であるずいうこずです。 Goには、各句がどのキャンプに属するかを読者に䌝える倚くの芖芚的な手がかりがありたすが、新しい構文はこれらを混乱させるため、タむプたたはプログラムフロヌを芋おいるかどうかは明らかではありたせん。

1぀の䞍自然な䟋

// Instantiation with unexported types and then function call,
// or chained method call?
a := draw(square, ellipse)(canvas, color)

提案むンスタンス化挔算子を䜿甚しお型パラメヌタヌを指定したす。 Dが䜿甚する!は完党に蚱容できるようです。 いく぀かのサンプル構文

// Lifted from the design draft
func New(type K, V)(compare func(K, K) int) *Map!(K, V) {
    return &Map!(K, V){compare: compare}
}

// ...

func (m *Map(K, V)) InOrder() *Iterator!(K, V) {
    sender, receiver := chans.Ranger!(keyValue!(K, V))()
    var f func(*node!(K, V)) bool
    f = func(n *node!(K, V)) bool {
        if n == nil {
            return true
        }
        // Stop sending values if sender.Send returns false,
        // meaning that nothing is listening at the receiver end.
        return f(n.left) &&
            sender.Send(keyValue!(K, V){n.key, n.val}) &&
            f(n.right)
    }
    go func() {
        f(m.root)
        sender.Close()
    }()
    return &Iterator{receiver}
}

// ...

私の個人的な芋地からするず、䞊蚘のコヌドは桁違いに読みやすくなっおいたす。 これにより、芖芚的にもパヌサヌにずっおも、すべおのあいたいさが解消されるず思いたす。 さらに、これが契玄に加えるこずができる唯䞀の最も重芁な倉曎である可胜性があるかどうか疑問に思いたす。

宣蚀スタむル

タむプ、関数、およびメ゜ッドを宣蚀する堎合、「実行時たたはコンパむル時」は少なくなりたす。 問題。 Gopherは、 typeたたはfuncで始たる行を芋お、プログラムの動䜜ではなく、宣蚀を芋おいるこずを知っおいたす。

ただし、いく぀かの芖芚的なあいたいさはただ存圚したす。

// Type-parameterized function,
// or function with multiple return values?
func Draw(cvs canvas, t tool)(canvas, tool) {
    // ...
}
func Draw(type canvas, tool)(cvs canvas, t tool) {
    // ...
}

// Type-parameterized struct, or function call?
func Set(elem constructible) rect {
    // ...
}
type Set(type Elem comparable) struct{
    // ...
}

// Method call, or type-parameterized function?
func Map(type Element)(s []Element, f func(Element) Element) (results []Element) {
    // ...
}
func (t Element) Map(s []Element, f func(Element) Element) (results []Element) {
    // ...
}

考え

  • これらの問題は、むンスタンス化の問題ほど重芁ではないず思いたす。
  • 最も明癜な解決策は、型匕数に䜿甚される区切り文字を倉曎するこずです。
  • おそらく、そこに他の皮類の挔算子たたは文字を入れるず !が倱われる可胜性がありたすが、 #どうでしょうか、曖昧さを解消できたす。

線集 @griesemer远加の説明に感謝したす

ありがずう。 自然な質問を投げかけるだけです。特定の呌び出しが実行時に評䟡されるのか、コンパむル時に評䟡されるのかを知るこずが重芁なのはなぜですか。 なぜそれが重芁な質問なのですか

@tooolbox

// Instantiation with unexported types and then function call,
// or chained method call?
a := draw(square, ellipse)(canvas, color)

なぜそれがどちらの方法でも重芁なのでしょうか カゞュアルな読者の堎合、これがコンパむル時たたは実行時に実行されたコヌドであるかどうかは関係ありたせん。 他のすべおの人にずっお、圌らは関数の定矩を䞀瞥するだけで䜕が起こっおいるのかを知るこずができたす。 埌の䟋は、たったくあいたいではないようです。

実際、型パラメヌタヌに()を䜿甚するこずは、関数を返す関数を呌び出しおいるように芋えるため、ある皋床意味がありたす。これは倚かれ少なかれ正しいこずです。 違いは、最初の関数が型を受け入れるこずです。これは通垞倧文字であるか、非垞によく知られおいたす。

この段階では、色ではなく、小屋の寞法を把握するこずがはるかに重芁です。

@tooolboxが話しおいるのは、コンパむル時ず実行時の違いではないず思いたす。 はい、それは1぀の違いですが、重芁な違いではありたせん。 重芁なのは、これは関数呌び出しですか、それずも型宣蚀ですか。 それらの動䜜が異なるため、知りたいのですが、ある匏が2぀の関数呌び出しを行っおいるのか1぀を行っおいるのかを掚枬する必芁はありたせん。これは、倧きな違いです。 ぀たり、 a := draw(square, ellipse)(canvas, color)のような衚珟は、呚囲の環境を調べる䜜業を行わないずあいたいになりたす。

プログラムの制埡フロヌを芖芚的に解析できるこずが重芁です。 Goはその良い䟋だず思いたす。

ありがずう。 自然な質問を投げかけるだけです。特定の呌び出しが実行時に評䟡されるのか、コンパむル時に評䟡されるのかを知るこずが重芁なのはなぜですか。 なぜそれが重芁な質問なのですか

申し蚳ありたせんが、コミュニケヌションがうたくいかなかったようです。 これは私が䌝えようずしおいた重芁なポむントです。

タむプたたはプログラムフロヌを芋おいるかどうかは明らかではありたせん

珟時点では、1぀はコンパむル䞭に分類され、もう1぀は実行時に発生したすが、これらは...特性であり、 @ infogulchが正しく取埗した重芁なポむントではありたせん。ありがずうございたす


ドラフトのゞェネリックスは関数呌び出しに䟋えるこずができるずいう意芋をいく぀かの堎所で芋たした。これは、実際の関数たたは型を返す䞀皮のコンパむル時関数です。 これは、コンパむル䞭に発生するこずのメンタルモデルずしおは圹立ちたすが、構文的には倉換されたせん。 構文的には、関数のように名前を付ける必芁がありたす。 次に䟋を瀺したす。

// Example from the Contracts draft
Print(int)([]int{1, 2, 3})

// New naming that communicates behavior and intent
MakePrintFunc(int)([]int{1, 2, 3}) // Chained function call, great!

そこでは、それは実際には関数を返す関数のように芋えたす。 かなり読みやすいず思いたす。

もう1぀の方法は、すべおにTypeの接尟蟞を付けるこずです。そのため、関数を「呌び出す」ず、型を取埗しおいるこずが名前から明らかです。 それ以倖の堎合、たずえば Pair(...)が構造䜓ではなく構造䜓型を生成するこずは明らかではありたせん。 しかし、その芏則が実斜されおいる堎合、このコヌドは明確になりたす a := drawType(square, ellipse)(canvas, color)

前䟋はむンタヌフェヌスの「-er」芏則であるこずを理解しおいたす。

私は䞊蚘を解決策ずしお特にサポヌトしおいないこずに泚意しおください。「関数ずしおのゞェネリック」が珟圚の構文で完党か぀明確に衚珟されおいないこずを説明しおいるだけです。


繰り返しになりたすが、 @ infogulchは私のポむントを非垞にうたく芁玄しおいたす。 私は、型匕数が型の䞀郚であるこずを明確にするために、型匕数を芖芚的に区別するこずをサポヌトしおいたす。

おそらく、その芖芚的な郚分は、゚ディタヌの構文の匷調衚瀺によっお匷化されるでしょう。

パヌサヌに぀いお、そしおどのようにしお先読みをしすぎないかに぀いおはよくわかりたせん。

ナヌザヌの芳点からは、コヌドにさらに別の文字を衚瀺したくないので、 «»はサポヌトされたせんキヌボヌドで文字が芋぀かりたせんでした。

ただし、䞞括匧の埌に䞞括匧が続くのを芋るのも、あたり目を楜したせおくれたせん。

䞭かっこを䜿甚するのは簡単ですか

a := draw{square, ellipse}(canvas, color)

ただし、 Print(int)([]int{1,2,3})では、動䜜の違いは「コンパむル時ず実行時」だけです。 はい、 MakePrintFunc Print $ 1 $$を䜿甚するず、この類䌌性がより匷調されたすが、  MakePrintFuncを䜿甚しないずいう議論ではありたせんか それは実際に実際の行動の違いを隠しおいるからです。

FWIW、どちらかずいえば、パラメトリック関数ずパラメトリック型に異なるセパレヌタヌを䜿甚するこずを䞻匵しおいるようです。 Print(int)は、実際には関数を返す関数コンパむル時に評䟡されるず同等であるず考えるこずができたすが、 Pair(int, string)はできないため、型を返す関数です。 Print(int)は、実際にはfunc倀に評䟡される有効な匏ですが、 Pair(int, string)は有効な匏ではなく、型仕様です。 したがっお、䜿甚法の本圓の違いは、「ゞェネリック関数ず非ゞェネリック関数」ではなく、「ゞェネリック関数ずゞェネリック型」です。 そしお、そのPOVから、実際に倀を衚すためのパラメトリック関数の性質を匷調しおいるため、少なくずもパラメトリック関数には()を䜿甚する必芁があるず思いたす。おそらく<>を䜿甚する必芁がありたす。パラメトリックタむプの堎合

パラメトリック型の()の議論は、関数型プログラミングから来おいるず思いたす。これらの関数を返す型は、型構築子ず呌ばれる実際の抂念であり、実際に関数ずしお䜿甚および参照できたす。 そしおFWIW、それは私がパラメトリック型に()を䜿甚しないこずを䞻匵しない理由でもありたす。 個人的に、私はこの抂念に非垞に満足しおおり、パラメトリック関数をパラメトリック型から明確にするずいう利点よりも、異なるセパレヌタヌが少ないずいう利点を奜みたす-結局のずころ、型たたは倀のいずれかを参照する玔粋な識別子にも問題はありたせん。

@tooolboxが話しおいるのは、コンパむル時ず実行時の違いではないず思いたす。 はい、それは1぀の違いですが、重芁な違いではありたせん。 重芁なのは、これは関数呌び出しですか、それずも型宣蚀ですか。 動䜜が異なり、匏が2぀の関数呌び出しを行っおいるのか1぀を行っおいるのかを掚枬する必芁がないため、知りたいず思いたす。これは倧きな違いです。 ぀たり、 a := draw(square, ellipse)(canvas, color)のような衚珟は、呚囲の環境を調べる䜜業を行わないずあいたいになりたす。

プログラムの制埡フロヌを芖芚的に解析できるこずが重芁です。 Goはその良い䟋だず思いたす。

型宣蚀はすべおキヌワヌドtypeで始たるため、非垞に芋やすくなりたす。 あなたの䟋は明らかにそれらの1぀ではありたせん。

おそらく、その芖芚的な郚分は、゚ディタヌの構文の匷調衚瀺によっお匷化されるでしょう。

理想的には、どんな色でも構文は明確でなければならないず思いたす。 それは囲碁の堎合であり、私はその基準から降りるのは良いこずではないず思いたす。

䞭かっこを䜿甚するのは簡単ですか

残念ながら、これは構造䜓リテラルず矛盟するず思いたす。

ただし、 Print(int)([]int{1,2,3})では、動䜜の違いは「コンパむル時ず実行時」だけです。 はい、 MakePrintFunc Print $ 1 $$を䜿甚するず、この類䌌性がより匷調されたすが、  MakePrintFuncを䜿甚しないずいう議論ではありたせんか それは実際に実際の行動の違いを隠しおいるからです。

ええず、䞀぀には、これが私がMakePrintFunc(int)([]int{1,2,3}) $よりも$ Print!(int)([]int{1,2,3})をサポヌトする理由です。 䜕かナニヌクなこずが起こっおいるのは明らかです。

しかし、繰り返しになりたすが、 @ ianlancetaylorが以前に尋ねた質問型のむンスタンス化/関数を返す関数がコンパむル時ず実行時のどちらであるかが重芁なのはなぜですか

考えおみれば、関数呌び出しをいく぀か䜜成し、コンパむラヌがそれらを最適化しおコンパむル時に結果を蚈算できれば、パフォヌマンスが向䞊するこずに満足するでしょう。 むしろ、重芁な偎面は、コヌドが䜕をしおいるのか、どのように動䜜するのかずいうこずです。 それは䞀目で明らかなはずです。

Print(...)を芋るず、私の最初の本胜は「どこかに曞き蟌む関数呌び出しです」です。 「これは関数を返したす」ずは通信したせん。 私の意芋では、これらのいずれも、行動ず意図を䌝えるこずができるため、より優れおいたす。

  • MakePrintFunc(...)
  • Print!(...)
  • Print<...>

蚀い換えるず、このコヌドは、次のコヌドで呌び出すこずができる関数を「参照」たたは䜕らかの方法で「提䟛」したす。

FWIW、どちらかずいえば、パラメトリック関数ずパラメトリック型に異なるセパレヌタヌを䜿甚するこずを䞻匵しおいるようです。 ..。

いいえ、最埌のいく぀かの䟋が関数に関するものであるこずは知っおいたすが、パラメトリック関数ずパラメトリック型の䞀貫した構文を提唱したす。 ゞェネリックスが統䞀された構文を持぀統䞀された抂念でない限り、GoチヌムがゞェネリックスをGoに远加するずは思わない。

Print(...)を芋るず、私の最初の本胜は「どこかに曞き蟌む関数呌び出しです」です。 「これは関数を返したす」ずは通信したせん。

Print(
)ず呌ばれる堎合、 func Print(
) func(
)も同様です。 それでも、私たちは集合的にそれで倧䞈倫です。 特別な呌び出し構文がない堎合、関数がfuncを返す堎合。
Print(
)構文は、今日の動䜜をほが正確に瀺しおいたす。そのPrintは、 Print(
)が評䟡する倀を返す関数です。 関数が返す型に興味がある堎合は、その定矩を芋おください。
たたは、おそらく、関数を返すこずを瀺すむンゞケヌタヌずしお、実際にはPrint(
)(
)であるずいう事実を䜿甚したす。

考えおみれば、関数呌び出しをいく぀か䜜成し、コンパむラヌがそれらを最適化しおコンパむル時に結果を蚈算できれば、パフォヌマンスが向䞊するこずに満足するでしょう。

もちろん。 私たちはすでにそれを持っおいたす。 たた、特別な構文アノテヌションを䜜成するために特定の構文アノテヌションが必芁ないこずを非垞に嬉しく思いたすが、コンパむラヌがこれらの関数のヒュヌリスティックを継続的に改善するこずを信頌できたす。

私の意芋では、これらのいずれも、行動ず意図を䌝えるこずができるため、より優れおいたす。

最初のものは少なくずもデザむンず100互換性があるこずに泚意しおください。 䜿甚される識別子の圢匏は芏定されおいたせん。その芏定を提案しないでくださいもしそうなら、 funcを返すだけに同じ芏則が適甚されない理由に興味がありたす。 。

いいえ、最埌のいく぀かの䟋が関数に関するものであるこずは知っおいたすが、パラメトリック関数ずパラメトリック型の䞀貫した構文を提唱したす。

さお、私が蚀ったように、私は同意したす:)私はあなたがしおいる議論が「ゞェネリック察非ゞェネリック」軞に沿っおどのように適甚できるか理解しおいないず蚀っおいたす。二぀。 䜕かが型仕様であるか匏であるかは、それを䜿甚できるコンテキストにずっお非垞に重芁であるため、これらは「型ず関数」の軞に沿っお意味がありたす。私はただ同意したせんが、少なくずも私は理解したす圌ら 

@Meroviusコメントありがずうございたす。

Print(
)ず呌ばれる堎合、 func Print(
) func(
)も同様です。 それでも、私たちは集合的にそれで倧䞈倫です。 特別な呌び出し構文なしで、関数が関数を返す堎合。
Print(
)構文は、今日の動䜜をほが正確に瀺しおいたす。そのPrintは、 Print(
)が評䟡する倀を返す関数です。 関数が返す型に興味がある堎合は、その定矩を芋おください。

私は、関数の名前はその機胜に関連しおいるべきだず考えおいたす。 したがっお、 Print(...)は、䜕が返されるかに関係なく、䜕かを印刷するこずを期埅しおいたす。 これは合理的な期埅であり、既存のGoコヌドの倧郚分で満たされる可胜性があるず思いたす。

Print(...)(...)が衚瀺された堎合、最初の()が䜕かを出力し、関数が䜕らかの関数を返し、2番目の()がその远加の動䜜を実行しおいるこずを瀺しおいたす。 。

これが珍しい、たたはたれな意芋だったずしたら驚きたすが、いく぀かの調査結果に぀いおは議論したせん。

最初のものは少なくずもデザむンず100互換性があるこずに泚意しおください。 䜿甚される識別子の圢匏は芏定されおいないので、芏定するこずを提案しないでくださいもしそうなら、同じ芏則が関数を返すだけに適甚されない理由に興味がありたす。

あなたは正しいです私はそれを提案したした:)

ほら、関数ず型の型パラメヌタによっおもたらされる芖芚的な曖昧さを修正するために私が考えるこずができる3぀の方法をリストしたした。 あいたいさが芋られない堎合は、どの提案も気に入らないでしょう。

「ゞェネリックvs.非ゞェネリック」軞に沿っおあなたが行っおいる議論をどのように適甚できるか理解しおいないず蚀っおいるだけです。2぀の間に重芁な行動の倉化はないからです。 䜕かが型仕様であるか匏であるかは、それを䜿甚できるコンテキストにずっお非垞に重芁であるため、これらは「型ず関数」の軞に沿っお意味がありたす。

あいたいさに関する䞊蚘のポむントず3぀の提案された解決策を参照しおください。

タむプパラメヌタは新しいものです。

  • それらを新しいものずしお掚論したい堎合は、区切り文字を倉曎するか、むンスタンス化挔算子を远加しお、通垞のコヌド関数呌び出し、型倉換などず完党に区別するこずを提案したす。
  • それらを単なる別の関数ずしお掚論したい堎合は、 identifier(...)のidentifierが動䜜ず戻り倀を䌝達するように、これらの関数に明確に名前を付けるこずを提案したす。

私は前者が奜きです。 どちらの堎合も、説明したように、倉曎は型パラメヌタヌ構文党䜓でグロヌバルになりたす。

これに光を圓おる方法は他にもいく぀かありたす。

  1. 調査
  2. チュヌトリアル

1.調査

序文これは民䞻䞻矩ではありたせん。 意思決定はデヌタに基づいおいるず思いたす。明確な論理ず広範な調査デヌタの䞡方が意思決定プロセスに圹立ちたす。

私にはこれを行う手段がありたせんが、「これらを明確にランク付けする」こずで数千匹のGopherを調査した堎合、どうなるか知りたいず思いたす。

ベヌスラむン

// Lifted from the design draft
func New(type K, V)(compare func(K, K) int) *Map(K, V) {
    return &Map(K, V){compare: compare}
}

// ...

func (m *Map(K, V)) InOrder() *Iterator(K, V) {
    sender, receiver := chans.Ranger(keyValue(K, V))()
    var f func(*node(K, V)) bool
    f = func(n *node(K, V)) bool {
        if n == nil {
            return true
        }
        // Stop sending values if sender.Send returns false,
        // meaning that nothing is listening at the receiver end.
        return f(n.left) &&
            sender.Send(keyValue(K, V){n.key, n.val}) &&
            f(n.right)
    }
    go func() {
        f(m.root)
        sender.Close()
    }()
    return &Iterator{receiver}
}

// ...

むンスタンス化挔算子

// Lifted from the design draft
func New(type K, V)(compare func(K, K) int) *Map!(K, V) {
    return &Map!(K, V){compare: compare}
}

// ...

func (m *Map(K, V)) InOrder() *Iterator!(K, V) {
    sender, receiver := chans.Ranger!(keyValue!(K, V))()
    var f func(*node!(K, V)) bool
    f = func(n *node!(K, V)) bool {
        if n == nil {
            return true
        }
        // Stop sending values if sender.Send returns false,
        // meaning that nothing is listening at the receiver end.
        return f(n.left) &&
            sender.Send(keyValue!(K, V){n.key, n.val}) &&
            f(n.right)
    }
    go func() {
        f(m.root)
        sender.Close()
    }()
    return &Iterator{receiver}
}

// ...

アングルブレヌス:(たたはいずれかの方法でダブルアングルブレヌス

// Lifted from the design draft
func New<type K, V>(compare func(K, K) int) *Map<K, V> {
    return &Map<K, V>{compare: compare}
}

// ...

func (m *Map<K, V>) InOrder() *Iterator<K, V> {
    sender, receiver := chans.Ranger<keyValue<K, V>>()
    var f func(*node<K, V>) bool
    f = func(n *node<K, V>) bool {
        if n == nil {
            return true
        }
        // Stop sending values if sender.Send returns false,
        // meaning that nothing is listening at the receiver end.
        return f(n.left) &&
            sender.Send(keyValue<K, V>{n.key, n.val}) &&
            f(n.right)
    }
    go func() {
        f(m.root)
        sender.Close()
    }()
    return &Iterator{receiver}
}

// ...

適切な名前の関数

// Lifted from the design draft
func NewConstructor(type K, V)(compare func(K, K) int) *MapType(K, V) {
    return &MapType(K, V){compare: compare}
}

// ...

func (m *MapType(K, V)) InOrder() *IteratorType(K, V) {
    sender, receiver := chans.RangerType(keyValueType(K, V))()
    var f func(*nodeType(K, V)) bool
    f = func(n *nodeType(K, V)) bool {
        if n == nil {
            return true
        }
        // Stop sending values if sender.Send returns false,
        // meaning that nothing is listening at the receiver end.
        return f(n.left) &&
            sender.Send(keyValueType(K, V){n.key, n.val}) &&
            f(n.right)
    }
    go func() {
        f(m.root)
        sender.Close()
    }()
    return &Iterator{receiver}
}

// ...

...おかしい、私は実際に最埌のものがずおも奜きです。

これらはGophers @Meroviusの広い䞖界でどのようにうたくいくず思いたすか

2.チュヌトリアル

これは非垞に䟿利な挔習になるず思いたす。お気に入りの構文の初心者向けのチュヌトリアルを䜜成し、それを読んで適甚しおもらう人もいたす。 コンセプトはどれくらい簡単に䌝えられたすか FAQずは䜕ですかどのように答えたすか

デザむンドラフトは、経隓豊富なGopherにコンセプトを䌝えるこずを目的ずしおいたす。 それは論理の連鎖に埓い、ゆっくりずあなたを浞したす。 簡朔なバヌゞョンは䜕ですか 簡単に理解できる1぀のブログ投皿で、契玄のゎヌルデンルヌルをどのように説明したすか

これにより、通垞のフィヌドバックレポヌトずは異なる角床たたはデヌタのスラむスが衚瀺される可胜性がありたす。

@tooolboxただ答えおいないのは、次のずおりです。これは、パラメトリック関数では問題になるのに、 funcを返すノンパラメトリック関数では問題にならないのはなぜですか。 今日は曞くこずができたす

func Print(a string) func(string) {
    return func(b string) {
        fmt.Println(a+b)
    }
}

func main() {
    Print("foo")("bar")
}

なぜこれで問題がなく、あいたいさに非垞に混乱するこずはありたせんが、 Printが倀パラメヌタヌではなく型パラメヌタヌを受け取るずすぐに、これは耐えられなくなりたすか たた、明らかな互換性の質問は別ずしお適切に実行するための制限を远加するこずも提案したす。これは、 Printの名前がMakeXFunc X倉曎されない限り䞍可胜です。

@tooolboxは、型掚論によっお関数のパラメトリック型を指定する必芁がなくなり、単玔な関数呌び出しだけが残る可胜性があるずいう仮定の堎合、これは本圓に問題になりたすか

@Merovius問題は、構文Print("foo")("bar")自䜓にあるずは思いたせん。これは、Go 1ですでに可胜であるためです。これは、可胜な解釈が1぀しかないためです。 問題は、倉曎されおいない提案では、匏Foo(X)(Y)があいたいになり、Go 1のように2぀の関数呌び出しを行っおいるか、型匕数を䜿甚しお1぀の関数呌び出しを行っおいるこずを意味しおいる可胜性がありたす。 。 問題は、プログラムが䜕をするかをロヌカルで掚枬できるこずであり、これら2぀の可胜な意味解釈は非垞に異なりたす。

@urandom型掚論により、明瀺的に提䟛された型パラメヌタヌの倧郚分を排陀できる可胜性があるこずに同意したすが、ほずんど䜿甚されないずいう理由だけで、認知の耇雑さをすべお蚀語の暗い隅に抌し蟌むのは良い考えではないず思いたすたた。 ほずんどの人が通垞それらに遭遇しないこずは十分にたれですが、それでも時々遭遇し、「ほずんどの」コヌドでない限り、いく぀かのコヌドが混乱する制埡フロヌを持぀こずを蚱可するず、私の口に悪い味が残りたす。 特に、Goは珟圚、stdlibを含む「配管」コヌドを読むずきに非垞に芪しみやすいためです。 たぶん、型掚論は非垞に優れおいるため、「たれ」は「決しお」なくなり、Goプログラマヌは高床な芏埋を保ち、型パラメヌタヌが必芁なシステムを蚭蚈するこずはありたせん。 この堎合、この問題党䜓は基本的に議論の䜙地がありたす。 しかし、私はそれには賭けたせん。

@tooolboxの議論の䞻な目的は、既存の構文を状況䟝存のセマンティクスで軜快にオヌバヌロヌドしおはならず、代わりに、あいたいではない他の構文を芋぀ける必芁があるこずだず思いたす Foo(X)!(Y) 。構文オプションを怜蚎する堎合、これは重芁な手段だず思いたす。

私は昔〜2008-2009に少しのDコヌドを䜿甚しお読みたしたが、 !はい぀も私を぀たずかせおいたず蚀わなければなりたせん。

代わりに、この小屋を# 、 $ 、たたは@のいずれかでペむントしたすGoたたはCでは意味がないため。
これにより、マップ、スラむス、たたは構造䜓ずの混同なしに䞭括匧を䜿甚できる可胜性が広がりたす。

  • Foo@{X}(Y)
  • Foo${X}(Y)
  • Foo#{X}(Y)
    たたは角かっこ。

このような議論では、実際のコヌドを調べるこずが䞍可欠です。

たずえば、 Foo(X)(Y)ず曞く人はほずんどいないず考えおください。 Goでは、型名ず倉数名および関数名はたったく同じように芋えたすが、人々は自分が芋おいるものに぀いお混乱するこずはめったにありたせん。 int64(v)は型倉換であり、 F(v)はたったく同じように芋えたすが、関数呌び出しであるこずを人々は理解しおいたす。

実際のコヌドを調べお、型匕数が実際に本圓に混乱しおいるかどうかを確認する必芁がありたす。 そうである堎合は、構文を調敎する必芁がありたす。 実際のコヌドがない堎合、私たちは単に知りたせん。

2020幎5月6日氎曜日の13:00に、Ian LanceTaylorは次のように曞いおいたす。

int64(v)は型倉換であり、 F(v)は型倉換であるこずを人々は理解しおいたす
たったく同じように芋えたすが、関数呌び出し。

私は今、提案に぀いおどちらの意芋も持っおいたせん
構文ですが、この特定の䟋はあたり良いずは思いたせん。 それはかもしれたせん
組み蟌み型に぀いおは真実ですが、私は実際にこれに混乱しおいたす
自分自身で䜕床か正確な問題私は関数を探しおいたした
定矩ず、以前のコヌドの動䜜に぀いお非垞に混乱しおいる
タむプの可胜性が高いこずに気づき、関数が芋぀からなかったため
それは関数呌び出しではありたせんでした。 䞖界の終わりではなく、そしお
掟手なIDEが奜きな人にずっおは、おそらくたったく問題にはなりたせんが、私は
これを䜕床も繰り返しお5分ほど無駄にしたした。

-サム

-
サムホワむトド

@ianlancetaylorあなたの䟋で気付いたのは、型を取り、同じ意味を持぀別の型を返す関数を蚘述できるこずです。したがっお、 int64(v)のような基本的な型倉換ずしお型を呌び出すこずは意味がありたす。 strconv.Atoi(v)が理にかなっおいるのず同じように。

ただし、 UseConverter(strconv.Atoi)は実行できたすが、Go 1ではUseConverter(int64)は䜿甚できたせん。次のようにゞェネリックをキャストに䜿甚できる堎合、typeパラメヌタヌの括匧を䜿甚するず、いく぀かの可胜性が開かれる可胜性がありたす。

func StrToNumber(type K)(s string) K {
  asInt := strconb.Atoi(s)
  return K(asInt)
}

なぜこれは倧䞈倫であり、あいたいさによっおあなたを非垞に混乱させるこずはありたせん

あなたの䟋は倧䞈倫ではありたせん。 最初の呌び出しが匕数を取るか、パラメヌタヌを入力するかは関係ありたせん。 䜕も出力しないPrint関数がありたす。 そのコヌドを読んだりレビュヌしたりするこずを想像できたすか 2番目の括匧のセットが省略されたPrint("foo")は問題ないように芋えたすが、密かに操䜜はできたせん。

そのコヌドをPRで提出した堎合は、名前をPrintFunc 、 MakePrintFunc 、 PrintPlusFunc 、たたはその動䜜を䌝えるものに倉曎するように指瀺したす。

私は昔〜2008-2009に少しDコヌドを䜿っお読んだのですが、ず蚀わなければなりたせん。 い぀も私を぀たずかせおいたした。

はぁ、おもしろい。 むンスタンス化挔算子には特に奜みはありたせん。 それらはたずもなオプションのようです。

Goでは、型名ず倉数名および関数名はたったく同じように芋えたすが、人々は自分が芋おいるものに぀いお混乱するこずはめったにありたせん。 芋た目はたったく同じですが、int64vは型倉換であり、Fvは関数呌び出しであるこずを人々は理解しおいたす。

私は同意したす。人々は通垞、型倉換ず関数呌び出しをすばやく区別できたす。 なぜだず思いたすか

私の個人的な理論では、型は通垞名詞であり、関数は通垞動詞です。 したがっお、 Noun(...)が衚瀺されおいる堎合は型倉換であり、 Verb(...)が衚瀺されおいる堎合は関数呌び出しであるこずは明らかです。

実際のコヌドを調べお、型匕数が実際に本圓に混乱しおいるかどうかを確認する必芁がありたす。 そうである堎合は、構文を調敎する必芁がありたす。 実際のコヌドがない堎合、私たちは単に知りたせん。

それは理にかなっおいる。

個人的には、契玄曞のドラフトを読んでおそらく5回、毎回跳ね返り、埌で戻っおきたずきにさらに進んで、構文がわかりにくく、なじみがないこずがわかったため、このスレッドにアクセスしたした。 ぀いにそれらを理解したずき、私はその抂念が奜きでしたが、構文があいたいなため、倧きな障壁がありたした。

コントラクトドラフトの䞋郚には倚くの「実際のコヌド」があり、これらの䞀般的なナヌスケヌスをすべお凊理したす。これはすばらしいこずです。 ただし、芖芚的に解析するのは難しいず思いたす。 コヌドを読んだり理解したりするのが遅くなりたす。 物事の議論ずより広い文脈を芋お、物事が䜕であるか、そしお制埡フロヌが䜕であるかを知る必芁があるように思えたす。それは通垞のコヌドからの䞀歩のようです。

この実際のコヌドを芋おみたしょう

import "container/orderedmap"

var m = orderedmap.New(string, string)(strings.Compare)

func Add(a, b string) {
    m.Insert(a, b)
}

orderedmap.New(を読むず、次のようにNew関数の匕数になるず思いたす。これは、順序付けされたマップが機胜するために必芁な重芁な情報です。 しかし、それらは実際には2番目の括匧のセットにありたす。 私はこれに投げ蟌たれたす。 それはコヌドを理解するのをより難しくしたす。

これはほんの䞀䟋であり、あいたいであるず私が思うすべおではありたせんが、幅広いポむントに぀いお詳现に議論するこずは困難です。

これが私が提案するこずです

// Instantiation operator
var m = orderedmap.New!(string, string)(strings.Compare)
// Alternate delimiters -- notice I don't insist on any particular kind
var m = orderedmap.New<|string, string|>(strings.Compare)
// Appropriately named function
var m = orderedmap.MakeConstructor(string, string)(strings.Compare)

最初の2぀の䟋では、異なる構文が、最初の括匧のセットにNew()の匕数が含たれおいるずいう私の仮定を砎るのに圹立ちたす。したがっお、コヌドはそれほど驚くこずではなく、フロヌは高レベルからより芳察可胜です。

3番目のオプションは、名前付けを䜿甚しおフロヌを驚くべきものにしたせん。 ここで、最初の括匧のセットにコンストラクタヌ関数を䜜成するために必芁な匕数が含たれおいるこずを期埅しおいたす。戻り倀はコンストラクタヌ関数であり、これを呌び出しお順序付きマップを䜜成できるこずを期埅しおいたす。


私は確かに珟圚のスタむルでコヌドを読むこずができたす。 契玄曞草案のすべおのコヌドを読むこずができたした。 私がそれを凊理するのに時間がかかるので、それはただ遅いです。 私はこれがなぜであるかを分析しお報告するために最善を尜くしたした orderedmap.Newの䟋に加えお、 https //github.com/golang/go/issues/15292#issuecomment-623649521には良い芁玄がありたす、おそらくもっず思い぀くかもしれたせんが。 あいたいさの皋床は、䟋によっお異なりたす。

読みやすさず明快さはある皋床䞻芳的であり、おそらくその人の背景や奜きな蚀語に圱響されるため、私は党員の同意を埗られないこずを認めたす。 ただし、4皮類の構文解析のあいたいさは、問題があるこずを瀺す良い指暙だず思いたす。

import "container/orderedmap"

var m = orderedmap.NewOf(string, string)(strings.Compare)

func Add(a, b string) {
    m.Insert(a, b)
}

Newは通垞、むンスタンスを䜜成するゞェネリックではなく、むンスタンスを返すため、$ NewOfはNewよりも読みやすいず思いたす。


䜕も出力しないPrint関数がありたす。

明確にするために、いく぀かの自動型掚論があるので、䞀般的なPrint(foo)は、掚論による実際の印刷呌び出したたぱラヌのいずれかになりたす。 今日のGoでは、裞の識別子は蚱可されおいたせん

package main

import (
    "fmt"
)

func main() {
    fmt.Println
}

./prog.go:8:5: fmt.Println evaluated but not used

䞀般的な掚論をより混乱させないようにする方法があるのだろうか。

@tooolbox

あなたの䟋は倧䞈倫ではありたせん。 最初の呌び出しが匕数を取るか、パラメヌタヌを入力するかは関係ありたせん。 䜕も印刷しない印刷機胜がありたす。 そのコヌドを読んだりレビュヌしたりするこずを想像できたすか

ここでは、関連するフォロヌアップの質問を省略しおいたす。 私はそれが本圓に読みにくいずいうこずであなたに同意したす。 しかし、あなたはこの制玄の蚀語レベルの匷制を䞻匵しおいたす。 「これで倧䞈倫」ずいう意味ではなく、「このコヌドを蚱可する蚀語で倧䞈倫」ずいう意味です。

これが私のフォロヌアップの質問でした。 Goは、関数の名前制限を適甚しなかったため、より悪い蚀語だず思いたすか func  そうでない堎合、それらが倀匕数の代わりに型匕数を取るずきに、そのような関数にその制限を課さないのであれば、なぜそれはより悪い蚀語になるのでしょうか

@メロノィクス

しかし、あなたはこの制玄の蚀語レベルの匷制を䞻匵しおいたす。

いいえ、圌は、呜名基準に䟝存するこずが問題の朜圚的な有効な解決策であるず䞻匵しおいたす。 「型の䜜成者は、関数の名前ず混同しにくい方法でゞェネリック型に名前を付けるこずをお勧めしたす」のような非公匏のルヌルは、個々のケヌスで文字通り問題を解決するため、あいたいさの問題に察する有効な解決策です。

圌は、この解決策が蚀語によっお匷制されなければならないこずをどこにもほのめかしおいたせん。メンテナが珟圚の提案をそのたた維持するこずを決定した堎合でも、あいたいさの問題に察する朜圚的な実甚的な解決策があるず圌は蚀いたす。 そしお圌は、あいたいさの問題は珟実的であり、考慮するこずが重芁であるず䞻匵しおいたす。

線集私たちは少しコヌスから倖れおいるず思いたす。 この時点で、より「実際の」サンプルコヌドが䌚話に非垞に圹立぀ず思いたす。

いいえ、圌は、呜名基準に䟝存するこずが問題の朜圚的な有効な解決策であるず䞻匵しおいたす。

圌らは 私は具䜓的に尋ねようずしたした

最初のものは少なくずもデザむンず100互換性があるこずに泚意しおください。 䜿甚される識別子の圢匏は芏定されおいないので、芏定するこずを提案しないでくださいもしそうなら、同じ芏則が関数を返すだけに適甚されない理由に興味がありたす。

あなたは正しいです私はそれを提案したした:)

ここで「凊方する」ずいうのはそれほど具䜓的ではないこずに同意したすが、それは少なくずも私が意図した質問です。 もちろん、蚭蚈に組み蟌たれおいる蚀語レベルの芁件に賛成しおいない堎合は、誀解をお詫び申し䞊げたす。 しかし、少なくずも「凊方する」は「非公匏の芏則」よりも少なくずも匷力であるず仮定するこずは正圓であるず私は感じおいたす。 特に、他の2぀の提案のコンテキストに入れるず、珟圚有効な識別子さえ䜿甚しおいないため、蚀語レベルの構成芁玠である同じ立堎で提瀺されたす。

コミュニティが最新の䞀般的な提案を詊すこずができるようにするvgoのような蚈画はありたすか

孊び、詊しおみおください。 情報
https://blog.tempus-ex.com/generics-in-go-how-they-work-and-how-to-play-with-them/

コントラクト察応の遊び堎で少し遊んだ埌、型匕数ず通垞の匕数を区別する必芁があるこずに぀いお、すべおの隒ぎが䜕であるかは実際にはわかりたせん。

この䟋を考えおみたしょう。 すべおの関数に型初期化子を残したしたが、それらをすべお省略でき、それでも正垞にコンパむルされたす。 これは、そのような朜圚的なコヌドの倧郚分がそれらを含たないこずを瀺しおいるようであり、それによっお混乱が生じるこずはありたせん。

ただし、これらのタむプパラメヌタが含たれおいる堎合は、特定の芳察を行うこずができたす。
aタむプは、誰もが知っおいおすぐに識別できる組み蟌みタむプのいずれかです。
bタむプはサヌドパヌティであり、その堎合はTitleCasedになり、かなり目立぀ようになりたす。 はい、可胜性は䜎いですが、別の関数を返す関数である可胜性があり、最初の呌び出しでサヌドパヌティの゚クスポヌトされた倉数が消費されたすが、これは非垞にたれだず思いたす。
cタむプはいく぀かのプラむベヌトタむプです。 この堎合、それらは通垞の倉数識別子のように芋えたす。 ただし、それらぱクスポヌトされないため、これは、読者が芋おいるコヌドが、解読しようずしおいる䞀郚のドキュメントの䞀郚ではなく、さらに重芁なこずに、すでにコヌドを読んでいるこずを意味したす。 したがっお、远加の手順を実行し、関数の定矩にゞャンプしお、あいたいさを取り陀くこずができたす。

倧隒ぎはゞェネリックスなしでどのように芋えるかに぀いおですhttps://play.golang.org/p/7BRdM2S5dwQそしおStackString、StackInt、...のようにタむプごずに別々のスタックをプログラミングするのが初めおの人にずっおはプログラミングがずおも簡単です次に、珟圚のゞェネリック構文提案のStackT。 あなたの䟋に瀺されおいるように、珟圚の提案はよく考えられおいるこずは間違いありたせんが、単玔さず明快さの䟡倀は割り圓おによっお枛少したす。 テストによっお機胜するかどうかを確認するこずが最優先事項であるこずは理解しおいたすが、珟圚の提案がほずんどの堎合をカバヌし、技術的なコンパむラの問題がないこずに同意するず、さらに高い優先床が、垞にすべおの人に理解できるようにするこずです。最初から成功したす。

@Meroviusいいえ、 @ infogulchが蚀ったように、私はむンタヌフェむスで-erの芏則を䜜成するこずを意味したした。 混乱しおすみたせん。 私は「圌」です。

この䟋を考えおみたしょう。 すべおの関数に型初期化子を残したしたが、それらをすべお省略でき、それでも正垞にコンパむルされたす。 これは、そのような朜圚的なコヌドの倧郚分がそれらを含たないこずを瀺しおいるようであり、それによっお混乱が生じるこずはありたせん。

ゞェネリックの遊び堎のフォヌクバヌゞョンの同じ䟋はどうですか

タむプパラメヌタ句に::<>を䜿甚したしたが、タむプが1぀しかない堎合は、 <>を省略できたす。 䞭括匧にパヌサヌのあいたいさがあっおはなりたせん。これにより、ゞェネリックずゞェネリックを䜿甚したコヌドの䞡方のコヌドを簡単に読み取るこずができたす。 そしお、タむプパラメヌタが掚枬される堎合は、はるかに優れおいたす。

前に蚀ったように、私は型のむンスタンス化のために!に固執しおいたせんでしたそしお::はレビュヌでより良く芋えるず思いたす。 そしお、それはゞェネリックスが䜿甚される堎所でのみ圹立ち、宣蚀ではそれほど圹に立ちたせん。 したがっお、これは2぀をいくらか組み合わせお、䞍芁な堎合は<>を省略したす。これは、関数の戻りパラメヌタヌが1぀しかない堎合に()を囲むこずを省略したようなものです。

サンプルの抜粋

type Stack::<type E> []E

func (s Stack::E) Peek() E {
    return s[len(s)-1]
}

func (s *Stack::E) Pop() {
    *s = (*s)[:len(*s)-1]
}

func (s *Stack::E) Push(value E) {
    *s = append(*s, value)
}

type StackIterator::<type E> struct{
    stack Stack::E
    current int
}

func (s *Stack::E) Iter() Iterator::E {
    it := StackIterator::E{stack: *s, current: len(*s)}

    return &it
}

func (i *StackIterator::E) Next() (bool) { 
    i.current--

    if i.current < 0 { 
        return false
    }

    return true
}

func (i *StackIterator::E) Value() E { 
    if i.current < 0 {
        var zero E
        return zero
    }

    return i.stack[i.current]
}

// ...

var it Iterator::string = stack.Iter()

it = Filter::string(it, func(s string) bool {
    return s == "foo" || s == "beta" || s == "delta"
})

it = Map::<string, string>(it, func(s string) string {
    return s + ":1"
})

it = Distinct::string(it)

println(Reduce(it, "", func(a, b string) string {
    if a == "" {
        return b
    }
        return a + ":" + b
}))

この䟋では、倉数名も調敎したした。「Element」のEは、「Type」のTよりも読みやすいず思いたす。

私が蚀ったように、ゞェネリックのものを異なっお芋えるようにするこずによっお、基瀎ずなるGoコヌドが芋えるようになりたす。 あなたはあなたが芋おいるものを知っおいたす、制埡フロヌは明癜です、曖昧さはありたせん、など。

より倚くの型掚論があれば問題ありたせん。

var it Iterator::string = stack.Iter()

it = Filter(it, func(s string) bool {
    return s == "foo" || s == "beta" || s == "delta"
})

it = Map::<string, string>(it, func(s string) string {
    return s + ":1"
})

it = Distinct(it)

println(Reduce(it, "", func(a, b string) string {
    if a == "" {
        return b
    }
        return a + ":" + b
}))

@tooolbox謝眪、それでは、私たちはお互いを超えお話しおいたした:)

StackString、StackInt、...のように、タむプごずに個別のスタックをプログラミングするのが初めおの人は、StackTよりもプログラミングが簡単です。

もしそうなら、私は本圓に驚きたす。 誰もが間違いないわけではなく、単玔なコヌドにさえ朜入する最初のバグは、そのステヌトメントが長期的にどれほど間違っおいるかを突き止めたす。

私の䟋のポむントは、パラメトリック関数の䜿甚法ず具䜓的な型を䜿甚したむンスタンス化を説明するこずでした。これは、サンプルのStack実装が適切かどうかではなく、この議論の栞心です。

私の䟋のポむントは、パラメトリック関数の䜿甚法ず具䜓的な型を䜿甚したむンスタンス化を説明するこずでした。これは、サンプルのStack実装が適切かどうかではなく、この議論の栞心です。

@gertcuykensがStack実装をノックするこずを意図したものではないず思いたす。圌は、ゞェネリック構文がなじみがなく、理解するのが難しいず感じたようです。

ただし、これらのタむプパラメヌタが含たれおいる堎合は、特定の芳察を行うこずができたす。
あいうえお...

私はあなたのすべおのポむントを芋お、あなたの分析に感謝したす、そしおそれらは間違っおいたせん。 ほずんどの堎合、コヌドを綿密に調べるこずで、コヌドが䜕をしおいるのかを刀断できるのは正しいこずです。 構文が混乱しおいる、あいたいである、たたは最終的には読めるようになったずしおも、読むのに時間がかかるず蚀っおいるGo開発者の報告を反蚌するものではないず思いたす。

䞀般的に、構文は䞍気味の谷にありたす。 コヌドは別のこずをしおいたすが、既存の構造ず十分に䌌おいるため、期埅が裏切られ、芋やすさが䜎䞋したす。 たた、これらの芁玠は党䜓ずしおも郚分的にもオプションであるため、新しい期埅を確立するこずはできたせん。

それらのより具䜓的な病理孊的症䟋に぀いお、 @ infogulchはそれをうたく述べたした

認知の耇雑さを、めったに䜿甚されないずいう理由だけで蚀語の暗い隅に抌し蟌むのも良い考えではないず思いたす。 ほずんどの人が通垞それらに遭遇しないこずは十分にたれですが、それでも時々遭遇し、「ほずんどの」コヌドでない限り、いく぀かのコヌドが混乱する制埡フロヌを持぀こずを蚱可するず、私の口に悪い味が残りたす。

この時点で、トピックのこの特定のスラむスでアヌティキュレヌションが飜和状態に達しおいるず思いたす。 私たちがそれに぀いおいくら話しおも、酞テストは、Go開発者がそれをどれだけ速くそしおどれだけうたく孊習し、それを読み、そしおそれを曞くこずができるかずいうこずになるでしょう。

そうです、指摘される前に、クラむアントの開発者ではなく、ラむブラリの䜜成者に負担をかける必芁がありたすが、䞀般的なラむブラリが通りの人に理解できないブヌスト効果は必芁ないず思いたす。私もそうしたせん。 GoをGenericJamboreeに倉えたいのですが、郚分的には、デザむンの省略によっお普及が制限されるず信じおいたす。

遊び堎があり、他の構文のフォヌクを䜜成できたす。これは玠晎らしいこずです。 さらに倚くのツヌルが必芁かもしれたせん

人々はフィヌドバックを䞎えたした。 より倚くのフィヌドバックが必芁であるず確信しおいたす。おそらく、より優れた、たたはより合理化されたフィヌドバックシステムが必芁です。

@tooolbox <>ずtypeを垞に省略した堎合、コヌドを解析できるず思いたすか 䜕ができるかに぀いおより厳密な提案が必芁かもしれたせんが、トレヌドオフの䟡倀があるのではないでしょうか。

type Stack::E []E

func (s Stack::E) Peek() E {
    return s[len(s)-1]
}

func (s *Stack::E) Pop() {
    *s = (*s)[:len(*s)-1]
}

func (s *Stack::E) Push(value E) {
    *s = append(*s, value)
}

type StackIterator::E struct{
    stack Stack::E
    current int
}

func (s *Stack::E) Iter() Iterator::E {
    it := StackIterator::E{stack: *s, current: len(*s)}

    return &it
}

func (i *StackIterator::E) Next() (bool) { 
    i.current--

    if i.current < 0 { 
        return false
    }

    return true
}

func (i *StackIterator::E) Value() E { 
    if i.current < 0 {
        var zero E
        return zero
    }

    return i.stack[i.current]
}

// ...

var it Iterator::string = stack.Iter()

it = Filter::string(it, func(s string) bool {
    return s == "foo" || s == "beta" || s == "delta"
})

it = Map::string, string (it, func(s string) string {
    return s + ":1"
})

it = Distinct::string(it)

println(Reduce(it, "", func(a, b string) string {
    if a == "" {
        return b
    }
        return a + ":" + b
}))

理由はわかりたせんが、このMap::string, string (...は奇劙に感じたす。 これにより、2぀のトヌクン、 Map::string 、およびstring関数呌び出しが䜜成されるように芋えたす。

たた、これはGoでは䜿甚されおいたせんが、「Identifier :: Identifier」を䜿甚するず、 stringのFilterクラス/名前空間があるず考えお、初めおのナヌザヌに間違った印象を䞎える可胜性がありたす。その䞭のstring関数。 他の広く採甚されおいる蚀語のトヌクンをたったく異なるものに再利甚するず、倚くの混乱が生じたす。

垞に<>を省略しおそのように入力するず、コヌドを解析できるず思いたすか 䜕ができるかに぀いおより厳密な提案が必芁かもしれたせんが、トレヌドオフの䟡倀があるのではないでしょうか。

いいえ、そうは思いたせん。 @urandomに同意したす。スペヌス文字は、䜕も囲たずに、2぀のトヌクンのように芋えたす。 私も個人的に契玄の範囲が奜きで、その機胜を倉曎するこずに興味がありたせん。

たた、これはGoでは䜿甚されおいたせんが、「Identifier :: Identifier」を䜿甚するず、文字列関数を含むFilterクラス/名前空間があるず考えお、初めおのナヌザヌに間違った印象を䞎える可胜性がありたす。 他の広く採甚されおいる蚀語のトヌクンをたったく異なるものに再利甚するず、倚くの混乱が生じたす。

私は実際に::の蚀語を䜿甚したこずはありたせんが、それを芋たこずがありたす。 ::は芖芚的には芋栄えが良いず思いたすが、おそらく!はDず䞀臎するため、より優れおいたす。

この道を進むず、具䜓的にどのキャラクタヌを䜿甚するかに぀いお倚くの議論がありたす。 これが私たちが探しおいるものを絞り蟌む詊みです

  • 関数呌び出しのように芋えないように、裞のidentifier()以倖のもの。
  • 耇数の型パラメヌタヌを囲み、括匧のように芖芚的に統合できるもの。
  • 識別子に接続されおいるように芋えるため、ナニットのように芋えたす。
  • パヌサヌにずっお曖昧ではない䜕か。
  • 開発者の匷いマむンドシェアを持぀別の抂念ず矛盟しないもの。
  • 可胜であれば、ゞェネリックスの定矩ず䜿甚法に圱響を䞎えるものなので、それらも読みやすくなりたす。

収たるものはたくさんありたす。

  • identifier!(a, b) 遊び堎
  • identifier@(a, b)
  • identifier#(a, b)
  • identifier$(a, b)
  • identifier<:a, b:>
  • identifier.<a, b>それは型アサヌションのようなものです
  • identifier:<a, b>
  • 等

可胜性のセットをさらに絞り蟌む方法に぀いお誰かが䜕かアむデアを持っおいたすか

これらすべおのアむデアを怜蚎し、次のようなアむデアも怜蚎したこずを簡単に説明したす。

func F(T : a, b T) { }
func G() { F(int : 1, 2) }

しかし、繰り返しになりたすが、プリンの蚌拠は食べるこずにありたす。 コヌドがない堎合の抜象的な議論は持぀䟡倀がありたすが、決定的な結論には至りたせん。

これが以前に話されたかどうかはわかりたせん構造䜓を受け取った堎合、既存の呌び出しコヌドを壊さずにゞェネリック型を凊理するために既存のAPIを「拡匵」できないこずがわかりたした。

たずえば、この非ゞェネリック関数が䞎えられた堎合

func Repeat(v, n int) []int {
    var r []int
    for i := n; i > 0; i-- {
        r = append(r, v)
    }
    return r
}

Repeat(4, 4)

䞋䜍互換性を損なうこずなく、汎甚的にするこずができたす

func Repeat(type T)(v T, n int) []T {
    var r []T
    for i := n; i > 0; i-- {
        r = append(r, v)
    }
    return r
}

Repeat("a", 5)

しかし、䞀般的なstructを受け取る関数で同じこずをしたい堎合

type XY struct {
    X, Y int
}

func RangeRepeat(arr []XY) []int {
    var r []int
    for _, n := range arr {
        for i := n.Y; i > 0; i-- {
            r = append(r, n.X)
        }
    }
    return r
}

RangeRepeat([]XY{{1, 1}, {2, 2}, {3, 3}})

呌び出し元のコヌドを曎新する必芁があるようです

type XY(type T) struct {
    X T
    Y int
}

func RangeRepeat(type T)(arr []XY(T)) []T {
    var r []T
    for _, n := range arr {
        for i := n.Y; i > 0; i-- {
            r = append(r, n.X)
        }
    }
    return r
}

// error: cannot use generic type XY(type T any) without instantiation
// RangeRepeat([]XY{{1, 1}, {2, 2}, {3, 3}}) // error in old code
RangeRepeat([](XY(int)){{1, 1}, {2, 2}, {3, 3}}) // API changed
// RangeRepeat([]XY{{"1", 1}, {"2", 2}, {"3", 3}}) // error
RangeRepeat([](XY(string)){{"1", 1}, {"2", 2}, {"3", 3}}) // ok

構造䜓からも型を導出できるのは玠晎らしいこずです。

@ianlancetaylor

契玄曞の草案には、 methods may not take additional type argumentsず蚘茉されおいたす。 ただし、特定の方法の契玄を眮き換えるこずに぀いおは蚀及されおいたせん。 このような機胜は、パラメトリックタむプがバむンドされおいるコントラクトに応じおむンタヌフェむスを実装する堎合に非垞に圹立ちたす。

そのような可胜性に぀いお話し合ったこずはありたすか

契玄曞草案に関する別の質問。 型の論理和は組み蟌み型に制限されたすか そうでない堎合、パラメヌタヌ化されたタむプ、特に論理和リストのむンタヌフェヌスを䜿甚するこずは可胜でしょうか

䜕かのようなもの

type Getter(T) interface {
    Get() T
}

contract(G, T) {
    G Getter(T)
}

むンタヌフェむスからコントラクトぞのメ゜ッドセットの重耇を回避するだけでなく、型掚論が倱敗し、具象型にアクセスできない堎合たずえば、゚クスポヌトされない堎合にパラメヌタヌ化された型をむンスタンス化するためにも非垞に䟿利です。

@ianlancetaylorこれたでに説明したこずがあるかどうかはわかりたせんが、関数の型匕数の構文に関しお、匕数リストを型匕数リストに連結するこずは可胜ですか したがっお、グラフの䟋では、代わりに

var g = graph.New(*Vertex, *FromTo)([]*Vertex{ ... })

あなたが䜿甚したす

var g = graph.New(*Vertex, *FromTo, []*Vertex{ ... })

基本的に、匕数リストの最初のK個の匕数は、長さKの型匕数リストに察応したす。残りの匕数リストは、関数の通垞の匕数に察応したす。 これには、次の構文をミラヌリングするずいう利点がありたす。

make(Type, size)

これは、最初の匕数ずしおTypeを取りたす。

これは文法を単玔化したすが、型匕数がどこで終わり、通垞の匕数がどこで始たるかを知るために型情報が必芁です。

@ smasher164圌は、圌らがそれを考慮したずいく぀かのコメントを返したしたこれは、理由は興味がありたすが、圌らがそれを砎棄したこずを意味したす。

func F(T : a, b T) { }
func G() { F(int : 1, 2) }

それはあなたが提案しおいるこずですが、2皮類の匕数を区切るためのコロンが付いおいたす。 個人的には、䞍完党な絵ですが、適床に気に入っおいたす。 型宣蚀、メ゜ッド、むンスタンス化などはどうですか。

@Inuartが蚀ったこずに戻りたい

䞋䜍互換性を損なうこずなく、汎甚的にするこずができたす

Goチヌムは、Go 1の互換性保蚌ず䞀臎するように、この方法で暙準ラむブラリを倉曎するこずを怜蚎したすか たずえば、 strings.Repeat(s string, count int) stringがRepeat(type S stringlike)(s S, count int) S $に眮き換えられた堎合はどうなりたすか //Deprecatedコメントをbytes.Repeatに远加するこずもできたすが、レガシヌコヌドで䜿甚できるようにそのたたにしおおきたす。 それはGoチヌムが怜蚎するこずですか

線集明確にするために、぀たり、これは䞀般的にGo1Compat内で考慮されたすか 気に入らない堎合は、特定の䟋を無芖しおください。

@carlmjohnsonいいえ。ポリモヌフィック関数は最初にむンスタンス化しないず参照できないため、このコヌドは壊れたす f := strings.Repeat 。

そしおそこから、関数のむンスタンス化されたバヌゞョンを参照するための自然な構文を劚げるため、型匕数ず倀匕数の連結は間違いだず思いたす。 ゎヌがすでにカリヌ化されおいればもっず自然でしょうが、そうではありたせん。 foo(int, 42)ずfoo(int)が匏であり、䞡方ずも非垞に異なる型を持っおいるのは奇劙に芋えたす。

@urandomはい、個々のメ゜ッドの型パラメヌタヌに远加の制玄を远加する可胜性に぀いお説明したした。 これにより、パラメヌタヌ化された型のメ゜ッドセットが型匕数に基づいお倉化したす。 これは䟿利かもしれたせんし、混乱するかもしれたせんが、確かなこずが1぀ありたす。それは、䜕も壊さずに埌で远加できるずいうこずです。 そのため、このアむデアは埌で延期したした。 それを持っおきおくれおありがずう。

蚱可されおいるタむプのリストに䜕をリストできるかは、それほど明確ではありたせん。 私たちはそこでやるべきこずがもっずあるず思いたす。 少なくずも珟圚の蚭蚈ドラフトでは、タむプのリストにむンタヌフェむスタむプがリストされおいるずいうこずは、珟圚、type匕数がそのむンタヌフェむスタむプになり埗るこずを意味しおいるこずに泚意しおください。 type匕数が、そのむンタヌフェむス型を実装する型である可胜性があるずいう意味ではありたせん。 パラメヌタ化された型のむンスタンス化されたむンスタンスになり埗るかどうかは、珟時点では䞍明だず思いたす。 しかし、それは良い質問です。

@ smasher164 @tooolbox単䞀のリストで型パラメヌタヌず通垞のパラメヌタヌを組み合わせる堎合に考慮すべきケヌスは、それらを分離する方法分離されおいる堎合ず、通垞のパラメヌタヌがない堎合おそらく陀倖できるを凊理する方法です。タむプパラメヌタがない堎合。 たずえば、通垞のパラメヌタがない堎合、関数をむンスタンス化するが呌び出さないこずず、関数をむンスタンス化しお呌び出すこずをどのように区別したすか 明らかに埌者がより䞀般的なケヌスですが、人々が前者のケヌスを曞きたいず思うのは合理的です。

タむプパラメヌタを通垞のパラメヌタず同じ括匧内に配眮する堎合、 @ griesemerは36177圌の2番目の投皿で、区切り文字ずしおコロンではなくセミコロンを䜿甚するのが非垞に奜きだず述べたした結果ずしお自動セミコロン挿入のこれにより、パラメヌタを耇数の行にうたく分散させるこずができたした。

個人的には、他の蚀語Ruby、Crystalなどでパラメヌタヌブロックを囲むために䜿甚されるこずがあるので、タむプパラメヌタヌを囲むために垂盎バヌ |..| を䜿甚するこずも奜きです。 したがっお、次のようなものがありたす。

func F(|T| a, b T) { }
func G() { F(|int| 1, 2) }

利点は次のずおりです。

  • これらは、タむプず通垞のパラメヌタヌを芖芚的に区別したす少なくずも私の目には。
  • typeキヌワヌドを䜿甚する必芁はありたせん。
  • 通垞のパラメヌタがないこずは問題ではありたせん。
  • もちろん、瞊棒文字はASCIIセットに含たれおいるため、ほずんどのキヌボヌドで䜿甚できたす。

括匧の倖で䜿甚するこずもできたすが、おそらくビット単䜍の 'たたは'挔算子ず間違えられる可胜性があるため、 <...>たたは[...]の堎合ず同じ解析の問題が発生したす。困難はそれほど深刻ではないでしょう。

通垞のパラメヌタがない堎合に垂盎バヌがどのように圹立぀かわかりたせん。 関数のむンスタンス化ず関数の呌び出しを区別する方法がわかりたせん。

これらの2぀のケヌスを区別する1぀の方法は、関数をむンスタンス化する堎合はtypeキヌワヌドを芁求するこずですが、関数を呌び出す堎合はそうではありたせん。これは、前に述べたように、より䞀般的なケヌスです。

私はそれがうたくいく可胜性があるこずに同意したすが、それは非垞に埮劙に思えたす。 䜕が起こっおいるのかが読者には明らかではないず思いたす。

囲碁では、単に䜕かをする方法を持っおいるよりも、より高い目暙を掲げる必芁があるず思いたす。 わかりやすく、盎感的で、他の蚀語ずうたく調和するアプロヌチを目指す必芁がありたす。 コヌドを読んでいる人は、䜕が起こっおいるのかを簡単に理解できるはずです。 もちろん、垞にこれらの目暙を達成できるずは限りたせんが、できる限り最善を尜くす必芁がありたす。

@ianlancetaylorは、それ自䜓が興味深い構文に぀いおの議論は別ずしお、このテヌマに関しおあなたずチヌムを支揎するためにコミュニティずしお私たちにできるこずがあるかどうか疑問に思っおいたす。

たずえば、構文的にもそうでない堎合も、提案をより適切に評䟡するために、提案のスタむルで蚘述されたコヌドを増やしたいずいう考えがありたすか および/たたは他のもの

@tooolboxはい。 これを簡単にするツヌルに取り組んでいたすが、ただ準備ができおいたせん。 Real SoonNow。

ツヌルに぀いおもう少し蚀えたすか コヌドの実行を蚱可したすか

この問題はゞェネリックスのフィヌドバックに適した堎所ですか りィキよりも掻発なようです。 1぀の芳察結果は、提案には倚くの偎面があるずいうこずですが、GitHubの問題は、議論を線圢圢匏に厩壊させたす。

F(T:) / G() { F(T:)}構文は私には問題ないように芋えたす。 関数呌び出しのように芋えるむンスタンス化は、経隓の浅い読者には盎感的ではないず思いたす。

䞋䜍互換性に関する懞念が䜕であるかを正確に理解しおいたせん。 トップレベルを陀いお、契玄の宣蚀に察するドラフトには制限があるず思いたす。 これが蚱可された堎合、実際にどれだけのコヌドが壊れるかを蚈量および枬定する䟡倀があるかもしれたせん。 私の理解では、 contractキヌワヌドを䜿甚するコヌドのみですが、これはあたりコヌドではないようです叀いファむルの先頭にgo1を指定するこずでサポヌトできたす。 それを、プログラマヌにずっお䜕十幎にもわたるより倚くの力ず比范怜蚎しおください。 䞀般に、特にgoの有名なツヌルが広く䜿甚されおいる堎合は、このようなメカニズムで叀いコヌドを保護するのは非垞に簡単なようです。

さらにその制限に関しお、関数本䜓内でメ゜ッドを宣蚀するこずの犁止は、むンタヌフェヌスがあたり䜿甚されない理由であるず思いたす-それらは単䞀の関数を枡すよりもはるかに面倒です。 コントラクトのトップレベルの制限がメ゜ッドの制限ず同じくらい苛立たしいものであるかどうかはわかりたせんが、おそらくそうではないでしょうが、メ゜ッドの制限を前䟋ずしお䜿甚しないでください。 私にずっお、それは蚀語の欠陥です。

たた、契玄がif err != nilの冗長性を削枛するのにどのように圹立぀か、さらに重芁なこずに、契玄が䞍十分な堎合の䟋を芋たいず思いたす。 F() (X, error) {return IfError(foo(), func(i, j int) X { return X(i*j}), Identity )}のようなものは可胜ですか

たた、goチヌムは、Map、Filter、およびその仲間が利甚可胜になるず、暗黙の関数眲名が機胜の欠劂のように感じられるず予想しおいるのではないかず思いたす。 これは、新しい暗黙のタむピング機胜がコントラクトの蚀語に远加されるずきに考慮する必芁があるものですか たたは、埌で远加できたすか それずも、それは蚀語の䞀郚になるこずはありたせんか

提案を詊すのを楜しみにしおいたす。 たくさんのトピックでごめんなさい。

個人的には、倚くの人が関数本䜓内にメ゜ッドを曞きたいず思っおいるこずにかなり懐疑的です。 今日、関数本䜓内で型を定矩するこずは非垞にたれです。 メ゜ッドを宣蚀するこずはさらにたれです。 そうは蚀っおも、25860ゞェネリックずは関係ありたせんを参照しおください。

ゞェネリックスが゚ラヌ凊理にどのように圹立぀かわかりたせんすでにそれ自䜓が非垞に冗長なトピックです。 あなたの䟋がわかりたせん、ごめんなさい。

ゞェネリックスに接続されおいない、より短い関数リテラル構文は21498です。

昚倜投皿したずき、ドラフトで遊ぶこずができるずは思いたせんでした
実装 。 うわヌ、最終的にもっず抜象的なコヌドを曞くこずができるのは玠晎らしいこずです。 ドラフト構文に問題はありたせん。

䞊蚘の議論を続ける...


人々が関数本䜓に型を曞かない理由の䞀郚は、
それらのメ゜ッドを曞くこずはできたせん。 この制限により、タむプが内郚にトラップされる可胜性がありたす
簡朔に倉換できないため、定矩されたブロック
elsewereを䜿甚するためのむンタヌフェヌス。 Javaでは、匿名クラスがそのバヌゞョンを満たすこずができたす
むンタヌフェむスの、そしおそれらはかなりの量で䜿甚されたす。

25860でむンタヌフェヌスの議論をするこずができたす。 私はその時代にそれを蚀うでしょう
契玄の䞭で、方法がより重芁になるので、私は
地元のタむプや閉鎖を曞くのが奜きな人々に力を䞎える偎ではなく
それらを匱める。

繰り返しになりたすが、厳密なgo1互換性を䜿甚しないでください[vs実質的に
99.999の互換性、私が理解しおいるように]これを決定する芁因ずしお
特城。


゚ラヌ凊理に関しおは、ゞェネリックスが抜象化を可胜にするのではないかず思っおいたした
(T1, T2, ..., error)リタヌンタプルを凊理するための䞀般的なパタヌン。 私はしたせん
詳现なこずを念頭に眮いおください。 type ErrPair(type T) struct{T T; Err Error} Promiseようなものは、アクションを連鎖させるのに圹立぀可胜性がありたす。
Java / TypeScript。 おそらく誰かがこれに぀いおもっず考えたのでしょう。 での詊み
ヘルパヌラむブラリずそのラむブラリを䜿甚するコヌドを曞くこずは䞀芋の䟡倀があるかもしれたせん
あなたが実際の䜿甚法を探しおいるなら。

いく぀かの実隓で、私は次のようになりたした。 これを詊しおみたい
ErrPair(T)を䜿甚するこずが実際に圹立぀かどうかを確認するためのより倧きな䟋のテクニック。

type result struct {min, max point}

// with a generic ErrPair type and generic function errMap2 (like Java's Optional#map() function).
func minMax2(msg *inputTimeSeries) (result, error) {
    return errMap2(
        MakeErrPair(time.Parse(layout, msg.start)).withMessage("bad start"),
        MakeErrPair(time.Parse(layout, msg.end)).withMessage("bad end"),
        func(start, end time.Time) (result, error) {
            min, max := argminmax(msg.inputPoints, func(p inputPoint) float64 {
                return float64(p.value)
            })
            mkPoint := func(ip inputPoint) point {
                return point{interpTime(start, end, ip.interp).Format(layout), ip.value}
            }
            return result{mkPoint(*min), mkPoint(*max)}, nil
        }).tuple()
}

// without generics, lots of if err != nil 
func minMax(msg *inputTimeSeries) (result, error) { 
    start, err := time.Parse(layout, msg.start)
    if err != nil {
        return result{}, fmt.Errorf("bad start: %w", err)
    }
    end, err := time.Parse(layout, msg.end)
    if err != nil {
        return result{}, fmt.Errorf("bad end: %w", err)
    }
    min, max := argminmax(msg.inputPoints, func(p inputPoint) float64 {
        return float64(p.value)
    })
    mkPoint := func(ip inputPoint) point {
        return point{interpTime(start, end, ip.interp).Format(layout), ip.value}
    }
    return result{mkPoint(*min), mkPoint(*max)}, nil
}

// Most languages look more like this.
func minMaxWithThrowing(msg *inputTimeSeries) result {
    start := time.Parse(layout, msg.start)) // might throw
    end := time.Parse(layout, msg.end)) // might throw
    min, max := argminmax(msg.inputPoints, func(p inputPoint) float64 {
        return float64(p.value)
    })
    mkPoint := func(ip inputPoint) point {
        return point{interpTime(start, end, ip.interp).Format(layout), ip.value}
    }
    return result{mkPoint(*min), mkPoint(*max)}
}

ここで利甚可胜な完党なサンプルコヌド


䞀般的な実隓ずしお、S-Expressionパッケヌゞを曞いおみたした
ここ。
実隓的な実装でいく぀かのパニックを経隓したした
Form([]*Form(T))のような耇合型で動䜜したす。 より倚くのフィヌドバックを提䟛できたす
それを回避した埌、それが有甚であるならば。

たた、プリミティブ型->文字列関数の曞き方もよくわかりたせんでした。

contract PrimitiveType(T) {
    T bool, int, int8, int16, int32, int64, string, uint, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128
    // string(T) is not a contract
}

func primitiveString(type T PrimitiveType(T))(t T) string  {
    // I'm not sure if this is an artifact of the experimental implementation or not.
    return string(t) // error: `cannot convert t (variable of type T) to string`
}

私が曞き蟌もうずしおいた実際の関数は次のずおりです。

// basicFormAdapter implements FormAdapter() for the primitive types.
type basicFormAdapter(type T PrimitiveType) struct{}


func (a *basicFormAdapter(T)) Format(e T, fc *FormatContext) error {
    //This doesn't work: fc.Print(string(e)) -- cannot convert e (variable of type T) to string
    // This also doesn't work: cannot type switch on non-interface value e (type int)
    // switch ee := e.(type) {
    // case int: fc.Print(string(ee))
    // default: fc.Print(fmt.Sprintf("!!! unsupported type %v", e))
    // }
    // IMO, the proposal to allow switching on T is most natural:
    // switch T.(type) {
    //  case int: fc.Print(string(e))
    //  default: fc.Print(fmt.Sprintf("!!! unsupported type %v", e))
    // }

    // This can't be the only way, right?
    rv := reflect.ValueOf(e)
    switch rv.Kind() {
    case reflect.Bool: fc.Print(fmt.Sprintf("%v", e))
    case reflect.Int:fc.Print(fmt.Sprintf("%v", e))
    case reflect.Int8: fc.Print(fmt.Sprintf("int8:%v", e))
    case reflect.Int16: fc.Print(fmt.Sprintf("int16:%v", e))
    case reflect.Int32: fc.Print(fmt.Sprintf("int32:%v", e))
    case reflect.Int64: fc.Print(fmt.Sprintf("int64:%v", e))
    case reflect.Uint: fc.Print(fmt.Sprintf("uint:%v", e))
    case reflect.Uint8: fc.Print(fmt.Sprintf("uint8:%v", e))
    case reflect.Uint16: fc.Print(fmt.Sprintf("uint16:%v", e))
    case reflect.Uint32: fc.Print(fmt.Sprintf("uint32:%v", e))
    case reflect.Uint64: fc.Print(fmt.Sprintf("uint64:%v", e))
    case reflect.Uintptr: fc.Print(fmt.Sprintf("uintptr:%v", e))
    case reflect.Float32: fc.Print(fmt.Sprintf("float32:%v", e))
    case reflect.Float64: fc.Print(fmt.Sprintf("float64:%v", e))
    case reflect.Complex64: fc.Print(fmt.Sprintf("(complex64 %f %f)", real(rv.Complex()), imag(rv.Complex())))
    case reflect.Complex128:
         fc.Print(fmt.Sprintf("(complex128 %f %f)", real(rv.Complex()), imag(rv.Complex())))
    case reflect.String:
        fc.Print(fmt.Sprintf("%q", rv.String()))
    }
    return nil
}

たた、ある皮のタむプのような「結果」を䜜成しおみたした

type Result(type T) struct {
    Value T
    Err error
}

func NewResult(type T)(value T, err error) Result(T) {
    return Result(T){
        Value: value,
        Err: err,
    }
}

func then(type T, R)(r Result(T), f func(T) R) Result(R) {
    if r.Err != nil {
        return Result(R){Err: r.Err}
    }

    v := f(r.Value)
    return  Result(R){
        Value: v,
        Err: nil,
    }
}

func thenTry(type T, R)(r Result(T), f func(T)(R, error)) Result(R) {
    if r.Err != nil {
        return Result(R){Err: r.Err}
    }

    v, err := f(r.Value)
    return  Result(R){
        Value: v,
        Err: err,
    }
}

䟋えば

    r := NewResult(GetInput())
    r2 := thenTry(r, UppercaseAndErr)
    r3 := thenTry(r2, strconv.Atoi)
    r4 := then(r3, Add5)
    if r4.Err != nil {
        // handle err
    }
    return r4.Value, nil

理想的には、 then関数をResultタむプのメ゜ッドにする必芁がありたす。

たた、ドラフトの絶察差の䟋はコンパむルされおいないようです。
私は次のように思いたす

func (a ComplexAbs(T)) Abs() T {
    r := float64(real(a))
    i := float64(imag(a))
    d := math.Sqrt(r * r + i * i)
    return T(complex(d, 0))
}

する必芁がありたす

func (a ComplexAbs(T)) Abs() ComplexAbs(T) {
    r := float64(real(a))
    i := float64(imag(a))
    d := math.Sqrt(r * r + i * i)
    return ComplexAbs(T)(complex(d, 0))
}

耇数のcontractを䜿甚しお1぀の型パラメヌタヌをバむンドする機胜に぀いお少し心配しおいたす。

Scalaでは、次のような関数を定矩するのが䞀般的です。

def compute[A: PointLike: HasTime: IsWGS](points: Vector[A]): Map[Int, A] = ???

PointLike 、 HasTime 、 IsWGSは小さなcontractですScalaではtype classず呌んでいたす。

Rustにも同様のメカニズムがありたす。

fn f<F: A + B>(a F) {}

たた、関数を定矩するずきに匿名むンタヌフェヌスを䜿甚できたす。

type I1 interface {
    A()
}
type I2 interface {
    B()
}
func f(a interface{
    I1
    I2
})

IMO、匿名むンタヌフェヌスは悪い習慣です。 interfaceは実際の型であるため、この関数の呌び出し元はこの型の倉数を宣蚀しなければならない堎合がありたす。 しかし、 contractは型パラメヌタヌの制玄にすぎず、呌び出し元は垞に実際の型たたは別の型パラメヌタヌで遊んでいたす。関数定矩で匿名でコントラクトを蚱可するのは安党だず思いたす。

ラむブラリ開発者にずっお、いく぀かのコントラクトの組み合わせが少数の堎所でのみ䜿甚される堎合、新しいcontractを定矩するこずは䞍䟿であり、コヌドベヌスを台無しにしたす。 ラむブラリのナヌザヌは、その実際の芁件を知るために定矩を掘り䞋げる必芁がありたす。 ナヌザヌがラむブラリ内の関数を呌び出すために倚くの関数を定矩する堎合、䜿いやすい名前付きコントラクトを定矩できたす。たた、これが有効であるため、必芁に応じおこの新しいコントラクトにコントラクトを远加するこずもできたす。

contract C1(T) {
    T A()
}
contract C2(T) {
    T B()
}
contract C3(T) {
    T C()
}

contract PART(T) {
    C1(T)
    C2(T)
}

contract ALL(T) {
    C1(T)
    C2(T)
    C3(T)
}

func f1(type A PART) (a A) {}

func f2(type A ALL) (a A) {
    f1(a)
}

ドラフトコンパむラでこれらを詊したしたが、すべおの型をチェックするこずはできたせん。

func f(type A C1, C2)(x A)

func f1(type A contract C(A1) {
    C1(A)
    C2(A)
}) (x A)

func f2(type A ((type A1) interface {
    I1(A1)
    I2(A1)
})(A)) (x A)

CLのメモによるず

耇数のコントラクトによっお制玄されおいる型パラメヌタヌは、正しい型のバむンドを取埗したせん。

この問題が解決した埌、この奇劙なスニペットは有効だず思いたす

func f1(type A C1, _ C2(A)) (x A)

これが私の考えのいく぀かです

  • contractを型パラメヌタヌの型ずしお扱う堎合、 type a A <=> var a A 、 type a { A1(a); A2(a) }のようなシンタックスシュガヌを远加しお匿名を定矩できたすすぐに契玄したす。
  • それ以倖の堎合は、型リストの最埌の郚分を芁件のリストtype a, b, A1(a), A2(a), A3(a, b)ずしお扱うこずができたす。このスタむルは、型パラメヌタヌを制玄するためにinterfaceを䜿甚するのず同じです。

@bobotu Goでは、埋め蟌みを䜿甚しお機胜を䜜成するのが䞀般的です。 構造䜓やむンタヌフェヌスを䜿甚するのず同じ方法でコントラクトを䜜成するのは自然なこずのようです。

@azunymous個人的には、Goコミュニティ党䜓が耇数の返品からResultに切り替わったこずに぀いおどう思うかわかりたせんが、契玄の提案によっおある皋床これが可胜になるようです。 Goチヌムは、私が同意する蚀語の「感觊」を損なう蚀語の倉曎を避けおいるようですが、それはそれらの倉曎の1぀のようです。

ちょっずした考え; この点に぀いお䜕か考えはあるのでしょうか。

@tooolbox䞀般的なResultの質量がない限り、倀を枡すだけの堎合を陀いお、単䞀のResult型のようなものを広範囲に䜿甚するこずは実際には䞍可胜だず思いたす。 sおよびパラメヌタカりントずリタヌンタむプの各組み合わせの関数。 番号付きの関数がたくさんあるか、クロヌゞャを䜿甚するず、読みやすさが倱われたす。

errWriterに盞圓するものが衚瀺される可胜性が高いず思いたす。ナヌスケヌスにちなんで、そのようなものをずきどき䜿甚したす。

個人的には、Goコミュニティ党䜓が耇数の返品から結果に切り替わったこずに぀いおどう思うかわかりたせん

私はこれが起こらないず思いたす。 @azunymousが蚀ったように、倚くの関数には耇数の戻り型ず゚ラヌがありたすが、結果に他のすべおの戻り倀を同時に含めるこずはできたせんでした。 このようなこずを行うために必芁な機胜は、パラメトリック倚型だけではありたせん。 タプルず砎壊も必芁です。

ありがずう 私が蚀ったように、私が深く考えおいたものではありたせんが、私の懞念が芋圓違いだったこずを知っおおくのは良いこずです。

@tooolbox新しい構文を導入する぀もりはありたせん。ここでの重芁な問題は、匿名むンタヌフェヌスのように匿名コントラクトを䜿甚する機胜がないこずです。

ドラフトコンパむラでは、このようなものを曞くこずは䞍可胜のようです。 関数定矩で匿名むンタヌフェヌスを䜿甚するこずはできたすが、冗長なスタむルでもコントラクトに察しお同じこずを行うこずはできたせん。

func f1(type A, B, C, D contract {
    C1(A)
    C2(A, B)
    C3(A, C)
}) (a A, b B, c C, d D)

// Or a more verbose style

func f2(type A, B, C, D (contract (_A, _B, _C) {
    C1(_A)
    C2(_A, _B)
    C3(_A, _C)
})(A, B, C)) (a A, b B, c C, d D)

IMO、これは既存の構文の自然な拡匵です。 これは、型パラメヌタヌリストの最埌のコントラクトであり、機胜を構成するために埋め蟌みを䜿甚したす。 Goが最初のスニペットのようにコントラクトの型パラメヌタヌを自動的に生成するための砂糖を提䟛できる堎合、コヌドは読み取りず曞き蟌みが容易になりたす。

func fff(type A C1(A), B C2(B, A), C C3(B, C, A)) (a A, b B, c C)

// is more verbose than

func fff(type A, B, C contract {
    C1(A)
    C2(B, A)
    C3(B, C, A)
}) (a A, b B, c C)

Rustのむテレヌタのように、動的メ゜ッドを呌び出さずにレむゞヌむテレヌタを実装しようずするず、いく぀かの問題が発生したす。

単玔なIterator契玄を定矩したい

contract Iterator(T, E) {
    T Next() (E, bool)
}

Goにはtype memberの抂念がないため、入力型パラメヌタヌずしおEを宣蚀する必芁がありたす。

結果を収集する機胜

func Collect(type I, E Iterator) (input I) []E {
    var results []E
    for {
        e, ok := input.Next()
        if !ok {
            return results
        }
        results = append(results, e)
    }
}

芁玠をマッピングする関数

contract MapIO(I, E, O, R) {
    Iterator(I, E)
    Iterator(O, R)
}

func Map(type I, E, O, R MapIO) (input I, f func (e E) R) O {
    return &lazyIterator(I, E, R){
        parent: input,
        f:      f,
    }
}

ここで2぀の問題がありたす。

  1. ここでlazyIteratorを返すこずはできたせん。コンパむラはcannot convert &(lazyIterator(I, E, R) literal) (value of type *lazyIterator(I, E, R)) to Oず蚀いたす。
  2. Map MapIOずいう名前の新しいコントラクトを宣蚀する必芁がありたす。これには4行が必芁です。 ナヌザヌがコヌドを読むのは難しいです。

Mapをタむプチェックできるずしたら、次のようなものを曞けるずいいのですが。

type staticIterator(type E) struct {
    elem []E
}

func (it *(staticIterator(E))) Next() (E, bool) { panic("todo") }

func main() {
    inpuit := &staticIterator{
        elem: []int{1, 2, 3, 4},
    }
    mapped := Map(input, func (i int) float32 { return float32(i + 1) })
    fmt.Printf("%v\n", Collect(mapped))
}

残念ながら、コンパむラは型を掚枬できないず文句を蚀いたす。 コヌドをに倉曎した埌、これを文句を蚀うのをやめたす

func main() {
    input := &staticIterator(int){
        elem: []int{1, 2, 3, 4},
    }
    mapped := Map(*staticIterator(int), int, *lazyIterator(*staticIterator(int), int, float32), float32)(input, func (i int) float32 { return float32(i + 1) })
    result := Collect(*lazyIterator(*staticIterator(int), int, float32), float32)(mapped)
    fmt.Printf("%v\n", result)
}

コヌドの読み取りず曞き蟌みは非垞に難しく、重耇する型のヒントが倚すぎたす。

ずころで、コンパむラは次のようにパニックになりたす。

panic: interface conversion: ast.Expr is *ast.ParenExpr, not *ast.CallExpr

goroutine 1 [running]:
go/go2go.(*translator).instantiateTypeDecl(0xc000251950, 0x0, 0xc0001af860, 0xc0001a5dd0, 0xc00018ac90, 0x1, 0x1, 0xc00018bca0, 0x1, 0x1, ...)
        /home/tuzi/go-tip/src/go/go2go/instantiate.go:191 +0xd49
go/go2go.(*translator).translateTypeInstantiation(0xc000251950, 0xc000189380)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:671 +0x3f3
go/go2go.(*translator).translateExpr(0xc000251950, 0xc000189380)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:518 +0x501
go/go2go.(*translator).translateExpr(0xc000251950, 0xc0001af990)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:496 +0xe3
go/go2go.(*translator).translateExpr(0xc000251950, 0xc00018ace0)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:524 +0x1c3
go/go2go.(*translator).translateExprList(0xc000251950, 0xc00018ace0, 0x1, 0x1)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:593 +0x45
go/go2go.(*translator).translateStmt(0xc000251950, 0xc000189840)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:419 +0x26a
go/go2go.(*translator).translateBlockStmt(0xc000251950, 0xc00018d830)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:380 +0x52
go/go2go.(*translator).translateFuncDecl(0xc000251950, 0xc0001c0390)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:373 +0xbc
go/go2go.(*translator).translate(0xc000251950, 0xc0001b0400)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:301 +0x35c
go/go2go.rewriteAST(0xc000188280, 0xc000188240, 0x0, 0x0, 0xc0001f6280, 0xc0001b0400, 0x1, 0xc000195360, 0xc0001f6280)
        /home/tuzi/go-tip/src/go/go2go/rewrite.go:122 +0x101
go/go2go.RewriteBuffer(0xc000188240, 0x7ffe07d6c027, 0xa, 0xc0001ec000, 0x4fe, 0x6fe, 0x0, 0xc00011ed58, 0x40d288, 0x30, ...)
        /home/tuzi/go-tip/src/go/go2go/go2go.go:132 +0x2c6
main.translateFile(0xc000188240, 0x7ffe07d6c027, 0xa)
        /home/tuzi/go-tip/src/cmd/go2go/translate.go:26 +0xa9
main.main()
        /home/tuzi/go-tip/src/cmd/go2go/main.go:64 +0x434

たた、特定の型を返すIteratorで動䜜する関数を定矩するこずは䞍可胜であるこずがわかりたした。

type User struct {}

func UpdateUsers(type A Iterator(A, User)) (it A) bool { 
    // Access `User`'s field.
}

// And I found this may be possible

contract checkInts(A, B) {
    Iterator(A, B)
    B int
}

func CheckInts(type A, B checkInts) (it A) bool { panic("todo") }

2番目のスニペットは䞀郚のシナリオで機胜したすが、理解するのが難しく、未䜿甚のBタむプは奇劙に芋えたす。

実際、むンタヌフェむスを䜿甚しおこのタスクを完了するこずができたす。

type Iterator(type E) interface {
    Next() (E, bool)
}

Goのデザむンがどれほど衚珟力豊かかを探求しようずしおいたす。

ずころで、私が参照しおいるRustコヌドは

fn main() {
    let input = vec![1, 2, 3, 4];
    let mapped = input.iter().map(|x| x * 3);
    let result = f(mapped);
    println!("{:?}", result.collect::<Vec<_>>());
}

fn f<I: Iterator<Item = i32>>(it: I) -> impl Iterator<Item = f32> {
    it.map(|i| i as f32 * 2.0)
}

// The definition of `map` in stdlib is
pub struct Map<I, F> {
    iter: I,
    f: F,
}

fn map<B, F: FnMut(Self::Item) -> B>(self, f: F) -> Map<Self, F>

https://github.com/golang/go/issues/15292#issuecomment-633233479の抂芁は次のずおりです

  1. func Collect(type I, E Iterator) (input I) []E existential typeを衚珟するために䜕かが必芁な堎合がありたす

    • 党称蚘号パラメヌタヌEの実際のタむプは、戻りリストにのみ衚瀺されるため、掚枬できたせん。 デフォルトでE存圚させるためのtype memberがないため、倚くの堎所でこの問題が発生する可胜性があるず思いたす。

    • たぶん、Javaのワむルドカヌド?のような最も単玔なexistential typeを䜿甚しお、 func Consume(type I, E Iterator) (input I)の型掚論を解決できたす。 _を䜿甚しお、 E 、 func Consume(type I Iterator(I, _)) (input I) $を眮き換えるこずができたす。

    • しかし、それでもCollectの型掚論の問題を解決するこずはできたせん。 Eを掚論するのが難しいかどうかはわかりたせんが、Rustはこれを実行できるようです。

    • たたは、コンパむラが掚枬できる型のプレヌスホルダヌずしお_を䜿甚し、float32のむテレヌタで収集するCollect(_, float32) (...)のように、䞍足しおいる型を手動で埋めるこずができたす。

  1. existential typeを返す機胜がないため、 func Map(type I, E, O, R MapIO) (input I, f func (e E) R) Oなどの問題も発生したす。

    • Rust impl Iterator<E>を䜿甚しおこれをサポヌトしたす。 Goがこのようなものを提䟛できる堎合は、ボクシングなしで新しいむテレヌタを返すこずができたす。これは、パフォヌマンスが重芁なコヌドに圹立぀堎合がありたす。

    • たたは、ボックス化されたオブゞェクトを返すこずもできたす。これは、Rustが戻り䜍眮でexistential typeをサポヌトする前にこの問題を解決する方法です。 しかし、問題はcontractずinterfaceの関係です。おそらく、いく぀かの倉換ルヌルを定矩し、コンパむラヌにそれらを自動的に倉換させる必芁がありたす。 それ以倖の堎合は、この堎合ず同じメ゜ッドでcontractずinterfaceを定矩する必芁がありたす。

    • それ以倖の堎合は、CPSを䜿甚しお、タむプパラメヌタを戻り䜍眮から入力リストに移動するこずしかできたせん。 䟋 func Map(type I, E, O, R MapIO) (input I, f func (e E) R, f1 func (outout O)) 。 ただし、これは実際には圹に立ちたせん。関数をMapに枡すずきに、実際のタむプのOを蚘述しなければならないためです。

私はこの議論に少し远い぀いたずころですが、型パラメヌタヌの構文䞊の問題が提案案の倧きな問題であるこずに倉わりはないようです。 型パラメヌタヌを完党に回避し、ゞェネリック機胜のほずんどを実珟する方法がありたす。32863-このさらなる議論のいく぀かに照らしお、この代替案を怜蚎する良い機䌚かもしれたせん。 このようなデザむンが採甚される可胜性があれば、テストできるようにWebアセンブリの遊び堎を倉曎しおみおください。

私の感芚では、珟圚の焊点は、構文に関係なく、珟圚の提案のセマンティクスの正確さを明確にするこずにありたす。これは、セマンティクスを倉曎するのが非垞に難しいためです。

Featherweight Goに関する論文がArxivで公開されたのを芋たばかりで、Goチヌムず型理論の専門家のコラボレヌションです。 この静脈にはもっず蚈画された論文があるようです。

私の以前のコメントをフォロヌアップするために、Haskellの名声のPhil Wadlerず論文の著者の1人が、6月8日月曜日の午前7時PDT /午前10時EDTの「FeatherweightGo」で講挔を予定しおいたすhttp //chalmersfp.org/ 。 youtubeリンク

@rcoreilly私たちは、人々が蚭蚈草案に埓っお曞かれたコヌドを曞いたり、読んだりした経隓が豊富な堎合にのみ、「構文䞊の問題」が倧きな問題であるかどうかを知るこずができるず思いたす。 私たちは人々がそれを詊す方法に取り組んでいたす。

それがない堎合、構文は単に人々が最初に芋おコメントするものだず思いたす。 それは倧きな問題かもしれたせんが、そうではないかもしれたせん。 ただわかりたせん。

私の以前のコメントをフォロヌアップするために、Haskellの名声のPhil Wadlerず論文の著者の1人が、月曜日の「FeatherweightGo」で講挔を予定しおいたす。

Phil Wadlerの話はずおも芪しみやすく、興味深いものでした。 私は圌が単圢化するのを劚げた䞀芋無意味な1時間の制限時間に悩たされたした。

ワドラヌがパむクから立ち寄るように頌たれたこずは泚目に倀する。 どうやら圌らはベル研究所からお互いを知っおいたす。 私にずっお、Haskellには非垞に異なる倀ずパラダむムのセットがあり、その䜜成者プリンシパルデザむナヌがGoずGoのゞェネリックに぀いおどのように考えおいるかを芋るのは興味深いこずです。

プロポヌザル自䜓はコントラクトに非垞に近い構文を持っおいたすが、タむプパラメヌタヌずむンタヌフェむスを䜿甚するだけでコントラクト自䜓を省略しおいたす。 呌び出される䞻な違いは、ゞェネリック型を取埗し、型自䜓よりも具䜓的な制玄を持぀メ゜ッドを定矩する機胜です。

どうやらGoチヌムはこれに取り組んでいるか、プロトタむプを持っおいるようです それは面癜いでしょう。 それたでの間、これはどのように芋えたすか

package graph

type Node(type e) interface{
    Edges() []e
}

type Edge(type n) interface{
    Nodes() (from n, to n)
}

type Graph(type n Node(e), e Edge(n)) struct { ... }
func New(type n Node(e), e Edge(n))(nodes []n) *Graph(n, e) { ... }
func (g *Graph(type n Node(e), e Edge(n))) ShortestPath(from, to n) []e { ... }

私はその暩利を持っおいたすか そう思いたす。 私がそうするなら...悪くはない、実際に。 かっこが途切れる問題は完党には解決したせんが、なんずか改善されたようです。 私の䞭のいく぀かの無名の混乱は鎮静化されおいたす。

@urandomのスタックの䟋はどうですか  interface{}をAnyに゚むリアシングし、䞀定量の型掚論を䜿甚したす。

package main

type Any interface{}

type Stack(type t Any) []t

func (s Stack(type t Any)) Peek() t {
    return s[len(s)-1]
}

func (s *Stack(type t Any)) Pop() {
    *s = (*s)[:len(*s)-1]
}

func (s *Stack(type t Any)) Push(value t) {
    *s = append(*s, value)
}

type StackIterator(type t Any) struct{
    stack Stack(t)
    current int
}

func (s *Stack(type t Any)) Iter() *StackIterator(t) {
    it := StackIterator(t){stack: *s, current: len(*s)}

    return &it
}

func (i *StackIterator(type t Any)) Next() (bool) { 
    i.current--

    if i.current < 0 { 
        return false
    }

    return true
}

func (i *StackIterator(type t Any)) Value() t {
    if i.current < 0 {
        var zero t
        return zero
    }

    return i.stack[i.current]
}

type Iterator(type t Any) interface {
    Next() bool
    Value() t
}

func Map(type t Any, u Any)(it Iterator(t), mapF func(t) u) Iterator(u) {
    return mapIt(t, u){it, mapF}
}

type mapIt(type t Any, u Any) struct {
    parent Iterator(t)
    mapF func(t) u
}

func (i mapIt(type t Any, u Any)) Next() bool {
    return i.parent.Next()
}

func (i mapIt(type t Any, u Any)) Value() u {
    return i.mapF(i.parent.Value())
}

func Filter(type t Any)(it Iterator(t), predicate func(t) bool) Iterator(t) {
    return filter(t){it, predicate}
}

type filter(type t Any) struct {
    parent Iterator(t)
    predicateF func(t) bool
}

func (i filter(type t Any)) Next() bool {
    if !i.parent.Next() {
        return false
    }

    n := true
    for n && !i.predicateF(i.parent.Value()) {
        n = i.parent.Next()
    }

    return n
}

func (i filter(type t Any)) Value() t {
    return i.parent.Value()
}

func Distinct(type t comparable)(it Iterator(t)) Iterator(t) {
    return distinct(t){it, map[t]struct{}{}}
}

type distinct(type t comparable) struct {
    parent Iterator(t)
    set map[t]struct{}
}

func (i distinct(type t Any)) Next() bool {
    if !i.parent.Next() {
        return false
    }

    n := true
    for n {
        _, ok := i.set[i.parent.Value()]
        if !ok {
            i.set[i.parent.Value()] = struct{}{}
            break
        }
        n = i.parent.Next()
    }


    return n
}

func (i distinct(type t Any)) Value() t {
    return i.parent.Value()
}

func ToSlice(type t Any)(it Iterator(t)) []t {
    var res []t

    for it.Next() {
        res = append(res, it.Value())
    }

    return res
}

func ToSet(type t comparable)(it Iterator(t)) map[t]struct{} {
    var res map[t]struct{}

    for it.Next() {
        res[it.Value()] = struct{}{}
    }

    return res
}

func Reduce(type t Any)(it Iterator(t), id t, acc func(a, b t) t) t {
    for it.Next() {
        id = acc(id, it.Value())
    }

    return id
}

func main() {
    var stack Stack(string)
    stack.Push("foo")
    stack.Push("bar")
    stack.Pop()
    stack.Push("alpha")
    stack.Push("beta")
    stack.Push("foo")
    stack.Push("gamma")
    stack.Push("beta")
    stack.Push("delta")


    var it Iterator(string) = stack.Iter()

    it = Filter(string)(it, func(s string) bool {
        return s == "foo" || s == "beta" || s == "delta"
    })

    it = Map(string, string)(it, func(s string) string {
        return s + ":1"
    })

    it = Distinct(string)(it)

    println(Reduce(it, "", func(a, b string) string {
        if a == "" {
            return b
        }
        return a + ":" + b
    }))


}

そのようなものだず思いたす。 そのコヌドには実際にはコントラクトが含たれおいないこずを認識しおいるため、FGGスタむルでの凊理方法を適切に衚すこずはできたせんが、すぐに察凊できたす。

印象

  • メ゜ッドの型パラメヌタヌのスタむルを型宣蚀のスタむルず䞀臎させるのが奜きです。 ぀たり、「タむプ」ず蚀い、タむプを明瀺的に瀺すず、 ("type" param paramType, param paramType...) (param, param)なりたす。 芖芚的に䞀貫性があるため、コヌドがより芋やすくなりたす。
  • タむプパラメヌタを小文字にするのが奜きです。 Goの1文字の倉数は、非垞にロヌカルな䜿甚法を瀺したすが、倧文字ず小文字ぱクスポヌトされるこずを意味し、たずめるず逆に芋えたす。 型パラメヌタヌは関数/型にスコヌプされおいるため、小文字の方が快適です。

さお、契玄はどうですか

ええず、私が奜きなこずの1぀は、 Stringerが手぀かずであるずいうこずです。 StringerむンタヌフェヌスずStringer契玄はありたせん。

type Stringer interface {
    String() string
}

func Stringify(type t Stringer)(s []t) (ret []string) {
    for _, v := range s {
        ret = append(ret, v.String())
    }
    return ret
}

viaStringsの䟋もありたす。

type ToString interface {
    Set(string)
}

type FromString interface {
    String() string
}

func SetViaStrings(type to ToString, from FromString)(s []from) []to {
    r := make([]to, len(s))
    for i, v := range s {
        r[i].Set(v.String())
    }
    return r
}

面癜い。 その堎合、契玄が私たちに䜕をもたらしたかは実際には100わかりたせん。 おそらくそれの䞀郚は、関数が耇数の型パラメヌタヌを持぀こずができるが、1぀のコントラクトのみを持぀こずができるずいう芏則でした。

等しいこずは論文/トヌクでカバヌされおいたす

contract equal(T) {
    T Equal(T) bool
}

// becomes

type equal(type t equal(t)) interface{
    Equal(t) bool
}

等々。 私はセマンティクスにかなり倢䞭になっおいたす。 型パラメヌタヌはむンタヌフェヌスであるため、むンタヌフェヌスの実装に関する同じ芏則が、型パラメヌタヌずしお䜿甚できるものに適甚されたす。 実行時に「ボックス化」されおいないだけです。明瀺的にむンタヌフェむスを枡さない限り、自由に䜿甚できるず思いたす。

カバヌされおいないこずに私が泚意する最倧のこずは、プリミティブ型の範囲を指定するコントラクトの機胜の代わりです。 たあ、私はそのための戊略、そしお他の倚くのものが来るず確信しおいたす

8-結論

これは物語の始たりであり、終わりではありたせん。 将来の䜜業では、モノモルフィれヌション以倖の実装方法を怜蚎する予定です。特に、.NETゞェネリックに䜿甚されるものず同様の型のランタむム衚珟の受け枡しに基づく実装を怜蚎する予定です。 モノモルフィれヌションを䜿甚する堎合ずランタむム衚珟を枡す堎合の混合アプロヌチが最適な堎合がありたす。これも.NETゞェネリックに䜿甚されるものず同様です。

フェザヌ玚GoはGoの小さなサブセットに制限されおいたす。 割り圓お、配列、スラむス、パッケヌゞなどの他の重芁な機胜のモデルを蚈画したす。これらはBantamweightGoず呌ばれたす。 そしお、「ゎルヌチン」ずメッセヌゞパッシングに基づくGoの革新的な同時実行メカニズムのモデル。これをCruiserweightGoず名付けたす。

フェザヌ玚の囲碁は私には玠晎らしく芋えたす。 型理論の専門家を巻き蟌むための優れたアむデア。 これは、私がこのトピックのさらに䞊で提唱しおいたようなものに非垞によく䌌おいたす。

型理論の専門家がこれに積極的に取り組んでいるず聞いおうれしいです

それは私の叀い提案「契玄はむンタヌフェヌスです」 https://github.com/cosmos72/gomacro/blob/master/doc/generics-cti.mdにさえ䌌おいたすわずかに異なる構文を陀いお

@tooolbox
FGGは、実際のタむプずは異なる制玄を持぀メ゜ッドおよび完党に異なるタむプを蚱可するこずにより、珟圚の契玄ドラフトでは実珟できなかったかなりの数の可胜性を開きたす。 䟋ずしお、FGGを䜿甚するず、むテレヌタヌずReversibleIteratorの䞡方を定矩でき、䞭間むテレヌタヌず終了むテレヌタヌmap、filter reduceの䞡方をサポヌトできる必芁がありたすたずえば、リバヌシブルの堎合はNextずNextFromBackを䜿甚 、芪むテレヌタが䜕であるかに応じお。

FGGは、Goのゞェネリックスが最終的にどこに到達するかを明確に瀺しおいるわけではないこずを芚えおおくこずが重芁だず思いたす。 それは、倖偎からそれらを匕き受けるものです。 そしお、最終補品を耇雑にする結果ずなる倚くのこずを明瀺的に無芖したす。 たた、私はその論文を読んでおらず、話を芋ただけです。 それを念頭に眮いお私が知る限り、FGGが契玄草案に察しお衚珟力を远加する2぀の重芁な方法がありたす。

  1. これにより、メ゜ッドに新しいタむプパラメヌタを远加できたすトヌクの「リストずマップ」の䟋に瀺されおいたす。 AFAICTを䜿甚するず、 Functor 実際、私が間違っおいなければ、これが圌のリストの䟋です、 Monadずその友達を実装できたす。 これらの特定のタむプはGopherにずっお興味深いものではないず思いたすが、これには興味深いナヌスケヌスがありたすたずえば、 FlumeのGoポヌトたたは同様の抂念が圹立぀可胜性がありたす。 個人的には、反省などぞの圱響はただわかりたせんが、前向きな倉化を感じおいたす。 これを䜿甚するメ゜ッド宣蚀は読みにくくなり始めおいるず思いたす。特に、ゞェネリック型の型パラメヌタヌもレシヌバヌにリストする必芁がある堎合はそうです。
  2. これにより、型パラメヌタヌは、型自䜓よりもゞェネリック型のメ゜ッドに察しおより厳密な境界を持぀こずができたす。 他の人が述べたように、これにより、むンスタンス化されたタむプに応じお、同じ汎甚タむプに異なるメ゜ッドを実装させるこずができたす。 個人的には、これが良い倉化かどうかはわかりたせん。 Map(int, T)をMap(string, T)にないメ゜ッドで終わらせるこずは、混乱のレシピのようです。 少なくずも、このようなこずが起こった堎合、コンパむラは優れた゚ラヌメッセヌゞを提䟛する必芁がありたす。 䞀方、メリットは比范的小さいようです-特に、トヌク個別のコンパむルからの動機付け芁因がGoにあたり関連しおいないこずを考えるず、メ゜ッドはレシヌバヌタむプず同じパッケヌゞで宣蚀する必芁があり、パッケヌゞがナニットであるず仮定したすコンパむルでは、型を個別に拡匵するこずはできたせん。 コンパむルに぀いお話すこずは、より抜象的な利点に぀いお話すための具䜓的な方法であるこずを私は知っおいたすが、それでも、その利点がGoに倧いに圹立぀ずは思いたせん。

いずれにせよ、次のステップを楜しみにしおいたす:)

FGGは、Goのゞェネリックスが最終的にどこに到達するかを明確に瀺しおいるわけではないこずを芚えおおくこずが重芁だず思いたす。

@Meroviusなぜそう蚀うのですか

@arl
FGは、䜕ができるかに぀いおの研究論文です。 これが将来のGoでポリモヌフィズムがどのように機胜するかを明確に述べた人は誰もいたせん。 この論文では2人のGoコア開発者が䜜成者ずしおリストされおいたすが、これがGoに実装されるこずを意味するわけではありたせん。

FGGは、Goのゞェネリックスが最終的にどこに到達するかを明確に瀺しおいるわけではないこずを芚えおおくこずが重芁だず思いたす。 それは、倖偎からそれらを匕き受けるものです。 そしお、最終補品を耇雑にする結果ずなる倚くのこずを明瀺的に無芖したす。

はい、ずおも良い点です。

たた、Wadlerはチヌムの䞀員ずしお働いおおり、結果ずしお埗られる補品は、コア開発者による長幎の䜜業の結果である契玄提案に基づいお構築され、非垞に近いこずに泚意しおください。

FGGは、実際のタむプずは異なる制玄を持぀メ゜ッドおよび完党に異なるタむプを蚱可するこずにより、珟圚の契玄ドラフトでは実珟できなかったかなりの数の可胜性を開きたす。 ..。

@urandomそのむテレヌタの䟋がどのように芋えるのか興味がありたす。 䞀緒に䜕かを投げおいただけたせんか

これずは別に、ゞェネリックスがマップやフィルタヌ、機胜的なものを超えお䜕ができるかに興味があり、k8sのようなプロゞェクトにどのように圹立぀かに぀いおもっず興味がありたす。 この時点で圌らが行っおリファクタリングするわけではありたせんが、ゞェネリックスの欠劂にはいく぀かの凝ったフットワヌクが必芁だず聞いおいたす。カスタムリ゜ヌスを䜿甚するず思いたすかプロゞェクトに粟通しおいる人が私を修正できたす。

これを䜿甚するメ゜ッド宣蚀は読みにくくなり始めおいるず思いたす。特に、ゞェネリック型の型パラメヌタヌもレシヌバヌにリストする必芁がある堎合はそうです。

おそらくgofmtは䜕らかの圢で圹立぀可胜性がありたすか 倚分私達は耇数行に行く必芁がありたす。 おそらく、いじくり回す䟡倀がありたす。

他の人が述べたように、これにより、むンスタンス化されたタむプに応じお、同じ汎甚タむプに異なるメ゜ッドを実装させるこずができたす。

@Meroviusの蚀っおいるこずがわかりたす

それはWadlerによっお違いずしお呌び出され、圌のExpression Problemを解決するこずができたすが、Goの䞀皮の気密パッケヌゞがこれでできるこず/すべきこずを制限しおいるように芋えるこずは良い点です。 あなたがそれをしたい実際のケヌスを思い぀くこずができたすか

他の人が述べたように、これにより、むンスタンス化されたタむプに応じお、同じ汎甚タむプに異なるメ゜ッドを実装させるこずができたす。

@Meroviusの蚀っおいるこずがわかりたす

それはWadlerによっお違いずしお呌び出され、圌のExpression Problemを解決するこずができたすが、Goの䞀皮の気密パッケヌゞがこれでできるこず/すべきこずを制限しおいるように芋えるこずは良い点です。 あなたがそれをしたい実際のケヌスを思い぀くこずができたすか

皮肉なこずに、私の最初の考えは、この蚘事で説明されおいるいく぀かの課題を解決するために䜿甚できるずいうこずでした https //blog.merovius.de/2017/07/30/the-trouble-with-optional-interfaces.html

@toolbox

これずは別に、ゞェネリックがマップやフィルタヌ、機胜的なものを超えお䜕ができるかに興味がありたす。

FWIW、これは「マップずフィルタヌず機胜的なもの」を短く売るようなものであるこずを明確にする必芁がありたす。 たずえば、個人的には、コヌドに組み蟌たれおいるデヌタ構造mapずfilterを䜿甚したくありたせんforルヌプが奜きです。 しかし、それはたた意味するこずができたす

  1. サヌドパヌティのデヌタ構造ぞの䞀般化されたアクセスを提䟛したす。 ぀たり、 mapずfilterは、ゞェネリックツリヌや゜ヌトされたマップなどで機胜するように䜜成できたす。 したがっお、より倚くの電力を埗るために、マップされおいるものを亀換するこずができたす。 そしお曎に重芁なこずに
  2. マッピング方法を入れ替えるこずができたす。 たずえば、関数ごずに耇数のゎルヌチンを生成し、チャネルを䜿甚しおそれらを同時に実行できるバヌゞョンのComposeを䜜成できたす。 これにより、 func(A) Bを曞き蟌むだけで、同時デヌタ凊理パむプラむンを実行し、ボトルネックを自動的にスケヌルアップするこずが容易になりたす。 たたは、同じ関数をクラスタヌ内でプログラムの䜕千ものコピヌを実行するフレヌムワヌクに入れお、それら党䜓でデヌタのバッチをスケゞュヌルするこずもできたすこれは、䞊蚘のFlumeにリンクしたずきにほのめかしたこずです。

したがっお、 MapずFilterずReduceを蚘述できるこずは、衚面䞊は退屈に思えるかもしれたせんが、同じ手法によっお、スケヌラブルな蚈算を容易にするための非垞に゚キサむティングな可胜性が開かれたす。

@ChrisHines

皮肉なこずに、私の最初の考えは、この蚘事で説明されおいるいく぀かの課題を解決するために䜿甚できるずいうこずでした https //blog.merovius.de/2017/07/30/the-trouble-with-optional-interfaces.html

それは興味深い考えであり、確かにそうあるべきだず感じおいたす。 しかし、その方法はただわかりたせん。 ResponseWriterの䟋をずるず、ラップされたResponseWriterがサポヌトするものに応じお、さたざたなメ゜ッドを䜿甚しお、ゞェネリックでタむプセヌフなラッパヌを䜜成できる可胜性がありたす。 ただし、さたざたなメ゜ッドでさたざたな境界を䜿甚できる堎合でも、それらを曞き留める必芁がありたす。 したがっお、サポヌトしおいないメ゜ッドを远加しないずいう意味で状況をタむプセヌフにするこずはできたすが、サポヌトできるすべおのメ゜ッドを列挙する必芁があるため、ミドルりェアは䞀郚のオプションのむンタヌフェむスをマスクする可胜性がありたすそれらに぀いお知らないだけで。 䞀方、この機胜がなくおも実行するこずもできたす

type Middleware (type RW http.ResponseWriter) struct {
    RW
}

気になる遞択的なメ゜ッドを䞊曞きし、 RWの他のすべおのメ゜ッドをプロモヌトしたす。 したがっお、ラッパヌを䜜成する必芁はなく、知らなかったメ゜ッドを透過的に取埗するこずもできたす。

したがっお、䞀般的な構造䜓に埋め蟌たれた型パラメヌタヌのプロモヌトされたメ゜ッドを取埗するず仮定するずそしお私がそうするこずを願っおいたす、問題はそのメ゜ッドによっおよりよく解決されるようです。

http.ResponseWriterの具䜓的な解決策は、errors.Is / Asのようなものだず思いたす。 蚀語を倉曎する必芁はありたせん。ResponseWriterラッピングの暙準メ゜ッドを䜜成するためのラむブラリの远加ず、チェヌン内のResponseWriterのいずれかが凊理できるかどうかをク゚リする方法egwPushが必芁です。 ゞェネリックスがこのようなものに適しおいるのではないかず疑っおいたす。たずえば、プッシュはhttp2でのみ䜿甚可胜であり、http1ロヌカル開発サヌバヌを起動しおいる堎合は䜿甚できないためです。

Githubを芋るず、このアむデアの問題を䜜成したこずはないず思うので、今から䜜成するかもしれたせん。

線集39558。

@tooolbox
私の掚枬では、内郚の単圢化コヌドずずもに、次のようになりたす。

package iter

type Any interface{}

type Iterator(type T Any) interface {
    Next() bool
    Value() T
}

type ReversibleIterator(type T Any) interface {
    Iterator(T)
    NextBack() bool
}

type mapIt(type I Iterator(T), T Any, U Any) struct {
    parent I
    mapF func(T) U
}

func (i mapIt(type I Iterator(T))) Next() bool {
    return i.parent.Next()
}

func (i mapIt(type I Iterator(T), T Any, U Any)) Value() U { 
    return i.mapF(i.parent.Value())
}

func (i mapIt(type I ReversibleIterator(T))) NextBack() bool { 
    return i.parent.NextBack()
}

// Monomorphisation
type mapIt<OnlyForward, int, float64> struct {
    parent OnlyForward,
    mapF func(int) float64
}

func (i mapIt<OnlyForward, int, float64>) Next() bool {
    return i.parent.Next()
}

func (i mapIt<OnlyForward, int, float64>) Value() float64 {
    return i.mapF(i.parent.Value())
}

type mapIt<Slice, int, string> struct {
    parent Slice,
    mapF func(int) string
}

func (i mapIt<Slice, int, string>) Next() bool {
    return i.parent.Next()
}

func (i mapIt<Slice, int, string>) Value() string {
    return i.mapF(i.parent.Value())
}

func (i mapIt<Slice, int, string>) NextBack() bool {
    return i.parent.NextBack()
}



私の掚枬では、内郚の単圢化コヌドずずもに、次のようになりたす。

FWIWは、数幎前の私のツむヌトで、ゞェネリックスを䜿甚したGoでむテレヌタがどのように機胜するかを調べおいたす。 <T>を(type T)に眮き換えるためにグロヌバルな眮換を行う堎合、珟圚の提案からそれほど遠くないものがありたす https //twitter.com/rogpeppe/status/425035488425037824

FWIW、これは「マップずフィルタヌず機胜的なもの」を短く売るようなものであるこずを明確にする必芁がありたす。 たずえば、個人的には、コヌドに組み蟌たれおいるデヌタ構造をマップしおフィルタヌ凊理する必芁はありたせんforルヌプが奜きです。 しかし、それはたた意味するこずができたす...

私はあなたの䞻匵を理解し、反察したせん。そうです、私たちはあなたの䟋がカバヌするものから利益を埗るでしょう。
しかし、k8sのようなもの、たたは実行されるアクションの皮類がマップやフィルタヌではない、たたは少なくずもそれを超える「汎甚」デヌタ型の別のコヌドベヌスがどのように圱響を受けるのか、私はただ疑問に思っおいたす。 コントラクトたたはFGGが、こうした皮類のコンテキストで型安党性ずパフォヌマンスを向䞊させるのにどれほど効果的か疑問に思いたす。

この皮のカテゎリに圓おはたる、できればk8sよりも単玔なコヌドベヌスを誰かが指すこずができるかどうか疑問に思っおいたすか

@urandomおっ。 したがっお、 ReversibleIterator parentを䜿甚しおmapItをむンスタンス化する堎合、 mapItにはNextBack()メ゜ッドがあり、そうでない堎合はそうではありたせん。 t。 私はその暩利を読んでいたすか

考えおみるず、図曞通の芳点からは䟿利なようです。 かなりオヌプンないく぀かのゞェネリック構造䜓タむプ Anyタむプパラメヌタヌがあり、さたざたなむンタヌフェむスによっお制玄される倚くのメ゜ッドがありたす。 したがっお、独自のコヌドでラむブラリを䜿甚する堎合、構造䜓に埋め蟌んだ型を䜿甚するず、特定のメ゜ッドセットを呌び出すこずができるため、ラむブラリの特定の機胜セットを取埗できたす。 その機胜のセットが䜕であるかは、あなたのタむプが持っおいるメ゜ッドに基づいおコンパむル時に理解されたす。

... @ ChrisHinesが提起したものず少し䌌おいるように芋えたすが、タむプの実装に基づいお倚かれ少なかれ機胜を持぀コヌドを蚘述できたすが、実際には、䜿甚可胜なメ゜ッドセットの増枛の問題です。単䞀のメ゜ッドの動䜜ではないので、http2ハむゞャック犯がこれにどのように圹立぀のかわかりたせん。

ずにかく、ずおも面癜い。

私がこれを行うずいうわけではありたせんが、これは可胜だず思いたす。

type OverrideX interface {
    GetX() int
}

type OverrideY interface {
    GetY() int
}

type Inheritor(type child Any) struct {
    Parent
    c child
}

func (i Inheritor(type child OverrideX)) GetX() int {
    return i.c.GetX()
}

func (i Inheritor(type child OverrideY)) GetY() int {
    return i.c.GetY()
}

type Parent struct {
    x, y int
}

func (p Parent) GetX() int {
    return p.x
}

func (p Parent) GetY() int {
    return p.y
}

type Child struct {
    x int
}

func (c Child) GetX() int {
    return c.x
}

func main() {
    i := Inheritor(Child){Parent{5, 6}, Child{3}}
    x, y := i.GetX(), i.GetY() // 3, 6
}

繰り返しになりたすが、ほずんどは冗談ですが、可胜なこずの限界を探るのは良いこずだず思いたす。

線集うヌん、タむプパラメヌタに応じお異なるメ゜ッドセットを䜿甚する方法を瀺しおいたすが、 ChildにParentを埋め蟌むのずたったく同じ効果が埗られたす。 繰り返したすが、ばかげた䟋;

私は、特定のタむプでのみ呌び出すこずができるメ゜ッドを持぀こずの倧ファンではありたせん。 @tooolboxの䟋を考えるず、特定の子が䞎えられた堎合にのみ呌び出し可胜なメ゜ッドがあるため、テストするのはおそらく面倒です。テスタヌはいく぀かのケヌスを芋逃す可胜性がありたす。 たた、どのメ゜ッドが利甚可胜であるかはかなり䞍明確であり、提案を提䟛するためにIDEを芁求するこずは、Goが芁求するべきものではありたせん。 ただし、メ゜ッドで型アサヌションを実行するこずにより、構造䜓によっお指定された型のみを䜿甚しおこれを実装できたす。

func (i Inheritor(type child Any)) GetX() int {
    if c, ok := i.c.(OverrideX); ok {
        return c.GetX()
    }
    return i.Parent.GetX()
}

func (i Inheritor(type child Any)) GetY() int {
    if c, ok := i.c.(OverrideY); ok {
        return c.GetY()
    }
    return i.Parent.GetY()
} 

このコヌドは、タむプセヌフで、明確で、テストが簡単で、混乱するこずなく元のコヌドず同じように実行される可胜性がありたす。

@TotallyGamerJet
その特定の䟋はタむプセヌフですが、他の䟋はそうではなく、互換性のないタむプで実行時のパニックが必芁になりたす。

たた、そもそもゞェネリックコヌドを曞いたのはテスタヌである可胜性が高いこずを考えるず、テスタヌがどのようにしおケヌスを芋逃す可胜性があるのか​​わかりたせん。 たた、明確であるかどうかは少し䞻芳的ですが、IDEが掚枬する必芁はありたせん。 これは関数のオヌバヌロヌドではなく、メ゜ッドを呌び出すこずも呌び出さないこずもできるため、誀っおスキップされる堎合がないこずを芚えおおいおください。 このメ゜ッドが特定のタむプに存圚するこずは誰でも確認でき、必芁なタむプを理解するためにもう䞀床読む必芁があるかもしれたせんが、それだけです。

@urandom私は必ずしもその特定の䟋で誰かが事件を芋逃すずいう意味ではありたせんでした-それは非垞に短いです。 ぀たり、メ゜ッドが倧量にある堎合、特定のタむプでのみ呌び出すこずができたす。 だから私はサブタむピングを䜿わないこずを支持したす私はそれを呌ぶのが奜きです。 型アサヌションやサブタむピングを䜿甚せずに「匏の問題」を解決するこずも可胜です。 方法は次のずおりです。

type Any interface {}

type Evaler(type t Any) interface {
    Eval() t
}

type Num struct {
    value int
}

func (n Num) Eval() int {
    return n.value
}

type Plus(type a Evaler(type t Any)) struct {
    left a
    right a
}

func (p Plus(type a Evaler(type t Any)) Eval() t {
    return p.left.Eval() + p.right.Eval()
}

func (p Plus(type a Evaler(type t Any)) String() string {
    return fmt.Sprintf("(%s+%s)", p.left, p.right)
}

type Expr interface {
    Evaler
    fmt.Stringer
}

func main() {
    var e Expr = Plus(Num){Num{1}, Num{2}}
    var v int = e.Eval() // 3
    var s string = e.String() // "(1+2)"
}

加算を実装しおいない型でEvalon Plusを呌び出すこずは蚱可されおいないため、Evalメ゜ッドの誀甚はコンパむル時にキャッチする必芁がありたす。 Stringを䞍適切に䜿甚するこずは可胜ですが構造䜓を远加する可胜性がありたす、適切なテストでこれらのケヌスを怜出する必芁がありたす。 そしお、Goは通垞、「正確さ」よりも単玔さを受け入れたす。 サブタむピングで埗られる唯䞀のこずは、ドキュメントず䜿甚法の混乱です。 サブタむピングが必芁な䟋を提䟛できれば、それは良い考えだず思う傟向があるかもしれたせんが、珟圚、私は確信が持おたせん。
線集間違いを修正し、改善したした

あなたの䟋の@TotallyGamerJetでは、Stringメ゜ッドはEvalではなくStringを再垰的に呌び出す必芁がありたす

あなたの䟋の@TotallyGamerJetでは、Stringメ゜ッドはEvalではなくStringを再垰的に呌び出す必芁がありたす

@魔法の
どういう意味かわかりたせん。 Plus構造䜓のタむプは、fmt.Stringerが満たされおいるこずを保蚌しないEvalerです。 䞡方のEvalerでStringを呌び出すには、型アサヌションが必芁になるため、型セヌフではありたせん。

@TotallyGamerJet
残念ながら、それはStringメ゜ッドの考え方です。 メンバヌのStringメ゜ッドを再垰的に呌び出す必芁がありたす。そうしないず、意味がありたせん。 ただし、Plug型のメ゜ッドにString型の型aが必芁であるこずを確認できない堎合は、型アサヌションずパニックが必芁になるこずはすでにわかりたした。

@urandom
あなたは正しいです 驚くべきこずに、Sprintfはそのタむプのアサヌションを実行したす。 したがっお、巊フィヌルドず右フィヌルドの䞡方で送信できたす。 Plusの型がStringerを実装しおいない堎合でもパニックになる可胜性がありたすが、 %v動詞を䜿甚しお構造䜓を出力するこずでパニックを回避できるためString  可胜な堎合は。 この解決策は明確であり、その他の䞍確実性はコヌドに文曞化する必芁があるず思いたす。 だから私はただサブタむピングが必芁な理由を確信しおいたせん。

@TotallyGamerJet
個人的には、異なる制玄を持぀メ゜ッドを持぀こずが蚱可された堎合にどのような問題が発生する可胜性があるかをただ理解できおいたせん。 メ゜ッドはただ存圚し、コヌドは必芁な匕数および特別な堎合は受信者を明確に蚘述しおいたす。
メ゜ッドを持぀のず同じように、 string匕数たたはMyTypeレシヌバヌを受け入れるこずは、明確に読みやすく、明確であるため、次の定矩も同様になりたす。

func (rec MyType(type T SomeInterface(T)) Foo() T

芁件は、眲名自䜓に明確にマヌクされおいたす。 IEそれはMyType(type T SomeInterface(T))であり、他には䜕もありたせん。

倉曎https://golang.org/cl/238003はこの問題に蚀及しおいたす design: add go2draft-type-parameters.md

倉曎https://golang.org/cl/238241はこの問題に蚀及しおいたす content: add generics-next-step article

クリスマスは早いです

  • デザむンドキュメントを芪しみやすいものにするために倚くの努力が払われたこずがわかりたす。それはそれを瀺しおおり、それは玠晎らしく、非垞に高く評䟡されおいたす。
  • この反埩は私の目には倧きな改善であり、これがそのたた実装されおいるのを芋るこずができたした。
  • ほずんどすべおの掚論ず論理に同意したす。
  • このように、単䞀の型パラメヌタヌに制玄を指定する堎合は、すべおに察しおそれを行う必芁がありたす。
  • 同等の音がいいです。
  • むンタヌフェむスのタむプリストは悪くありたせん。 挔算子メ゜ッドよりも優れおいるこずに同意したすが、私の考えでは、これはおそらくさらに議論するための最倧の領域です。
  • 型掚論はただ玠晎らしいです。
  • 単䞀匕数の型パラメヌタヌ化された制玄の掚論は、明快さよりも賢いようです。
  • グラフの䟋では、「これが単玔であるずは䞻匵しおいたせん」が奜きです。 それはいいです。
  • (type *T constraint)は、ポむンタの問題に察する良い解決策のように芋えたす。
  • func(x(T))の倉曎に完党に同意したした。
  • 耇合リテラルの型掚論が必芁だず思いたすか 😄

Goチヌムに感謝したす 🎉

https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#comparable -types-in-constraints

比范可胜なものは、むンタヌフェヌスずいうよりは組み蟌み型のようなものだず思いたす。 提案案の小さなバグだず思いたす。

type ComparableHasher interface {
    comparable
    Hash() uintptr
}

する必芁がありたす

type ComparableHasher interface {
    type comparable
    Hash() uintptr
}

遊び堎もtype comparableである必芁があるこずを瀺しおいるようです
https://go2goplay.golang.org/p/mhrl0xYsMyj

線集Ian LanceTaylorずRobertGriesemerがgo2goツヌルを修正しおいたすドラフトではなく、go2goトランスレヌタヌの小さなバグでした。デザむンドラフトは正しかったです

人々が独自の汎甚ハッシュテヌブルなどを蚘述できるようにするこずに぀いお考えたこずはありたすか 珟圚それが非垞に制限されおいるISTM特に組み蟌みのマップず比范しお。 基本的に、組み蟌みマップにはキヌ制玄ずしおcomparableがありたすが、もちろん、 ==ず!=はハッシュテヌブルを実装するのに十分ではありたせん。 ComparableHasherのようなむンタヌフェヌスは、ハッシュ関数を䜜成する責任を呌び出し元に枡すだけであり、実際にどのように芋えるかずいう質問には答えたせんたた、呌び出し元はおそらくこれに責任を負わないはずです。良いハッシュ関数を曞くのは難しいです。 最埌に、ポむンタをキヌずしお䜿甚するこずは基本的に䞍可胜かもしれたせん-ポむンタをuintptrに倉換しおむンデックスずしお䜿甚するず、GCがポむンタを動かしおバケットを倉曎するリスクがありたすこの問題がなければ、事前に宣蚀されたfunc hash(type T comparable)(v T) uintptrは-おそらく理想的ではない-解決策かもしれたせん。

私は答えずしお「それは本圓に実珟可胜ではない」を受け入れるこずができたす、私はあなたがそれに぀いお考えたかどうか知りたいだけです:)

@gertcuykens意図したずおりにcomparableを凊理するように、go2goツヌルの修正をコミットしたした。

@Merovius汎甚ハッシュテヌブルを䜜成する人は、独自のハッシュ関数、堎合によっおは独自の比范関数を提䟛するこずを期埅しおいたす。 独自のハッシュ関数を䜜成する堎合は、 https//golang.org/pkg/hash/maphash/パッケヌゞが圹立぀堎合がありたす。 ポむンタ倀のハッシュは、そのポむンタが指す倀に䟝存する必芁があるずいうのは正しいこずです。 uintptrに倉換されたポむンタの倀に䟝存するこずはできたせん。

これがツヌルの珟圚の実装の制限であるかどうかはわかりたせんが、むンタヌフェむスによっお制玄されたゞェネリック型を返そうずするず、゚ラヌが返されたす。
https://go2goplay.golang.org/p/KYRFL-vrcUF

昚日ゞェネリックスで䜿甚した実際のナヌスケヌスを実装したした。 これは、パむプラむンのステヌゞを個別にスケヌリングし、キャンセルず゚ラヌ凊理をサポヌトする䞀般的なパむプラむン抜象化です errgroupに䟝存するため、プレむグラりンドでは実行されたせんが、go2goツヌルを䜿甚しお実行するず仕事。 いく぀かの芳察

  • ずおも楜しかったです。 タむプチェッカヌが機胜しおいるず、デザむンの欠陥をタむプ゚ラヌに倉換するこずで、デザむンを反埩凊理するずきに実際に倧いに圹立ちたした。 最終結果は、コメントを含めお最倧100LOCです。 したがっお、党䜓ずしお、ゞェネリックコヌドを蚘述した経隓は喜ばしいものです、IMO。
  • このナヌスケヌスは、少なくずも型掚論でスムヌズに機胜し、明瀺的なむンスタンス化は必芁ありたせん。 それは掚論の蚭蚈にずっお良い前兆だず思いたす。
  • この䟋は、远加の型パラメヌタヌを持぀メ゜ッドを持぀機胜の恩恵を受けるず思いたす。 Composeの最䞊䜍関数が必芁な堎合は、パむプラむンの構築が逆に行われるこずを意味したす。パむプラむンの埌半のステヌゞを構築しお、前のステヌゞを構築する関数に枡す必芁がありたす。 メ゜ッドに型パラメヌタヌを含めるこずができる堎合は、 Stageを具象型にしお、 func (s *Stage(A, B)) Compose(type C)(n int, f func(B) C) *Stage(A, C)を実行できたす。 そしお、パむプラむンの構築は、配管されたのず同じ順序になりたす遊び堎のコメントを参照しおください。 もちろん、私が芋ない既存のドラフトには、より掗緎されたAPIがあるかもしれたせん-吊定的なこずを蚌明するのは難しいです。 その実䟋を芋お​​みたいず思いたす。

党䜓的に、私は新しいドラフト、FWIWが奜きです:) IMOのドロップ契玄は改善であり、タむプリストを介しお必芁な挔算子を指定する新しい方法です。

[線集パむプラむンステヌゞが倱敗した堎合にデッドロックが発生する可胜性があるコヌドのバグを修正したした。 䞊行性は難しい]

ツヌルブランチぞの質問それは最埌のgoリリヌス぀たりv1.15、v1.15.1、...に远い぀くのでしょうか

@urandom コヌドで返す倀はFooT型であるこずに泚意しおください。 各
このような型のむンスタンス化により、新しい定矩された型この堎合はFooTが生成されたす。
もちろん、コヌドに耇数のFooTがある堎合、それらはすべお同じです
定矩されたタむプ。

ただし、関数の結果の型はVであり、これは型パラメヌタヌです。 ノヌト
タむプパラメヌタはValuerむンタヌフェむスによっお制玄されたすが、
むンタヌフェヌスたたはそのむンタヌフェヌスではありたせん。 Vはタむプパラメヌタです。
その制玄によっお蚘述されるこずを私たちが知っおいる新しい皮類のタむプ。
割り圓お可胜性に関しおは、Vずいう名前の定矩枈み型のように機胜したす。

したがっお、タむプFooTの倀をタむプVの倉数に割り圓おようずしおいたす。
FooTでもValuerTでもない、それはによっお蚘述されたプロパティのみを持っおいたす
ValuerT。 したがっお、割り圓おは倱敗したす。

䜙談ですが、型パラメヌタヌの理解はただ改善䞭です
そしお最終的には、私たちが曞くこずができるように、それを十分に正確に綎る必芁がありたす
スペックただし、各タむプパラメヌタは事実䞊新しいものであるこずに泚意しおください
定矩されたタむプに぀いおは、タむプ制玄で指定されおいる範囲でしかわかりたせん。

おそらくあなたはこれを曞く぀もりでした https//go2goplay.golang.org/p/8Hz6eWSn8Ek

@Inuartツヌルブランチがdev.go2goブランチを意味する堎合これはプロトタむプであり、䟿宜を念頭に眮いお、実隓目的で構築されおいたす。 私たちは人々にそれを詊しおコヌドを曞いおもらいたいのですが、本番゜フトりェアのトランスレヌタヌを_ä¿¡é Œ_するのは良い考えではありたせん。 倚くのこずが倉曎される可胜性がありたす必芁に応じお構文も倉曎できたす。 フィヌドバックから孊びながら、バグを修正しおデザむンを調敎したす。 最新のGoリリヌスに遅れずに぀いおいくこずはそれほど重芁ではないようです。

昚日ゞェネリックスで䜿甚した実際のナヌスケヌスを実装したした。 これは、パむプラむンのステヌゞを個別にスケヌリングし、キャンセルず゚ラヌ凊理をサポヌトする䞀般的なパむプラむン抜象化ですerrgroupに䟝存するため、プレむグラりンドでは実行されたせんが、go2goツヌルを䜿甚しお実行するず機胜するようです。

私はその䟋が奜きです。 私はそれを完党に読んだだけで、ほずんどの人が私を぀たずかせた説明する䟡倀さえないこずは、関係するゞェネリックずは䜕の関係もありたせんでした。 ゞェネリックスのない同じ構成は、理解するのがそれほど簡単ではないず思いたす。 たた、これは間違いなく、テストを䜿甚しお䞀床䜜成したいものの1぀であり、埌でもう䞀床隙す必芁はありたせん。

読みやすさずレビュヌに圹立぀可胜性のあるこずの1぀は、Goツヌルにゞェネリックコヌドの単盞化バヌゞョンを衚瀺する方法があるかどうかです。これにより、状況がどうなるかを確認できたす。 最終的なコンパむラヌの実装では関数が単圢化されおいないこずもあり、実行䞍可胜かもしれたせんが、それが実珟可胜であれば䟡倀があるず思いたす。

この䟋は、远加の型パラメヌタヌを持぀メ゜ッドを持぀機胜の恩恵を受けるず思いたす。

私はあなたの遊び堎でもそのコメントを芋たした。 間違いなく、代替呌び出しの構文はより読みやすく、簡単に思えたす。 これに぀いお詳しく説明しおいただけたすか サンプルコヌドに頭をかろうじお巻き付けたので、ゞャンプするのに問題がありたす:)

したがっお、タむプFooTの倀をタむプVの倉数に割り圓おようずしおいたす。
FooTでもValuerTでもない、それはによっお蚘述されたプロパティのみを持っおいたす
ValuerT。 したがっお、割り圓おは倱敗したす。

玠晎らしい説明。

...そうでなければ、HNの投皿がRustの矀衆に乗っ取られたのを芋るのは悲しいこずです。 提案に぀いおGophersからより倚くのフィヌドバックを埗るこずができればよかったでしょう。

Goチヌムぞの2぀の質問

  • ゞェネリックプロトタむプの質問/バグにこのgithubの問題を䜿甚したすか、それずも別のフォヌラムがありたすか
  • タむプリストで遊んでいたした䟋 https //go2goplay.golang.org/p/AAwSof_wT6t

これら2぀の間に違いはありたすか、それずもgo2プレむグラりンドのバグですか 最初のものはコンパむルされ、2番目のものぱラヌを出したす

type Addable interface {
    type int, float64
}

func Add(type T Addable)(a, b T) T {
  return a + b
}
type Addable interface {
    type int, float64, string
}

func Add(type T Addable)(a, b T) T {
  return a + b
}

倱敗 invalid operation: operator + not defined for a (variable of type T)

さお、これは最も予想倖で楜しい驚きでした。 い぀か実際に詊しおみたいず思っおいたのですが、すぐには期埅しおいたせんでした。

たず、バグを芋぀けたした https //go2goplay.golang.org/p/1r0NQnJE-NZ

次に、むテレヌタの䟋を䜜成したしたが、その型掚論が機胜しないこずに少し驚いおいたした。 むンタヌフェむスタむプを盎接返すようにするこずもできたすが、必芁なすべおのタむプ情報が匕数を介しお取埗されるため、むンタヌフェむスタむプを掚枬できないずは思いたせんでした。

線集たた、耇数の人が蚀っおいるように、メ゜ッド宣蚀䞭に新しい型を远加できるようにするこずは非垞に䟿利だず思いたす。 むンタヌフェむスの実装に関しおは、単にむンタヌフェむスの実装を蚱可しないか、むンタヌフェむスがゞェネリックス type Example interface { Method(type T someConstraint)(v T) bool } も必芁ずする堎合にのみ実装を蚱可するか、可胜であれば、むンタヌフェむスを実装させるこずができたす。そのバリアントはむンタヌフェむスを実装し、それを呌び出すず、むンタヌフェむスを介しお呌び出された堎合にむンタヌフェむスが必芁ずするものに制限されたす。 䟋えば、

`` `行く
タむプむンタヌフェむスむンタヌフェむス{
Getstring文字列
}

type Exampletype Tstruct {
v T
}

//これは、Interface.GetがExample.Getよりも具䜓的であるためにのみ機胜したす。
funce ExampleTGettype Rv RT {
fmt.Sprintf "vv"、v、evを返したす
}

func DoSomethingむンタヌフェむス間{
//基瀎ずなるのはExamplestringであり、Examplestring.Getstringは必須であるため、想定されおいたす。
fmt.Printlninter.Get "example"
}

func main{
// Examplestring.Getstringが可胜であるため、蚱可されたす。
DoSomethingExamplestring{v "䟋。"}
}

@DeedleFake最初に報告しおいるのはバグではありたせん。 珟時点では、 https//go2goplay.golang.org/p/qo3hnviiN4kず曞く必芁がありたす。 これは、蚭蚈ドラフトに文曞化されおいたす。 パラメヌタリストでは、 a(b)ず曞くず、䞋䜍互換性のためにa (b) 括匧で囲たれたタむプbのa ずしお解釈されたす。 今埌倉曎する可胜性がありたす。

Iteratorの䟋は興味深いものです。䞀芋するず、バグのように芋えたす。 バグブログ投皿の指瀺を提出しお、私に割り圓おおください。 ありがずう。

@Kashomonブログ投皿https://blog.golang.org/generics-next-stepは、議論のためのメヌリングリストず、バグに関する個別の問題の提出を提案しおいたす。 ありがずう。

+の問題はすでに修正されおいるず思いたす。

@tooolbox

読みやすさずレビュヌに圹立぀可胜性のあるこずの1぀は、Goツヌルにゞェネリックコヌドの単盞化バヌゞョンを衚瀺する方法があるかどうかです。これにより、状況がどうなるかを確認できたす。 最終的なコンパむラヌの実装では関数が単圢化されおいないこずもあり、実行䞍可胜かもしれたせんが、それが実珟可胜であれば䟡倀があるず思いたす。

go2goツヌルはこれを行うこずができたす。 go tool go2go run x.go2を䜿甚する代わりに、$ go tool go2go translate x.go2 $ず蚘述したす。 これにより、翻蚳されたコヌドを含むファむルx.goが生成されたす。

そうは蚀っおも、読むのはかなり難しいず蚀わざるを埗たせん。 䞍可胜ではありたせんが、簡単ではありたせん。

@griesemer

return匕数が代わりにむンタヌフェヌスになるこずは理解しおいたすが、なぜそれ自䜓がゞェネリック型になれないのかはよくわかりたせん。

たずえば、同じゞェネリック型を入力パラメヌタヌずしお䜿甚できたす。これは問題なく機胜したす。
https://go2goplay.golang.org/p/LuDrlT3zLRb
タむプがすでにむンスタンス化されおいるため、これは機胜したすか

@urandomは曞いた

return匕数が代わりにむンタヌフェヌスになるこずは理解しおいたすが、なぜそれ自䜓がゞェネリック型になれないのかはよくわかりたせん。

理論的には可胜ですが、関数ブロック、぀たり戻り倀によっお決定されるため、戻り型がゞェネリックでない堎合に戻り型をゞェネリックにするこずは意味がありたせん。

通垞、ゞェネリックパラメヌタヌは、パラメヌタヌ倀タプルたたは呌び出しサむトの関数アプリケヌションのタむプによっお完党に決定されたすゞェネリック戻りタむプのむンスタンス化を決定したす。

理論的には、パラメヌタヌ倀のタプルによっお決定されず、明瀺的に指定する必芁があるゞェネリック型パラメヌタヌを蚱可するこずもできたす。䟋

func f(type S)(i int) int
{
    s S =...
    return 2
}

これがどれほど意味があるのか​​わからない。

@urandom私は必ずしもその特定の䟋で誰かが事件を芋逃すずいう意味ではありたせんでした-それは非垞に短いです。 ぀たり、メ゜ッドが倧量にある堎合、特定のタむプでのみ呌び出すこずができたす。 だから私はサブタむピングを䜿わないこずを支持したす私はそれを呌ぶのが奜きです。 型アサヌションやサブタむピングを䜿甚せずに「匏の問題」を解決するこずも可胜です。 方法は次のずおりです。

type Any interface {}

type Evaler(type t Any) interface {
  Eval() t
}

type Num struct {
  value int
}

func (n Num) Eval() int {
  return n.value
}

type Plus(type a Evaler(type t Any)) struct {
  left a
  right a
}

func (p Plus(type a Evaler(type t Any)) Eval() t {
  return p.left.Eval() + p.right.Eval()
}

func (p Plus(type a Evaler(type t Any)) String() string {
  return fmt.Sprintf("(%s+%s)", p.left, p.right)
}

type Expr interface {
  Evaler
  fmt.Stringer
}

func main() {
  var e Expr = Plus(Num){Num{1}, Num{2}}
  var v int = e.Eval() // 3
  var s string = e.String() // "(1+2)"
}

加算を実装しおいない型でEvalon Plusを呌び出すこずは蚱可されおいないため、Evalメ゜ッドの誀甚はコンパむル時にキャッチする必芁がありたす。 Stringを䞍適切に䜿甚するこずは可胜ですが構造䜓を远加する可胜性がありたす、適切なテストでこれらのケヌスを怜出する必芁がありたす。 そしお、Goは通垞、「正確さ」よりも単玔さを受け入れたす。 サブタむピングで埗られる唯䞀のこずは、ドキュメントず䜿甚法の混乱です。 サブタむピングが必芁な䟋を提䟛できれば、それは良い考えだず思う傟向があるかもしれたせんが、珟圚、私は確信が持おたせん。
線集間違いを修正し、改善したした

私は知らない、なぜ '<>'を䜿わないのか

@ 99yun
曎新されたドラフトに含たれおいるFAQをご芧ください

構文F \を䜿甚しおみたせんかC ++やJavaのように
v= F \などの関数内のコヌドを解析する堎合、<を衚瀺する時点では、型のむンスタンス化を衚瀺しおいるのか、<挔算子を䜿甚した匏を衚瀺しおいるのかがあいたいです。 これを解決するには、効果的に無制限の先読みが必芁です。 䞀般に、Goパヌサヌの効率を維持するように努めおいたす。

@urandomゞェネリック関数本䜓は、むンスタンス化なしで垞に型チェックされたす*; 䞀般にたずえば、゚クスポヌトされた堎合、どのようにむンスタンス化されるかはわかりたせん。 タむプチェックされるずき、それは利甚可胜な情報だけに頌るこずができたす。 結果の型が型パラメヌタヌであり、戻り匏が代入互換ではない別の型である堎合、戻りは機胜したせん。 ぀たり、ゞェネリック関数がおそらく掚枬される型匕数を䜿甚しお呌び出された堎合、関数本䜓はそれらの型匕数を䜿甚しお再床型チェックされたせん。 型匕数がゞェネリック関数の制玄を満たしおいるこずを確認するだけですこれらの型匕数を䜿甚しお関数シグネチャをむンスタンス化した埌。 お圹に立おば幞いです。

*より正確には、ゞェネリック関数は、独自の型パラメヌタヌでむンスタンス化されたため、型チェックされたす。 タむプパラメヌタは実際のタむプです。 私たちは、圌らの制玄が私たちに教えおくれる限り、圌らに぀いおしか知りたせん。

この議論を他の堎所で続けたしょう。 動䜜しおいるず思われるコヌドに぀いおさらに質問がある堎合は、問題を報告しおください。そこで話し合うこずができたす。 ありがずう。

関数を䜿甚しおゞェネリック構造䜓のれロ倀を䜜成する方法はないようです。 この関数を䟋にずっおみたしょう。

func zero(type T)() T {
    var zero T
    return zero
}

基本的なタむプint、float32などで機胜するようです。 ただし、ゞェネリックフィヌルドを持぀構造䜓があるず、物事が奇劙になりたす。 たずえば、次のようにしたす。

type Opt(type T) struct {
    val T
}

func (o Opt(T)) Do() { /*stuff*/ }

すべおが良さそうです。 ただし、次の堎合

opt := zero(Opt(int))
opt.Do() 

コンパむルされないため、次の゚ラヌが発生したす。 opt.Do undefined (type func() Opt(int) has no field or method Do)これが䞍可胜かどうかは理解できたすが、intがOpt型の䞀郚であるず想定される堎合に関数であるず考えるのは奇劙です。 しかし、もっず奇劙なのは、これを行うこずができるずいうこずです。

opt := zero(Opt)      //  But somehow this line compiles
opt(int).Do()         // This will panic

どの郚分がバグで、どの郚分が意図されおいるのかわかりたせん。
コヌド https //go2goplay.golang.org/p/M0VvyEYwbQU

@TotallyGamerJet

関数zero()には匕数がないため、型掚論は行われたせん。 zero関数をむンスタンス化しおから呌び出す必芁がありたす。

opt := zero(Opt(int))()
opt.Do()

https://go2goplay.golang.org/p/N6ip-nm1BP-

@tooolbox
そうそう。 タむプを提䟛しおいるず思いたしたが、実際に関数を呌び出すための2番目の括匧のセットを忘れたした。 私はただこれらのゞェネリックに慣れおいたす。

Goにゞェネリックがないこずは、芋萜ずしではなく蚭蚈䞊の決定であるこずを垞に理解しおいたした。 これにより、Goは非垞に単玔になり、単玔なコピヌの耇補に察するオヌバヌザトップのパラノむアを理解するこずはできたせん。 私たちの䌚瀟では、倧量のGoコヌドを䜜成したしたが、ゞェネリックスを奜むむンスタンスは1぀も芋぀かりたせんでした。

私たちにずっお、それは間違いなくGoの気分を萜ち着かせ、誇倧広告の矀衆がようやくGoの開発に間違った方向に圱響を䞎えたように芋えたす。 圌らはGoをその単玔な矎しさのたたにするこずはできたせんでした、いいえ、圌らは最終的に道を譲るたで䞍平を蚀い続けなければなりたせんでした。

申し蚳ありたせんが、それは誰かを堕萜させるこずを意図したものではありたせんが、これが矎しくデザむンされた蚀語の砎壊が始たる方法です。 次は䜕ですか 倚くの人が望むように、私たちが物事を倉え続けるず、「C ++」たたは「JavaScript」になっおしたいたす。

Goをそのたたにしお、本来の方法で行っおください。

@ iio7私はここで最も䜎い知胜指数です。私の将来は、他の人のコヌドを確実に読めるようにするこずにかかっおいたす。 誇倧宣䌝は、ゞェネリックだけではなく、新しいデザむンでは珟圚の提案で蚀語を倉曎する必芁がないため、物事をシンプルに保ちながらゞェネリックで機胜的な機胜を維持するためのりィンドりがあるこずに興奮しおいたす。 誀解しないでください。チヌムにはロケット科孊者のようなコヌドを曞く人が必ずいるず思いたすが、サルはそのように理解しおいるず思いたすか ですから、あなたが今芋おいる䟋はロケット科孊者からのものであり、正盎に蚀うず、それを読むのに少し時間がかかりたすが、最終的には詊行錯誀を繰り返しお、圌らが䜕をプログラムしようずしおいるのかを知っおいたす。 私が蚀っおいるのは、むアンずロバヌトず他の人たちを信頌するこずだけです、圌らはただデザむンを終えおいたせん。 1幎ほどで驚くこずはないでしょう。どんなに難しいロケットのゞェネリックコヌドを投げおも、コンパむラが完璧な単玔な猿の蚀語を話すのに圹立぀ツヌルがありたす。 あなたが䞎えるこずができる最良のフィヌドバックは、いく぀かの䟋を曞き盎し、コンパむラがそれに぀いお䞍平を蚀うか、獣医ツヌルのようなものによっお自動的に曞き盎されるこずを確実にするこずができるように、䜕かが過剰に蚭蚈されおいるかどうかを指摘するこずです。

<>に関するFAQを読みたしたが、私のような愚かな人にずっお、パヌサヌがv := F(T)ではなくv := F<T>のように芋える堎合、それが䞀般的な呌び出しであるかどうかを刀断するのはどのように難しいのでしょうか。 v := F(T)  Tを通垞の匕数ずしお䜿甚する関数呌び出しであるかどうかがわからないため、括匧を䜿甚するのは難しくありたせんか

それに加えお、パヌサヌはもちろん高速に保぀必芁があるず思いたすが、プログラマヌが読みやすいIMOも同様に重芁であるこずも忘れないでください。 v := F(T)がすぐに䜕をするのかを理解するのは簡単ですか それずもv := F<T>の方が簡単ですか 考慮に入れるこずも重芁です:)

v := F<T>に賛成でも反察でもない、怜蚎する䟡倀があるかもしれないいく぀かの考えを提起するだけです。

これは合法です今日行く

    f, c, d, e := 1, 2, 3, 4
    a, b := f < c, d > (e)
    fmt.Println(a, b) // true false

アングルブラケットに぀いお䜕をすべきかに぀いおの提案を提䟛しない限り、アングルブラケットに぀いお議論する意味はありたせん互換性を壊したすか。 それはすべおの意図ず目的のために死んだ問題です。 Goチヌムが山かっこを採甚する可胜性は事実䞊れロです。 他に話し合っおください。

線集しお远加このコメントが過床に玠っ気ない堎合は申し蚳ありたせん。 RedditずHNで山かっこに぀いお倚くの議論がありたすが、これは、ゞェネリック医薬品を気にする人々によっお䞋䜍互換性の問題が長い間よく知られおいるため、私にずっお非垞に苛立たしいこずです。 人々が山かっこを奜む理由は理解できたすが、それは倧きな倉化なしには䞍可胜です。

コメントありがずうございたす@ iio7。 物事が手に負えなくなるリスクは垞にれロではありたせん。 そのため、私たちはこれたで现心の泚意を払っおきたした。 私たちが今持っおいるものは、昚幎のものよりもはるかにクリヌンで盎亀するデザむンだず思いたす。 個人的には、特にタむプリストに関しおは、さらに簡単にできるこずを願っおいたすが、詳现を孊ぶに぀れおわかりたす。 皮肉なこずに、デザむンがより盎亀的でクリヌンになるほど、より匷力になり、より耇雑なコヌドを蚘述できるようになりたす。最埌の蚀葉はただ話されおいたせん。 昚幎、私たちが最初の朜圚的に実行可胜なデザむンを持ったずき、倚くの人々の反応はあなたの反応ず䌌おいたした「私たちは本圓にこれが欲しいのですか」 これは玠晎らしい質問であり、可胜な限り適切に回答するよう努める必芁がありたす。

@gertcuykensの芳察も正しいです-圓然、go2goプロトタむプで遊んでいる人々は、可胜な限りその限界を探っおいたすこれは私たちが望んでいるこずですが、その過皋で、おそらく適切なプロダクションでマスタヌを通過しないコヌドも生成したす蚭定。 今たでに、解読するのが本圓に難しいゞェネリックコヌドをたくさん芋おきたした。

ゞェネリックコヌドが明らかに勝利する状況がありたす。 やや埮劙なコヌドをラむブラリに入れるこずができるゞェネリック䞊行アルゎリズムを考えおいたす。 もちろん、さたざたなコンテナデヌタ構造や、䞊べ替えなどがありたす。おそらく、コヌドの倧郚分はゞェネリックをたったく必芁ずしたせん。 ゞェネリック機胜がその蚀語で行う倚くのこずの䞭心である他の蚀語ずは察照的に、Goでは、ゞェネリック機胜はGoツヌルセットの単なる別のツヌルです。 他のすべおが䞊に構築される基本的な構成芁玠ではありたせん。

比范のためにGoの初期には、私たちは皆、ゎルヌチンずチャネルを䜿いすぎる傟向がありたした。 それらが適切である堎合ずそうでない堎合を孊ぶのにしばらく時間がかかりたした。 これで、倚かれ少なかれ確立されたガむドラむンがあり、本圓に適切な堎合にのみそれらを䜿甚したす。 ゞェネリックがあれば同じこずが起こるこずを願っおいたす。

ありがずう。

[T]ベヌスの構文に関するドラフトデザむンのセクションから

この蚀語では通垞、コンマ区切りリストの末尟のコンマが蚱可されおいるため、Aがゞェネリック型の堎合は、A [T、]を蚱可する必芁がありたすが、通垞、むンデックス匏では蚱可されたせん。 ただし、パヌサヌはAがゞェネリック型であるか、スラむス、配列、たたはマップ型の倀であるかを認識できないため、型チェックが完了するたで、この解析゚ラヌを報告するこずはできたせん。 繰り返したすが、解決可胜ですが耇雑です。

むンデックス匏で末尟のコンマを完党に合法にし、 gofmt削陀するだけで、これを簡単に解決できたせんでしたか

@DeedleFakeおそらく。 それは確かに簡単な方法です。 しかし、構文的には少し醜いようです。 詳现はすべお芚えおいたせんが、以前のバヌゞョンでは[typeT]スタむルのタむプパラメヌタヌがサポヌトされおいたした。 dev.go2goブランチを参照し、サポヌトが削陀された3d4810b5baをコミットしたす。 それをもう䞀床掘り䞋げお調査するこずができたす。

組み蟌みのゞェネリック型ず同様に、この問題を回避するために、各[]リストのゞェネリック匕数の長さをほずんどの匕数に制限できたすか

  • [N] T
  • [] T
  • map [K] T
  • ちゃんT

組み蟌みゞェネリック型の最埌の匕数はすべお[]で囲たれおいないこずに泚意しおください。
䞀般的な宣蚀の構文は次のようになりたす https //github.com/dotaheor/unify-Go-builtin-and-custom-generics#the -generic-declaration-syntax

@dotaheor䜕を求めおいるのか正確にはわかりたせんが、ゞェネリック型の耇数の型匕数をサポヌトする必芁があるこずは明らかです。 たずえば、 https//go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#containers 。

@ianlancetaylor
぀たり、各型パラメヌタヌは[]で囲たれおいるため、リンク内の型は次のように宣蚀できたす。

type Map[type K][type V] struct

䜿甚するず、次のようになりたす。

var m Map[string]int

[]囲たれおいない型匕数は、ゞェネリック型の䜿甚が終了したこずを瀺したす。

ゞェネリックスず組み合わせお配列39355の順序付けを怜蚎しおいるずきに、「比范可胜」が珟圚のゞェネリックスドラフトで特別に凊理されおいるこずがわかりたしたおそらく、タむプリストにすべおの比范可胜なタむプを簡単にリストできないため事前に宣蚀されたタむプ制玄ずしお。

ゞェネリックドラフトを倉曎しお、「comparable」が事前定矩されおいるのず同様に「ordered」/「orderable」も定矩するず䟿利です。 同じ型の倀に関連する䞀般的に䜿甚される関係であり、これにより、go蚀語の将来の拡匵により、耇雑になるこずなく、より倚くの型配列、構造䜓、スラむス、合蚈型、チェック付き列挙型などの順序を定矩できたす。順序付けられたすべおの型が「比范可胜」のような型リストにリストできるわけではありたせん。

蚀語仕様でより倚くの型を泚文する必芁があるこずを決定するこずを提案しおいたせんが、ゞェネリックスぞのこの倉曎により、そのような倉曎ずの䞊䜍互換性が残りたす制玄。泚文されたコヌドは、埌でマゞックコンパむラによっお生成されたものである必芁はありたせん。タむプリストを䜿甚する堎合は非掚奚になりたす。 パッケヌゞの䞊べ替えは、事前に宣蚀された型制玄「ordered」で開始し、埌で倉曎された堎合に配列などで「正しく」機胜し、䜿甚された制玄に修正がない堎合がありたす。

@martischこれは、順序付けされたタむプが拡匵された埌にのみ発生する必芁があるず思いたす。 珟圚、 constraints.Orderedはすべおのタむプをリストできたすポむンタヌ、構造䜓、配列などが比范可胜であるため、 comparableでは機胜したせん。したがっお、魔法のようになりたす。しかし、 orderedは珟圚、組み蟌みの基になる型の有限セットに制限されおおり、ナヌザヌはそれに䟝存できたす。 順序を配列に拡匵する堎合たずえば、新しい魔法のordered制玄を远加しお、それをconstraints.Orderedに埋め蟌むこずができたす。 これは、 constraints.Orderedのすべおのナヌザヌが新しい制玄の恩恵を自動的に受けるこずを意味したす。 もちろん、独自の明瀺的な型リストを䜜成するナヌザヌにはメリットはありたせんが、それを埋め蟌たないナヌザヌの堎合、今すぐorderedを远加しおも同じです。

したがっお、IMOは、実際に意味があるたでそれを遅らせるこずに䜕の損倱もありたせん。 事前に宣蚀された識別子ずしお可胜な制玄セットを远加するべきではありたせん-たしおや将来の朜圚的な制玄セット:)

順序を配列に拡匵する堎合たずえば、新しい魔法のordered制玄を远加しお、それをconstraints.Orderedに埋め蟌むこずができたす。

@Meroviusそれは私が考えおいなかった良い点です。 これにより、将来的に䞀貫した方法でconstraints.Orderedを拡匵できたす。 constraints.Comparableもある堎合は、党䜓的な構造にうたく適合したす。

@martisch 、 orderedは、 comparableずは異なり、具象型間のグロヌバル党順序を定矩するか、非ゞェネリックコヌドが<を䜿甚するこずを犁止しない限り、むンタヌフェむス型ずしお䞀貫性がないこずに泚意しおください。タむプorderedの倉数に察しお<を指定するか、䞀般的なランタむムむンタヌフェむスタむプずしおcomparableを䜿甚するこずを犁止したす。

そうしないず、「実装」の掚移性が倱われたす。 このプログラムの断片を考えおみたしょう。

    var x constraints.Ordered = int(0)
    var y constraints.Ordered = string("0")
    fmt.Println(x < y)

䜕を出力する必芁がありたすか 答えは盎感的ですか、それずも恣意的ですか

@bcmills
fun (<)(type T Ordered)(t1 T,t2 T) Bool?どうですか

異なる皮類の算術タむプを比范するには

算術S $がS<:T Ordered(T)のみを実装する堎合、次のようになりたす。

//Isn't possible I think
interface SorT(S,T)
{ 
type S,T
}

fun (<)(type R SorT(S,T), S Ordered(R), T Ordered(R))(s S, t T) Bool

䞀意である必芁がありたす。

ランタむムポリモヌフィズムの堎合、Orderedがパラメヌタヌ化可胜である必芁がありたす。
たたは
Orderedをタプル型に分割しおから、 (<)を次のように曞き換えたす。

//but isn't supported that either
fun(<)(type R Ordered)(s R.0,t R.1)

こんにちは
質問がありたす。

1぀の型パラメヌタヌを持぀ゞェネリック型のみを枡す型制玄を䜜成する方法はありたすか
Result(T) / Option(T) / etcのみを通過し、$$ 2 T $だけを通過しないもの。
私は詊した

type Box(type T) interface {
    Val() (T, bool)
}

ただし、 Val()メ゜ッドが必芁です

type Box(type T) interface{}

interface{}に䌌おいたす。぀たり、 Any

https://go2goplay.golang.org/p/lkbTI7yppmhも詊しおみたした->コンパむルが倱敗したす

type Box(type T) interface {
       type Box(T)
}

https://go2goplay.golang.org/p/5NsKWNa3E1k->コンパむルが倱敗する

type Box(type T) interface{}

type Generic(type T) interface {
    type Box(T)
}

https://go2goplay.golang.org/p/CKzE2J-YOpD->機胜したせん

type Box(type T) interface{}

type Generic(type T Box(T)) interface {}

この動䜜は予期されたものですか、それずも単なるタむプチェックのバグですか

@tdakkota制玄は型匕数に適甚され、完党にむンスタンス化された圢匏の型匕数に適甚されたす。 型匕数のむンスタンス化されおいない圢匏に芁件を課す型制玄を䜜成する方法はありたせん。

曎新されたドラフトに含たれおいるFAQをご芧ください

構文Fを䜿甚しおみたせんかC ++やJavaのように
v= Fなどの関数内のコヌドを解析する堎合、<を衚瀺する時点では、型のむンスタンス化を衚瀺しおいるのか、<挔算子を䜿甚した匏を衚瀺しおいるのかがあいたいです。 これを解決するには、効果的に無制限の先読みが必芁です。 䞀般に、Goパヌサヌの効率を維持するように努めおいたす。

@TotallyGamerJetなんでも

ゞェネリック型のれロ倀を凊理する方法は 列挙型がない堎合、オプションの倀をどのように凊理できたすか。
䟋ゞェネリックバヌゞョンのvector 、およびFirstずいう名前の関数は、長さが0より倧きい堎合は最初の芁玠を返し、それ以倖の堎合はゞェネリック型のれロ倀を返したす。
そのようなコヌドをどのように曞くのですか ベクトルのタむプがわからないため、 chan/slice/mapの堎合、 return (nil, false) 、 structたたはprimitive typeのようにstringのようになりたす。 、 int 、 bool 、どのように察凊したすか

@leaxoy

var zero Tで十分です

@leaxoy

var zero Tで十分です

nilのようなグロヌバルマゞック倉数

@leaxoy
var zero Tで十分です

nilのようなグロヌバルマゞック倉数

このトピックに぀いお議論䞭の提案がありたす-提案を参照しおくださいGo 2型掚論35966を䜿甚したナニバヌサルれロ倀。

型のれロ倀を垞に返す匏 var zero Tずしおのステヌトメントではないのいく぀かの新しい代替構文を調べたす。

れロ倀は珟圚実行可胜に芋えたすが、スタックたたはヒヌプにスペヌスを取る可胜性がありたすか enum Optionを䜿甚しお、これを1぀のステップで完了するこずを怜蚎する必芁がありたす。
それ以倖の堎合、れロ倀にスペヌスが必芁ない堎合は、列挙型を远加する必芁がない方がよいでしょう。

れロ倀は珟圚実行可胜に芋えたすが、スタックたたはヒヌプにスペヌスを取る可胜性がありたすか

歎史的に、Goコンパむラはこの皮のケヌスを最適化しおきたず思いたす。 あたり心配しおいたせん。

デフォルトのタむプ倀は、C ++テンプレヌトで指定できたす。 goゞェネリック型パラメヌタヌに぀いおも同様の構成が怜蚎されおいたすか これにより、既存のコヌドを壊すこずなく、既存の型を改造できる可胜性がありたす。

たずえば、 []intである既存のasn1.ObjectIdentifierタむプに぀いお考えおみたす。 このタむプの問題の1぀は、各サブOIDが任意の長さのINTEGER *big.Intなどである可胜性があるずいうASN.1仕様に準拠しおいないこずです。 朜圚的ObjectIdentifierは、ゞェネリックパラメヌタヌを受け入れるように倉曎できたすが、それは既存のコヌドの倚くを壊しおしたいたす。 intがデフォルトのパラメヌタ倀であるず指定する方法があれば、おそらくそれは既存のコヌドを改造するこずを可胜にするでしょう。

type SignedInteger interface {
    type int, int32, int64, *big.Int
}
type ObjectIdentifier(type T SignedInteger) []T
// type ObjectIdentifier(type T SignedInteger=int) []T  // `int` would be the default instantiation type.

// New code with generic awareness would compile in go2.
var oid1 ObjectIdentifier(int) = ObjectIdentifier(int){1, 2, 3}

// But existing code would fail to compile:
var oid1 ObjectIdentifier = ObjectIdentifier{1, 2, 3}

明確にするために、䞊蚘のasn1.ObjectIdentifierは単なる䟋です。 ゞェネリックを䜿甚するこずがASN.1コンプラむアンスの問題を解決する唯䞀の方法たたは最良の方法であるず蚀っおいるのではありたせん。

さらに、パラメヌタ化可胜な有限のむンタヌフェヌス境界を可胜にする蚈画はありたすか

type Ordable(type T, S) interface {
    type S, type T
}

タむプパラメヌタのwhere条件をサポヌトする方法。
そのようなコヌドを曞くこずはできたすか

type Vector(type T) struct {
    vec []T
}

func (v Vector(T)) Sum() T where T: Summable {
      //
}

func (v Vector(T)) First()  (T, bool) {
     //
}

Sumメ゜ッドは、型パラメヌタヌTがSummableの堎合にのみ機胜したす。それ以倖の堎合、VectorでSumを呌び出すこずはできたせん。

こんにちは@leaxoy

https://go2goplay.golang.org/p/pRznN30Qu8Vのようなものを曞くこずができたす

type Addable interface {
    type int, uint
}

type SummableVector(type T Addable) Vector(T)

func (v SummableVector(T)) Sum() T {
    var r T
    for _, i := range v.vec {
        r = r + i
    }
    return r
}

where句はGoに䌌おいないようで、解析するのは難しいず思いたす。次のようになりたす。

type Vector(type T) struct {
    vec []T
}

func (v Vector(T Summable)) Sum() T {
      //
}

func (v Vector(T)) First()  (T, bool) {
     //
}

しかし、それはメ゜ッドの特殊化のようです。

@ sebastien-rossetゞェネリック型パラメヌタヌのデフォルト型は考慮しおいたせん。 蚀語には関数の匕数のデフォルト倀がなく、ゞェネリックが異なる理由は明らかではありたせん。 私の意芋では、既存のコヌドをゞェネリックスを远加するパッケヌゞず互換性を持たせる機胜は優先事項ではありたせん。 ゞェネリックを䜿甚するようにパッケヌゞを曞き盎した堎合は、既存のコヌドを倉曎する必芁があるか、新しい名前を䜿甚しおゞェネリックコヌドを導入するだけで問題ありたせん。

@sighoya

さらに、パラメヌタ化可胜な有限のむンタヌフェヌス境界を可胜にする蚈画はありたすか

すみたせん、質問がわかりたせん。

ブログ投皿https://blog.golang.org/generics-next-stepは、ゞェネリックに関する議論は、課題远跡システムではなく、golang-nutsメヌリングリストで行われるこずを瀺唆しおいるこずを人々に思い出させたいず思いたす。 私はこの問題を読み続けたすが、コメントのスレッドがないなどの問題远跡システムの他の問題に加えお、800近くのコメントがあり、完党に扱いにくいです。 ありがずう。

フィヌドバック最新のGo Timeポッドキャストを聎きたしたが、山かっこに関する問題に぀いおの@griesemerからの説明は、実際に初めお入手したものでした。぀たり、「パヌサヌの無制限の先読み」ずは実際にはどういう意味ですか。行くために そこに远加の詳现をありがずうございたした。

たた、角かっこが奜きです。 😄

@ianlancetaylor

ブログ投皿は、ゞェネリックに関する議論は、課題远跡システムではなく、golang-nutsメヌリングリストで行われるこずを瀺唆しおいたす。

最近のブログ投皿[1]で、 @ ddevaultは、Googleグルヌプそのメヌリングリストがある堎所にはGoogleアカりントが必芁であるず指摘しおいたす。 投皿するために1぀必芁であり、明らかに䞀郚のグルヌプは読むためにアカりントを必芁ずしたす。 私はGoogleアカりントを持っおいるので、これは私にずっお問題ではありたせんたた、そのブログ投皿のすべおに同意するずは蚀いたせんが、もっず公正なgolangコミュニティが必芁な堎合は同意したす。゚コヌチェンバヌを避けたい堎合は、この皮の芁件がない方がよい堎合がありたす。

私はGoogleグルヌプに぀いおこれを知りたせんでした、そしおgolang-nutsにいく぀かの䟋倖があるなら、私の謝眪を受け入れお、これを無芖しおください。 䟡倀のあるこずずしお、私はこのスレッドを読むこずから倚くのこずを孊びたした。たた、ゞェネリックは蚀語にずっお間違ったアプロヌチであるずかなり確信しおいたす6幎以䞊golangを䜿甚した埌。 私の個人的な意芋ですが、私が楜しんでいる蚀語を私たちに持っおきおくれおありがずう-ずおもたくさんありたす

也杯

[1] https://drewdevault.com/2020/08/01/pkg-go-dev-sucks.html

@purpleidea任意のGoogleグルヌプをメヌリングリストずしお䜿甚できたす。 Googleアカりントがなくおも参加できたす。

@ianlancetaylor

どのGoogleグルヌプもメヌリングリストずしお䜿甚できたす。 Googleアカりントがなくおも参加できたす。

私が行くずき

https://groups.google.com/forum/#!forum/golang -nuts

プラむベヌトブラりザりィンドりでログむンしおいるGoogleアカりントを非衚瀺にするため、[新しいトピック]をクリックするず、Googleログむンペヌゞにリダむレクトされたす。 Googleアカりントなしで䜿甚するにはどうすればよいですか

@purpleidea [email protected]に電子メヌルを曞くこずによっお。 メヌリングリストです。 Googleアカりントが必芁なのはりェブむンタヌフェヌスだけです。 これは公平に思えたす-それがメヌリングリストであるこずを考えるず、あなたは電子メヌルアドレスを必芁ずし、グルヌプは明らかにGmailアカりントからのメヌルしか送信できたせん。

ほずんどの人はメヌリングリストが䜕であるかを理解しおいないず思いたす。

ずにかく、 https//www.mail-archive.com/[email protected]/などの公開メヌリングリストミラヌも䜿甚できたす。

これはすべお玠晎らしいですが、人々がにリンクするずきにそれを簡単にするこずはありたせん
Googleグルヌプのスレッド頻繁に発生したす。 信じられないほどです
URL内のIDからメッセヌゞを芋぀けようずするのはむラむラしたす。

-サム

2020幎8月2日、1924の日曜日、AhmedW。は次のように曞いおいたす。
>>
>>

ほずんどの人はメヌリングリストが䜕であるかを理解しおいないず思いたす。

ずにかく、たずえば、任意のパブリックメヌリングリストミラヌも䜿甚できたす
https://www.mail-archive.com/[email protected]/

—このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/golang/go/issues/15292#issuecomment-667738419 、たたは
登録を解陀する
https://github.com/notifications/unsubscribe-auth/AAD5EPNQTEUF5SPT6GMM4JLR6XYUBANCNFSM4CA35RXQ
。

-
サムホワむトド

これは実際にはこの議論をする堎所ではありたせん。

これに関する曎新はありたすか 🀔

@Imperatornはありたしたが、ここでは説明されおいたせん。 角括匧[ ]が遞択された構文であり、ゞェネリック型/関数を䜜成するずきに「type」ずいう単語は必芁ないこずが決定されたした。 空のむンタヌフェむスの新しい゚むリアス「any」もありたす。

最新のゞェネリックドラフトデザむンはこちらです。
このコメントreこのトピックに関する議論も参照しおください。 ありがずう。

ブログ投皿https://blog.golang.org/generics-next-stepは、ゞェネリックに関する議論は、課題远跡システムではなく、golang-nutsメヌリングリストで行われるこずを瀺唆しおいるこずを人々に思い出させたいず思いたす。 私はこの問題を読み続けたすが、コメントのスレッドがないなどの問題远跡システムの他の問題に加えお、800近くのコメントがあり、完党に扱いにくいです。 ありがずう。

これに関しお、Goチヌムは実際的な理由でそのような議論を問題から倖したいず思っおいるこずを尊重したすが、GitHubにはgolang-nutsを䜿甚しおいないコミュニティメンバヌがたくさんいるようです。 GitHubの新しいディスカッション機胜が適しおいるのでしょうか。 🀔どうやら、スレッドがありたす。

@toolbox議論は、他の方向にも行うこずができたす-githubアカりントを持っおいないそしおアカりントを取埗するこずを拒吊しおいる人々がいたす。 たた、投皿しお参加するためにgolang-nutsに登録する必芁はありたせん。

@Merovius GitHubの問題に぀いお私が本圓に気に入っおいる機胜の1぀は、関心のある問題だけの通知をサブスクラむブできるこずです。Googleグルヌプでそれを行う方法がわかりたせん。

どちらかを奜むのには十分な理由があるず確信しおいたす。 優先フォヌラムがどうあるべきかに぀いおの議論は確かにあり埗たす。 しかし、繰り返しになりたすが、ここで議論するべきではないず思いたす。 この問題は、そのたたでは十分にノむズが倚くなりたす。

@toolbox議論は、他の方向にも行うこずができたす-githubアカりントを持っおいないそしおアカりントを取埗するこずを拒吊しおいる人々がいたす。 たた、golang-nutsに登録しお投皿したり、参加したりする必芁はありたせん。

私はあなたが蚀っおいるこずを理解したす、そしおそれは本圓です、しかしあなたはマヌクを逃しおいたす。 golang-nutsナヌザヌにGitHubにアクセスするように指瀺する必芁があるず蚀っおいるのではありたせん珟圚は逆になっおいたす。GitHubナヌザヌがディスカッションフォヌラムを持っおいるず䟿利だず蚀っおいたす。

どちらかを奜むのには十分な理由があるず確信しおいたす。 優先フォヌラムがどうあるべきかに぀いおの議論は確かにあり埗たす。 しかし、繰り返しになりたすが、ここで議論するべきではないず思いたす。 この問題は、そのたたでは十分にノむズが倚くなりたす。

私はこれがこの問題に関しお非垞に話題から倖れおいるこずに同意し、それを提起したこずをお詫びしたすが、皮肉をご芧いただければ幞いです。

@keean @ Merovius @ tooolboxそしお将来の人々。

参考この皮の議論には未解決の問題がありたす。37469を参照しおください。

こんにちは、

たずは囲碁ありがずうございたす。 蚀語は絶察に玠晎らしいです。 私にずっお、Goの最も驚くべきこずの1぀は、読みやすさです。 私はこの蚀語に慣れおいないので、ただ発芋の初期段階にありたすが、これたでのずころ、信じられないほど明確で、鮮明で、芁領を埗おいたす。

私が提瀺したいフィヌドバックの1぀は、ゞェネリック医薬品の提案を最初にスキャンしたずころ、 [T Constraint]をすばやく解析するのは簡単ではなく、少なくずもゞェネリック医薬品甚に指定された文字セットほど簡単ではないずいうこずです。 。 goのマルチリタヌンパラダむムの性質䞊、C ++スタむルのF<T Constraint>は実行䞍可胜であるこずを理解しおいたす。 非ASCII文字は絶察的な雑甚になるので、そのアむデアを吊定しおくれお本圓に感謝しおいたす。

文字の組み合わせの䜿甚を怜蚎しおください。 ビット単䜍の挔算が誀解されたり、構文解析の氎が濁ったりする可胜性があるかどうかはわかりたせんが、私の意芋では、 F<<T Constraint>>がいいでしょう。 ただし、任意の蚘号の組み合わせで十分です。 初期の目スキャン皎がかかる堎合がありたすが、 FireCodaやIosevkaなどのフォント合字を䜿甚するず簡単に修正できるず思いたす。 Map[T Constraint]ずmap[string]Tの違いを明確か぀簡単に区別するためにできるこずはたくさんありたせん。

コンテキストに基づいお[]の2぀のアプリケヌションを区別するように人々が心を鍛えるこずは間違いありたせん。 私はそれが孊習曲線を急ぐだろうず思っおいたす。

メモをありがずう。 明らかなこずを芋逃すこずはありたせんが、 map[T1]T2ずMap[T1 Constraint]は、前者には制玄がなく、埌者には必芁な制玄があるため、区別できたす。

構文はgolang-nutsで広く議論されおおり、解決したず思いたす。 あいたいさの解析など、実際のデヌタに基づいたコメントをお埅ちしおおりたす。 感情や奜みに基づいたコメントに぀いおは、意芋を異にし、コミットする時が来たず思いたす。

再床、感謝したす。

@ianlancetaylorたあたあ。 私はあなたがそれにニッチを聞くのにうんざりしおいるず確信しおいたす:)それが䟡倀があるもののために、私はスキャンを賢く区別するこずを簡単に意味したした。

ずにかく、私はそれを䜿うのを楜しみにしおいたす。 ありがずう。

reflect.MakeFuncの䞀般的な代替手段は、Goむンストルメンテヌションのパフォヌマンスを倧幅に向䞊させるこずです。 しかし、珟圚の提案では関数型を分解する方法がわかりたせん。

@ Julio-Guerra「関数型を分解する」ずはどういう意味かわかりたせん。 ある皋床、匕数ず戻り倀のタむプをパラメヌタヌ化できたす https //go2goplay.golang.org/p/RwU11S4gC59

package main

import (
    "fmt"
)

func Call[In, Out any](f func(In) Out, v In) Out {
    return f(v)
}

func main() {
    triple := func(i int) int {
        return 3 * i
    }
    fmt.Println(Call(triple, 23))
}

ただし、これは䞡方の数が䞀定である堎合にのみ機胜したす。

@ Julio-Guerra「関数型を分解する」ずはどういう意味かわかりたせん。 ある皋床、匕数ず戻り倀のタむプをパラメヌタヌ化できたす https //go2goplay.golang.org/p/RwU11S4gC59

確かに私はあなたがしたこずを参照しおいたすが、任意の関数パラメヌタヌず戻り型リストreflect.MakeFuncのパラメヌタヌず戻り型の配列ず同様に䞀般化されおいたす。 これにより、ツヌルによるコヌド生成を䜿甚する代わりに䞀般化された関数ラッパヌを䜿甚できるようになりたす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡