Add `HH\Lib\Ref<T>`
This class wraps a value inside an object - this can be useful to get byref-like semantics. For example:
$total = C\count($jobs);
$done = new Ref(0);
concurrent {
await Vec\map_async(
$jobs,
async $job ==> {
try {
return await handle_job_async($job);
} finally {
// As `$done` is an object, the changes persist outside of this scope;
// if `$done` were an integer, `$done++` would only modify a copy of
// the local within the lambda scope.
$done->value++;
}
},
);
await async {
while($done->value < $total) {
await \HH\Asio\usleep(1000 * 1000);
await IO\request_output()->writeAsync(
Str\format("Progress: %d/%d\n", $done->value, $total)
);
}
};
};
It is usually best to refactor to avoid this class; for example:
- use
inout
parameters - return values from lambdas instead of mutating values from inside lamdas
- use
C\reduce()
orC\reduce_with_key()
if a Ref is being used as an accumulator
There are cases like the above where Ref is the cleanest solution; you may also find Ref<vec<T>>
to be preferable to Vector<T>
, in order to use a consistent API and be more explicit about when a function is likely to mutate a container.