On 17/06/2023 12:26, Ilija Tovilo wrote:
I don't believe blocks for general expressions are that useful in PHP
due to the lack of block scoping. Your suggestion to make the block a
separate closure could avoid that (as well as the optimizer issue
mentioned below) but comes with new issues, like making modification
of captured values impossible without by-ref capturing.
I've been pondering various things in this space for a while,
particularly since the last auto-capture closures RFC. I haven't quite
coalesced on a coherent concept, but there are a few things that I think
inter-relate:
* Opting into block-scoped variables, while retaining full access to the
outer scope, like JS "let"
* Code blocks as some kind of first-class thing, distinct from closures
* Macro-like constructs that take a block of code and do something
special with it, or something like Python's "context managers"
One of the use cases people often cite for auto-capture in closures is
for use in patterns like this:
$db->doInTransaction(function() use (...) {
$db->execute('some SQL here');
$db->execute('some more SQL');
// etc
});
Or this:
$name = $cache->memoize(function() use (...) {
$result = $db->query('some SQL');
return $result['item_name'];
});
This is a nice pattern, but closures are quite a heavy tool for this
job, requiring two extra stack frames (the doInTransaction or memoize
method, and the closure itself), and boilerplate to pass the result back
through.
As I say, I haven't got a coherent design, but I think it would be great
to have something context-manager-like:
$name = with($cache->memoize() as $cacheItem) {
let $result = $db->query('some SQL');
$cacheItem->save( $result['item_name'] );
} );
... or macro-based:
$name = null;
$cache->memoize!($name, block {
let $result = $db->query('some SQL');
$name = $result['item_name'];
} );
Regards,
--
Rowan Tommins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php