Thread overview | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 08, 2015 static foreach considered | ||||
---|---|---|---|---|
| ||||
Walter and I are looking at ways to implement it. Here's a baseline without static foreach - a "trace" function that prints function calls before they are made: http://dpaste.dzfl.pl/762c83c7fe30 If the function is overloaded, that won't work. In such cases, static foreach might be helpful. Here's code from the cycle "I have a dream": http://dpaste.dzfl.pl/82a70c809210 I'm trying to collect together motivating examples and to figure out the semantics of the feature. Andrei |
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Monday, 8 June 2015 at 20:02:11 UTC, Andrei Alexandrescu wrote:
> Walter and I are looking at ways to implement it. Here's a baseline without static foreach - a "trace" function that prints function calls before they are made:
>
> http://dpaste.dzfl.pl/762c83c7fe30
>
> If the function is overloaded, that won't work. In such cases, static foreach might be helpful. Here's code from the cycle "I have a dream":
>
> http://dpaste.dzfl.pl/82a70c809210
>
> I'm trying to collect together motivating examples and to figure out the semantics of the feature.
>
>
> Andrei
How will scoping work? Similar to mixin templates?
It would be nice together with this feature to be able to mixin identifiers:
static foreach (ident; ["foo", "bar"])
{
auto mixin(ident)()
{
// code for foo/bar
}
}
Otherwise, other than overloads and template instantiations this won't be much better then generating code strings with CTFE...
|
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Monday, 8 June 2015 at 20:16:53 UTC, Idan Arye wrote:
> On Monday, 8 June 2015 at 20:02:11 UTC, Andrei Alexandrescu wrote:
>> Walter and I are looking at ways to implement it. Here's a baseline without static foreach - a "trace" function that prints function calls before they are made:
>>
>> http://dpaste.dzfl.pl/762c83c7fe30
>>
>> If the function is overloaded, that won't work. In such cases, static foreach might be helpful. Here's code from the cycle "I have a dream":
>>
>> http://dpaste.dzfl.pl/82a70c809210
>>
>> I'm trying to collect together motivating examples and to figure out the semantics of the feature.
>>
>>
>> Andrei
>
> How will scoping work? Similar to mixin templates?
>
> It would be nice together with this feature to be able to mixin identifiers:
>
> static foreach (ident; ["foo", "bar"])
> {
> auto mixin(ident)()
> {
> // code for foo/bar
> }
> }
>
> Otherwise, other than overloads and template instantiations this won't be much better then generating code strings with CTFE...
I would assume that it would be pretty much the same as doing
foreach(T; TypeTuple!(...))
{
...
}
except that you're not forced to shove everything in a TypeTuple.
- Jonathan M Davis
|
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On 06/08/2015 10:16 PM, Idan Arye wrote: > On Monday, 8 June 2015 at 20:02:11 UTC, Andrei Alexandrescu wrote: >> Walter and I are looking at ways to implement it. Here's a baseline >> without static foreach - a "trace" function that prints function calls >> before they are made: >> >> http://dpaste.dzfl.pl/762c83c7fe30 >> >> If the function is overloaded, that won't work. In such cases, static >> foreach might be helpful. Here's code from the cycle "I have a dream": >> >> http://dpaste.dzfl.pl/82a70c809210 >> >> I'm trying to collect together motivating examples and to figure out >> the semantics of the feature. >> >> >> Andrei > > How will scoping work? Similar to mixin templates? > ... I think the body should have access to a scope that is hidden from the outside which contains the loop variable, but declarations should be inserted into the enclosing scope like for static if. > It would be nice together with this feature to be able to mixin > identifiers: > > static foreach (ident; ["foo", "bar"]) > { > auto mixin(ident)() > { > // code for foo/bar > } > } > > Otherwise, other than overloads and template instantiations this won't > be much better then generating code strings with CTFE... +1. Other use cases: auto mixin(ident) = x; identifier.list.mixin(ident).foo(); import std.mixin(ident); |
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Monday, 8 June 2015 at 20:02:11 UTC, Andrei Alexandrescu wrote:
> I'm trying to collect together motivating examples and to figure out the semantics of the feature.
>
>
> Andrei
Hmmm, codegen based on UDA?
struct magic
{
interface readonly;
private static struct hidden
{
@readonly enum a = 0;
}
static foreach(id; __traits(allMembers, hidden))
{
// Inspect UDA and generate code accordingly,
// Ex fields with public ReadOnly and private ReadWrite
}
}
|
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Monday, 8 June 2015 at 21:14:46 UTC, Jonathan M Davis wrote: > I would assume that it would be pretty much the same as doing > > foreach(T; TypeTuple!(...)) > { > ... > } > > except that you're not forced to shove everything in a TypeTuple. > > - Jonathan M Davis If that was the case, A library solution for converting a compile-time range to a TypeTuple would have sufficed(http://dpaste.dzfl.pl/7eb30f5e1156 - this compiles in 2.67). The problem with regular `foreach` over type tuple is that declarations inside the foreach's body are invisible from the outside. If `static foreach` had this limitation, Andrei's example wouldn't work since `trace` would be local to the body of the `static foreach`. This essentially renders the main usecase of this feature(declaring stuff) and leaves us with a loop unrolling optimization... |
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Monday, 8 June 2015 at 21:32:52 UTC, Timon Gehr wrote:
> I think the body should have access to a scope that is hidden from the outside which contains the loop variable, but declarations should be inserted into the enclosing scope like for static if.
This would require some syntax to mark the declarations we want to expose. Maybe `out`?
This is far better than the mixin template approach, since it'll alert us early about conflicts:
static foreach (ident; ["a", "b", "a"])
{
int mixin(ident ~ "1");
out int mixin(ident ~ "2");
}
`a1` is created twice, but that's OK since it isn't marked with `out`. `a2` is declared twice and raises a compilation error because it's marked with `out`. This will ensure these kind of errors are detected early and the compilation error points to the exact place of declaration.
|
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Monday, 8 June 2015 at 20:02:11 UTC, Andrei Alexandrescu wrote: > I'm trying to collect together motivating examples and to figure out the semantics of the feature. maybe not completely related, but I made a blog post on using CTFE to unroll foreach at compiletime https://rsw0x.github.io/post/switch-unrolling/ I find myself often writing recursive templates for compile-time generation of constructs that could be done cleaner with static foreach. |
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On 06/09/2015 12:12 AM, Idan Arye wrote:
> On Monday, 8 June 2015 at 21:32:52 UTC, Timon Gehr wrote:
>> I think the body should have access to a scope that is hidden from the
>> outside which contains the loop variable, but declarations should be
>> inserted into the enclosing scope like for static if.
>
> This would require some syntax to mark the declarations we want to
> expose. Maybe `out`?
>
> This is far better than the mixin template approach, since it'll alert
> us early about conflicts:
>
> static foreach (ident; ["a", "b", "a"])
> {
> int mixin(ident ~ "1");
> out int mixin(ident ~ "2");
> }
>
> `a1` is created twice, but that's OK since it isn't marked with `out`.
> `a2` is declared twice and raises a compilation error because it's
> marked with `out`. This will ensure these kind of errors are detected
> early and the compilation error points to the exact place of declaration.
I actually intended all declarations in the body to be inserted into the enclosing scope, at least by default.
|
June 08, 2015 Re: static foreach considered | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 6/8/15 2:14 PM, Jonathan M Davis wrote:
>
> I would assume that it would be pretty much the same as doing
>
> foreach(T; TypeTuple!(...))
> {
> ...
> }
>
> except that you're not forced to shove everything in a TypeTuple.
I'm even fine with the type tuple, just allow at declaration level and don't introduce a scope. Would be a great start. -- Andrei
|
Copyright © 1999-2021 by the D Language Foundation