Description
Consider a builtin called pick
that can pick from one of two given values of the same type, depending on a boolean expression:
// before
var v string
if expr {
v = "value1"
} else {
v = "value2"
}
// after
v := pick(expr, "value1", "value2")
Yes, it is yet another ternary operator proposal :-), but this time suggested as a builtin similar to append
or delete
.
The signature of pick would look like:
func pick(cond bool, lhs, rhs Type) Type
where Type
is any(?) type and the compiler would enforce that lhs
, rhs
and the return value are of the same type - similar to how the 2nd and later arguments of append
and the return value are of the same type.
Only one of the arguments would be evaluated depending on the result of the boolean expression, similar to an if-else statement.
As for evidence that this can simplify code, here are some examples, all taken from the single Go source code file fmt/format.go:
lines 76-80:
// before
// Decide which byte the padding should be filled with.
padByte := byte(' ')
if f.zero {
padByte = byte('0')
}
// after
padByte := byte(pick(f.zero, '0', ' '))
lines 124-132:
// before
func (f *fmt) fmtBoolean(v bool) {
if v {
f.padString("true")
} else {
f.padString("false")
}
}
// after
func (f *fmt) fmtBoolean(v bool) {
f.padString(pick(v, "true", "false"))
}
lines 370-374:
// before
length := len(b)
if b == nil {
// No byte slice present. Assume string s should be encoded.
length = len(s)
}
// after
length := pick(b == nil, len(s), len(b))
lines 419-423:
// before
if b != nil {
c = b[i] // Take a byte from the input byte slice.
} else {
c = s[i] // Take a byte from the input string.
}
// after
c = pick(b != nil, b[i], s[i])
lines 454-458, also lines 481-485:
// before
if f.plus {
f.pad(strconv.AppendQuoteToASCII(buf, s))
} else {
f.pad(strconv.AppendQuote(buf, s))
}
// after
f.pad(pick(f.plus, strconv.AppendQuoteToASCII(buf, s), strconv.AppendQuote(buf, s))
lines 464-467, also lines 476-479:
// before
r := rune(c)
if c > utf8.MaxRune {
r = utf8.RuneError
}
// after
r := pick(c > utf8.MaxRune, utf8.RuneError, rune(c))
lines 526-531:
// before
digits = prec
// If no precision is set explicitly use a precision of 6.
if digits == -1 {
digits = 6
}
// after
digits = pick(digits == -1, 6, prec)