序文:それif else
が進むべき道であると主張することなく、言語対応の構成要素をいじって楽しみを見つけることができます。
次のIf
構成はgithub.com/icza/gox
、builtinx.If
タイプである他の多くのメソッドとともに私のライブラリで利用できます。
Goを使用すると、などのプリミティブ型を含む、任意のユーザー定義型にメソッドをアタッチできますbool
。基になる型bool
として持つカスタム型を作成し、条件に対する単純な型変換を使用して、そのメソッドにアクセスできます。オペランドを受け取って選択するメソッド。
このようなもの:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
どうすれば使用できますか?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
たとえば、三進法を行うmax()
:
i := If(a > b).Int(a, b)
三元的なことabs()
:
i := If(a >= 0).Int(a, -a)
これはクールに見え、シンプルでエレガント、そして効率的です(インライン化にも適しています)。
「実際の」三項演算子と比較した1つの欠点:常にすべてのオペランドを評価します。
延期された場合にのみ必要な評価を実現するための唯一のオプションは、関数(宣言された関数またはメソッド、または関数リテラル)を使用することです。
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
それを使用する:レッツは、私たちが計算するには、これらの機能を持っていると仮定a
してb
:
func calca() int { return 3 }
func calcb() int { return 4 }
次に:
i := If(someCondition).Fint(calca, calcb)
たとえば、条件が現在の年> 2020である場合:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
関数リテラルを使用したい場合:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
最後の注意:異なるシグネチャを持つ関数がある場合、ここではそれらを使用できません。その場合、シグネチャが一致する関数リテラルを使用して、それらを引き続き適用できます。
たとえばcalca()
とcalcb()
(戻り値以外に)あまりにものパラメータを持っているでしょう。
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
これはあなたがそれらを使うことができる方法です:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Go Playgroundでこれらの例を試してください。