Hi
On 1/15/26 19:38, Volker Dusch wrote:
a function is already a reasonable scope
That - together with the other points you raised - made me realize one
thing: In contrast to block scoping, the main purpose of “Context
Managers” is *not* managing arbitrary variables in the current scope in
combination with existing control structures. Instead it is just
managing a single variable in a reasonably *self-contained* fashion,
with other variables just needing to “exist”.
It could therefore also just be a regular function taking a callback, as
is already done in userland, e.g. with Laravel's DB::transaction() helper.
I believe something like this would be equivalent to the RFC:
function using(
callable $runInContext,
ContextManager ...$managers
): void {
$contexts = [];
foreach ($managers as $manager) {
$contexts[] = $manager->enterContext();
}
try {
$runInContext(...$contexts);
foreach (array_reverse($managers) as $manager) {
$manager->exitContext();
}
} catch (Throwable $e) {
foreach (array_reverse($managers) as $manager) {
if ($manager->exitContext($e) === true) {
$e = null;
}
}
if ($e !== null) {
throw $e;
}
}
}
This would completely side-steps the “break to exit” question, since a
`return` will just work. It also avoids introducing new keywords, it
just requires a new function in the global namespace.
I understand that using variables from the current scope in a Closure is
currently not particularly convenient, particularly when they need to be
changed. However this is something that can be solved in a generic
fashion, for example inspired by the C++ lambda syntax:
// Captures everything by value and $result by reference.
function ($context) use (*, &$result) { }
// Captures everything by reference.
function ($context) use (&*) { }
which would also be useful in other situations.
Best regards
Tim Düsterhus