digitalmars.dip.ideas - List comprehensions for D
- Quirin Schroll (82/82) Jun 10 ### Intro
Many languages, especially high-level and functional ones, have list comprehensions. Translated to D lingo, one can get a range object with elements based on other ranges. The hardest thing for D is to come up with a reasonable syntax and semantics. Comprehensions have two main advantages: * They are more readable than filter and map operations. * They are more concise than filter and map operations. Generally speaking, a comprehension has two parts: destinations and sources/conditions/variables. So, the basic template is this: ```d [ ArgumentList ; Comprehensors ] ``` The argument list usually has 1 entry, but it can have more. The `Comprehensors` are what I called sources/conditions/variables. They are semicolon-separated and every `Comprehensor` is of the form of a `foreach` (for a source), an `if` (for a condition), or a variable declaration. A simple example of a filter: ```d foreach (x; [ x; foreach (x; xs); if (x > 0) ]) { … } ``` The bracketed thing is a first-class object and has a type (unspelled, like a lambda), so it can be e.g. assigned to a local variable. ```d auto positives = [ x; foreach (x; xs); if (x > 0) ]; foreach (x; positives) { … } ``` Without links: ``` ComprehensionExpression: [ ArgumentList ; Comprehensors ] Comprehensors: Comprehensor ;? Comprehensor ; Comprehensors? Comprehensor: AggregateForeach RangeForeach if ( IfCondition ) VarDeclarations ``` With Links: *`ComprehensionExpression`*: `[` *[`ArgumentList`](https://dlang.org/spec/grammar.html#ArgumentList)* `;` *`Comprehensors`* `]` *`Comprehensors`*: *`Comprehensor`* `;`? *`Comprehensor`* `;` *`Comprehensors`*? *`Comprehensor`*: *[`AggregateForeach`](https://dlang.org/spec/grammar.html#AggregateForeach)* *[`RangeForeach`](https://dlang.org/spec/grammar.html#RangeForeach)* `if` `(` *[`IfCondition`](https://dlang.org/spec/grammar.html#IfCondition)* `)` *[`VarDeclarations`](https://dlang.org/spec/grammar.html#VarDeclarations)* This is implemented by a lowering. A ComprehensionExpression is an object of the following type: ```d struct CE // name is exposition-only and an implementation defined name { int opApplyImpl(DG)(scope DG dg) // name is exposition-only and an implementation defined name { // Comprehensors if (auto result = dg(ArgumentList)) return result; return 0; } alias opApply = opApplyImpl!(int delegate( typeof(ArgumentList) // (see comment below) )); } ``` For arguments that are lvalues, a `ref` is included unless the argument is a non-`ref` local variable (or foreach variable) declared in the comprehension expression. The `ComprehensionExpression` is replaced by `CE()`.
Jun 10