# Expressions And Operators: Coalesce

Given the expression `e1 ?? e2`, if `e1` is defined and not `null`, then the result is `e1`. Otherwise, `e2` is evaluated, and its value becomes the result. There is a sequence point after the evaluation of `e1`.

``````\$nully = null;
\$nonnull = 'a string';
\print_r(vec[
\$nully ?? 10,    // 10 as \$nully is `null`
\$nonnull ?? 10,  // 'a string' as \$nonnull is `nonnull`
]);

\$arr = dict['black' => 10, 'white' => null];
\print_r(vec[
\$arr['black'] ?? -100,  // 10 as \$arr['black'] is defined and not null
\$arr['white'] ?? -200,  // -200 as \$arr['white'] is null
\$arr['green'] ?? -300,  // -300 as \$arr['green'] is not defined
]);
``````
Output
``````Vec
(
[0] => 10
[1] => a string
)
Vec
(
[0] => 10
[1] => -200
[2] => -300
)
``````

It is important to note that the right-hand side of the `??` operator will be conditionally evaluated. If the left-hand side is defined and not `null`, the right-hand side will not be evaluated.

``````\$nonnull = 4;

// The `1 / 0` will never be evaluated and no Exception is thrown.
\$nonnull ?? 1 / 0;

// The function_with_sideeffect is never invoked.
\$nonnull ?? function_with_sideeffect();
``````

## `??` and `idx()`

The `??` operator is similar to the built-in function `idx()`. However, an important difference is that `idx()` only falls back to the specified default value if the given key does not exist, while `??` uses the fallback value even if a key exists but has `null` value. Compare these examples to the ones above:

``````\$arr = dict['black' => 10, 'white' => null];
\print_r(vec[
idx(\$arr, 'black', -100),  // 10
idx(\$arr, 'white', -200),  // null
idx(\$arr, 'green', -300),  // -300
idx(\$arr, 'green'),        // null
]);
``````
Output
``````Vec
(
[0] => 10
[1] =>
[2] => -300
[3] =>
)
``````

## Coalescing assignment operator

A coalescing assignment operator `??=` is also available.

The `??=` operator can be used for conditionally writing to a variable if it is null, or to a collection if the specified key is not present or has `null` value.

This is similar to `e1 = e1 ?? e2`, with the important difference that `e1` is only evaluated once.

``````\$arr[++\$i] ??= 42;              // \$i is incremented once
\$arr[++\$i] = \$arr[++\$i] ?? 42;  // \$i is incremented twice
``````

The `??=` operator is very useful for initializing elements of a collection:

``````function get_counts_by_value(Traversable<string> \$values): dict<string, int> {
\$counts_by_value = dict[];
foreach (\$values as \$value) {
\$counts_by_value[\$value] ??= 0;
++\$counts_by_value[\$value];
}
return \$counts_by_value;
}

function get_people_by_age(
KeyedTraversable<string, int> \$ages_by_name,
): dict<int, vec<string>> {
\$people_by_age = dict[];
foreach (\$ages_by_name as \$name => \$age) {
\$people_by_age[\$age] ??= vec[];
\$people_by_age[\$age][] = \$name;
}
return \$people_by_age;
}

<<__EntryPoint>>
function main(): void {
\$values = vec['foo', 'bar', 'foo', 'baz', 'bar', 'foo'];
\print_r(get_counts_by_value(\$values));

\$people = dict[
'Arthur' => 35,
'Ford' => 110,
'Trillian' => 35,
'Zaphod' => 120,
];
\print_r(
get_people_by_age(\$people)
|> Dict\map(\$\$, \$names ==> Str\join(\$names, ', '))
);
}
``````
Output
``````Dict
(
[foo] => 3
[bar] => 2
[baz] => 1
)
Dict
(
[35] => Arthur, Trillian
[110] => Ford
[120] => Zaphod
)
``````