Skip to content

proposal: Go 2: spec: conditional-assign (?=) for limited ternary operator functionality #31659

@ugorji

Description

@ugorji

Introduce a ?= operator, to support the limited use-case of a conditional assignment

var s ?= boolean_expr, ifTrueVal, ifFalseVal

For example:

var v, s string
// ...
 s ?= len(v) == 0, "blank", "not blank"

By using commas in the RHS, it limits this syntax to only be usable on explicit assignment to a declared variable and consequently limits the LHS to only have one declared variable.

Also, because go does not permit variable assignment to declare variables on the RHS, this CANNOT be abused.


This is not a ternary operator proposal, or contain the drawbacks of it.

I appreciate the resistance to do a ternary operator (see https://golang.org/doc/faq#Does_Go_have_a_ternary_form ), and I have also looked at some proposals and conversations to add it back in some form: (see https://golang.org/issue/20774 )

This is NOT such a proposal.

We all can clearly see the benefit of the ternary operator as seen in (scenario 1) where it translates:

var n T
if expr {
    n = trueVal
} else {
    n = falseVal
}

to a 1-liner

var n = expr ? trueVal : falseVal

The overriding drawback is that it permits the creation of incredibly complex nested expressions as seen in (scenario 2)

var b1, b2, b3 bool
var s = b1 || b2 ? b2 && b3 ? b1 && b3 : "s1" : "s2" : "s3": "s4" // impossible to read

VERSUS

var s string
if b1 || b2 {
    if b2 && b3 {
        if b1 && b3 {
            s = "s4"
        } else {
            s = "s3"
       }
    } else {
        s = "s2"
    }
} else {
    s = "s1"
}

Clearly, it's incredibly hard to understand the one-liner in scenario 2. Its longer version, while many lines, is clearly more readable. I have looked at the one-liner many times, and I don't even know if it is even correct, or if the syntax is correct. Clearly, the one-liner is unreadable, and it was great that it was disallowed in the language.


The main drawback occurs only when there is more than 1 boolean expression checked within the RHS. The way to limit it is to make the syntax be tied to the assignment operator, so it can only occur during explicit variable assignment.

We know the common use of ternary operators by pragmatic programmers is scenario 1. What if we can allow that use-case, and just that alone? It could dramatically reduce the number of lines of code. This is what this proposal should permit.


Thoughts? Please let us discuss ideas about how this could give us the middle ground we all crave i.e. pragmatically limit the use of ternary operator to the one-line, one expression cases that we all agree improves readability.

^^ cc'ing @agl @rsc @bradfitz @dominikh @robpike @ianlancetaylor


Alternative syntax from comments below that I really like:

@nigeltao #31659 (comment)

// boolean expressions and assignment values are simple statements which do not nest
var s string = b1 ? "s1" : b2 ? "s2" : b3 ? "s3" : "s4000"
// equivalent to
if b1 { s = "s1" } else if b2 { s = "s2" } else if b3 { s = "s3" } else { s = "s4000" }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions