A couple of extensions to `with` that would be worthwhile
Paul Backus
snarwin at gmail.com
Wed Oct 13 20:41:11 UTC 2021
On Wednesday, 13 October 2021 at 19:18:55 UTC, Andrei
Alexandrescu wrote:
> The point is that with keeps the entire expression live, even
> if you only care about a part of it:
>
> struct S { int x; ... }
>
> with (auto y = S().x)
> {
> ...
> }
>
> In this case the S() temporary will be destroyed only at the
> end of with's scope.
Not a fan. It uses the same syntax as `if (auto y = S().x)` but
has subtly different semantics, in a way that's likely to go
unnoticed in common usage.
It's also not obvious which sub-expressions get kept alive. For
example:
// What's kept alive--S(1), S(2), or both?
bool b = /* ... */;
with (auto y = (b ? S(1) : S(2)).x)
// Are S(1) and S(2) kept alive?
S fun(S a, S b) { /* ... */ }
with (auto y = fun(S(1), S(2)).x)
Of course one could work out a set of rules for this and add them
to the language spec, but it seems like a lot of effort and
complexity for not much benefit, especially when we can already
get the desired behavior with normal block scopes:
{
S temporary = S();
with(auto y = temporary.x)
{
/* ... */
}
} // temporary's lifetime ends here
> This enables idioms such as "I want to create a temporary
> string and mess with it".
You can already do this by wrapping the string in a struct that
owns its memory:
struct OwnedString
{
string[] payload;
~this() { free(payload.ptr); }
// etc.
}
That way, D's existing scoping rules will ensure that the
resources are released at the correct time, and you do not have
to worry about keeping some unrelated temporary alive via obscure
special-case language rules.
More information about the Digitalmars-d
mailing list