From c9188d7760fb68a60e6791f0adf42f8dc1728251 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 11 Dec 2024 10:55:33 -0800 Subject: [PATCH] types/bools: add IfElse (#14272) The IfElse function is equivalent to the ternary (c ? a : b) operator in many other languages like C. Unfortunately, this function cannot perform short-circuit evaluation like in many other languages, but this is a restriction that's not much different than the pre-existing cmp.Or function. The argument against ternary operators in Go is that nested ternary operators become unreadable (e.g., (c1 ? (c2 ? a : b) : (c2 ? x : y))). But a single layer of ternary expressions can sometimes make code much more readable. Having the bools.IfElse function gives code authors the ability to decide whether use of this is more readable or not. Obviously, code authors will need to be judicious about their use of this helper function. Readability is more of an art than a science. Updates #cleanup Signed-off-by: Joe Tsai --- types/bools/bools.go | 28 +++++++++++++++++++ .../bools/{compare_test.go => bools_test.go} | 9 ++++++ types/bools/compare.go | 17 ----------- 3 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 types/bools/bools.go rename types/bools/{compare_test.go => bools_test.go} (70%) delete mode 100644 types/bools/compare.go diff --git a/types/bools/bools.go b/types/bools/bools.go new file mode 100644 index 000000000..962e39919 --- /dev/null +++ b/types/bools/bools.go @@ -0,0 +1,28 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// Package bools contains the [Compare] and [Select] functions. +package bools + +// Compare compares two boolean values as if false is ordered before true. +func Compare[T ~bool](x, y T) int { + switch { + case x == false && y == true: + return -1 + case x == true && y == false: + return +1 + default: + return 0 + } +} + +// IfElse is a ternary operator that returns trueVal if condExpr is true +// otherwise it returns falseVal. +// IfElse(c, a, b) is roughly equivalent to (c ? a : b) in languages like C. +func IfElse[T any](condExpr bool, trueVal T, falseVal T) T { + if condExpr { + return trueVal + } else { + return falseVal + } +} diff --git a/types/bools/compare_test.go b/types/bools/bools_test.go similarity index 70% rename from types/bools/compare_test.go rename to types/bools/bools_test.go index 280294621..1b466db17 100644 --- a/types/bools/compare_test.go +++ b/types/bools/bools_test.go @@ -19,3 +19,12 @@ func TestCompare(t *testing.T) { t.Errorf("Compare(true, true) = %v, want 0", got) } } + +func TestIfElse(t *testing.T) { + if got := IfElse(true, 0, 1); got != 0 { + t.Errorf("IfElse(true, 0, 1) = %v, want 0", got) + } + if got := IfElse(false, 0, 1); got != 1 { + t.Errorf("IfElse(false, 0, 1) = %v, want 1", got) + } +} diff --git a/types/bools/compare.go b/types/bools/compare.go deleted file mode 100644 index ac433b240..000000000 --- a/types/bools/compare.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -// Package bools contains the bools.Compare function. -package bools - -// Compare compares two boolean values as if false is ordered before true. -func Compare[T ~bool](x, y T) int { - switch { - case x == false && y == true: - return -1 - case x == true && y == false: - return +1 - default: - return 0 - } -}