<p>While single-item tuples aren't particularly useful, disallowing them entirely, or allowing them but with few to no valid representations in syntax, may also be undesirable. However, since tuples typically use parentheses, the default comma-separated syntax would make a tuple literal indistinguishable (without context) from an expression wrapped in parentheses for grouping purposes. E.g., is <code>(2 + 2)</code> the tuple <code>(4)</code>, or just <code>4</code>?</p>
<p>What are some approaches which could be used to address this ambiguity?</p>

<syntax><tuple><ambiguity><compiler-inference>
How can single-item tuples be disambiguated from the grouping operator?
<h1>Rust-style: Trailing comma</h1>
<p>Since Rust allows and even encourages trailing commas in arrays, structs, and so on, it also allows them in tuples, giving you a simple, unambiguous single-item tuple syntax: <code>(2 + 2,)</code>. This also works for types: <code>(Option&lt;String&gt;,)</code>.</p>

CC BY-SA 4.0
2023-06-23T12:56:10.217Z
2023-06-23T12:56:10.217Z
rydwolf
CC BY-SA 4.0
2023-06-23T13:05:59.057Z
Swift decided to allow trailing commas in arrays and dictionaries, but not tuples. Why they did that is beyond me.
Bbrk24
CC BY-SA 4.0
2023-06-23T13:10:03.340Z
This is Python style, too.
kaya3
CC BY-SA 4.0
2023-06-30T12:07:45.087Z
Note that Python tuples don't require parenthesis. `a = 1,` will assign a single-item tuple to the name `a`, and similarly `a, = ...` is a common way of destructuring a single-item tuple.
BoppreH
<h1>Compiler inference</h1>
<p>Another, more complex option would be compiler inference. In a statically and strongly typed language, and one where few operators can be used on a tuple, it may be relatively simple to see where a tuple is expected, and check each possible set of parentheses to see whether or not it would make sense to treat it as a tuple. E.g.:</p>
<pre><code>fn unwrap_me_once(x: (int)) -&gt; int {
    x.0
}

unwrap_me_once((2 + 2)); // This must be a tuple
unwrap_me_once(((2 + 2))); // Either interpretation could be valid, but both are the same
unwrap_me_once(((2 + 2) * 4)); // The inner parentheses can't be a tuple

fn shame_on_me(x: int) -&gt; int {
    x
}

shame_on_me((2 + 2).0); // This must be a tuple, since accessing an item of an int would be invalid
shame_on_me(((1 + 1) + (1 + 1))); // These must all be grouping, since + doesn't work on tuples, and the function expects an int instead of a single-item tuple
</code></pre>

CC BY-SA 4.0
2023-06-23T13:02:07.790Z
2023-06-23T13:02:07.790Z
rydwolf
<h1>Labels</h1>
<p>Some languages, such as Swift and C#, let you label the items in tuple types:</p>
<pre class="lang-swift prettyprint-override"><code>var t: (high: Int, low: UInt) = largeInteger.multipliedFullWidth(by: anotherLargeInteger)
</code></pre>
<p>These particular languages also have <code>_</code> for an &quot;ignore me&quot; identifier:</p>
<pre class="lang-swift prettyprint-override"><code>let ignoresSecondArgument: (Int, Int) -&gt; Int = { i, _ in i }
_ = ignoreTheReturnValue()
let yesThisIsLegal: (_: Int, _: Double) = (1, 2.0)
let soIsThis: (Int, Double) = (_: 3, _: 4.0)
</code></pre>
<p>So, you could require that single-element tuples have item labels, and then unlabelled single-element tuples use <code>_</code>:</p>
<pre class="lang-swift prettyprint-override"><code>let singleElementTuple = (_: 1)
let labelledSingleElementTuple = (x: 1)
</code></pre>
<p>Note: In Swift, labelled single-element tuples are illegal, and unlabelled single-element tuples are identical to the type that they wrap around. This means that, as strange as it looks, this is valid:</p>
<pre class="lang-swift prettyprint-override"><code>print((_: 2 + 3) / 5) // prints &quot;1&quot;
</code></pre>

CC BY-SA 4.0
2023-06-23T13:03:11.430Z
2023-06-23T13:03:11.430Z
Bbrk24
# How can single-item tuples be disambiguated from the grouping operator?
Posted by: username_0 on 2023-06-23
While single-item tuples aren't particularly useful, disallowing them entirely, or allowing them but with few to no valid representations in syntax, may also be undesirable. However, since tuples typically use parentheses, the default comma-separated syntax would make a tuple literal indistinguishable (without context) from an expression wrapped in parentheses for grouping purposes. E.g., is `(2 + 2)` the tuple `(4)`, or just `4`?

What are some approaches which could be used to address this ambiguity?
**Tags:** syntax tuple ambiguity compiler-inference
---
## 3 answers
### Answer by username_0 on 2023-06-23. Score: 7
# Rust-style: Trailing comma

Since Rust allows and even encourages trailing commas in arrays, structs, and so on, it also allows them in tuples, giving you a simple, unambiguous single-item tuple syntax: `(2 + 2,)`. This also works for types: `(Option,)`.
> **Comments:**
> **username_1** (2023-06-23): Swift decided to allow trailing commas in arrays and dictionaries, but not tuples. Why they did that is beyond me.  
> **username_2** (2023-06-23): This is Python style, too.  
> **username_3** (2023-06-30): Note that Python tuples don't require parenthesis. `a = 1,` will assign a single-item tuple to the name `a`, and similarly `a, = ...` is a common way of destructuring a single-item tuple.  
---
### Answer by username_1 on 2023-06-23. Score: 3
Labels
Some languages, such as Swift and C#, let you label the items in tuple types:
var t: (high: Int, low: UInt) = largeInteger.multipliedFullWidth(by: anotherLargeInteger)

These particular languages also have _ for an "ignore me" identifier:
let ignoresSecondArgument: (Int, Int) -> Int = { i, _ in i }
_ = ignoreTheReturnValue()
let yesThisIsLegal: (_: Int, _: Double) = (1, 2.0)
let soIsThis: (Int, Double) = (_: 3, _: 4.0)

So, you could require that single-element tuples have item labels, and then unlabelled single-element tuples use _:
let singleElementTuple = (_: 1)
let labelledSingleElementTuple = (x: 1)

Note: In Swift, labelled single-element tuples are illegal, and unlabelled single-element tuples are identical to the type that they wrap around. This means that, as strange as it looks, this is valid:
print((_: 2 + 3) / 5) // prints "1"
---
### Answer by username_0 on 2023-06-23. Score: 1
Compiler inference
Another, more complex option would be compiler inference. In a statically and strongly typed language, and one where few operators can be used on a tuple, it may be relatively simple to see where a tuple is expected, and check each possible set of parentheses to see whether or not it would make sense to treat it as a tuple. E.g.:
fn unwrap_me_once(x: (int)) -> int {
    x.0
}

unwrap_me_once((2 + 2)); // This must be a tuple
unwrap_me_once(((2 + 2))); // Either interpretation could be valid, but both are the same
unwrap_me_once(((2 + 2) * 4)); // The inner parentheses can't be a tuple

fn shame_on_me(x: int) -> int {
    x
}

shame_on_me((2 + 2).0); // This must be a tuple, since accessing an item of an int would be invalid
shame_on_me(((1 + 1) + (1 + 1))); // These must all be grouping, since + doesn't work on tuples, and the function expects an int instead of a single-item tuple
---
