Re: Expression code blocks
| From: | Rowan Tommins | Date: | Sat, 17 Jun 2023 14:59:04 +0000 |
| Subject: | Re: Expression code blocks | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-120611@lists.php.net to get a copy of this message | ||
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]