https://issues.dlang.org/show_bug.cgi?id=23136
--- Comment #2 from Bolpat <[email protected]> --- This could be solved by allowing captures to be explicitly specified in a capture list, like C++ lambdas do it. Here’s how it could be done: A lambda or non-static local function may have a capture list after the parameter list and before any constraints and contracts. The capture list is syntactically expressed with square brackets (or, as an alternative, with `catch` and parentheses). The capture list is optional; providing no capture list is equivalent to providing `[ref]` (or `catch(ref)`). The entries of a capture list are comma-separated. The first entry of a capture list can be a specially handled token sequence, called "capture default": It can be `ref` or `auto`. (Otherwise it is handled like other entries.) Every other entry must be (Grammar below) 1. `this`, or 2. an Identifier, or 3. `ref` followed by `this`, 4. `ref` followed by an Identifier, or 5. `auto` followed by an Identifier, `=`, and a [ConditionalExpression](https://dlang.org/spec/expression.html#ConditionalExpression), or 6. `ref` followed by an Identifier `=`, and a ConditionalExpression, or 7. `auto ref` followed by an Identifier `=`, and a ConditionalExpression. `this` can be specified at most once and Identifiers must be unique. (Specifying `this` is only valid in a non-static member function.) An `auto ref` capture is `auto` if the ConditionalExpression evaluates to an rvalue and it is `ref` if the ConditionalExpression evaluates to an lvalue. If the ConditionalExpression is a compile-time sequence (introduced by template `...` in some way), `auto ref` becomes `auto` or `ref` for each sequence element individually. (The primary use-case for this is parameter forwarding.) A capture that includes the `ref` token is called a "reference capture" and a "value capture" otherwise. A non-`this` capture without `=` is treated as if it were followed by `=` and the given identifier, and prefixed by `auto` if it is not `ref`. (This rewrite is assumed in the following.) The Identifiers/`this` on the left of `=` in the capture list are called left-hand sides, the ConditionalExpressions in the capture list are called right-hand sides. The left-hand sides are only in scope of the lambda, not its parent. The right-hand sides are resolved in the scope of the lambda’s parent. For a value capture, the context of the lambda holds a value that is initialized by the right-hand side when statement is encountered in which the lambda resides. If the right-hand side is implicit, the type must be copyable; a non-copyable type can be used if the right-hand side is an rvalue. For a reference capture, the context of the lambda holds a reference to the variable. If the lambda is `scope`, variables that hold the lambda must not outlive the bound references. (There is no such restriction for value captures.) This has two important consequences: 1. Lambdas with value captures are dependent on the exact point of creation. 2. Value captures cannot be shared among lambdas. In contrast to C++, in D, a lambda with captures may outlive the captured variables (unless, of course, it is marked `scope`). A local variable that is captured by a non-`scope` lambda must be allocated on the heap only if the capture is by reference. A reference parameter cannot be captured unless the lambda is `scope`. In contrast to C++, in D, a lambda’s call operator is not `const`; value captures can be written to (unless, of course, their type is `const` or `immutable` or the lambda is itself marked `const` or `immutable`). Grammar: ``` CaptureList: [ ] [ CaptureDefault ] [ CaptureDefault , ] [ CaptureList ] [ CaptureList , ] [ CaptureDefault , Captures ] [ CaptureDefault , Captures , ] CaptureDefault: ref auto Captures: Capture Capture , Captures Capture this ref this Identifier ref Identifier auto Identifier = ConditionalExpression ref Identifier = ConditionalExpression auto ref Identifier = ConditionalExpression ``` As a syntactical alternative, instead of using brackets, the `catch` keyword could be re-used: ``` CaptureList: catch ( CaptureDefault ) catch ( CaptureDefault , ) catch ( CaptureList ) catch ( CaptureList , ) catch ( CaptureDefault , Captures ) catch ( CaptureDefault , Captures , ) ``` --
