Re: What's a good approach to DRY with the block code of a case-statement?

2021-04-28 Thread z via Digitalmars-d-learn
I'd recommend you to use templates with alias parameters but you 
mentioned that you need to retain function context(for gotos, 
continue, break, etc...)
One thing you could do is mix the ugly mixin solution with the 
good one:

```D
//inside the function, so that you can access locals
pragma(inline, true)
string getDRYstr(T, parameters...)() {
static assert(__ctfe);
string mixedinstr;
mixedinstr ~= /*code*/;
static if(/**/){mixedinstr ~= /*code*/;}
//...
mixedinstr ~= "break;";
return mixedinstr
}
```
There is no doubt that it is an ugly solution but the time saved 
not copy-pasting code could be worth it.


Re: What's a good approach to DRY with the block code of a case-statement?

2021-04-26 Thread ag0aep6g via Digitalmars-d-learn

On Monday, 26 April 2021 at 20:39:55 UTC, Jack wrote:
I have a block of code that the only thing that change is the 
type passed in one of the template functions called so I'd like 
to make a DRY for this. But I'm not just replacing by a 
function due to control-flow, for example, there are 
if-statements where one just break and the other return 0. I 
think I could do something with mixin() that would kinda mimic 
C's macro but I still find it messy. Any alternatives?


```d
static int doSomething()
{
switch(val)
{
case VAL_FOO:
auto obj = getObject!MyType(someData); // this is the 
type

   // that changes
if(obj.shouldExit()) break;

auto m = Message(...);
if(obj.doSomethingElse(m)) return 0;
break;

   // ...

   default:
}

return doSomethingY();
}
```


I think you're looking for this D idiom:

```d
sw: switch (rt_value)
{
static foreach (ct_value; ct_values)
{
case ct_value: some_template!ct_value; break sw;
}
}
```

Applied to your code it might look like this:

```d
import std.meta: AliasSeq;
alias stuff = AliasSeq!(VAL_FOO, MyType, VAL_BAR, MyOtherType, /* 
... */);

sw: switch (val)
{
static foreach (i; 0 .. stuff.length / 2)
{
case stuff[i]:
auto obj = getObject!(stuff[i + 1])(someData);
if(obj.shouldExit()) break sw;
auto m = Message(...);
if(obj.doSomethingElse(m)) return 0;
break sw;
}
}
```


What's a good approach to DRY with the block code of a case-statement?

2021-04-26 Thread Jack via Digitalmars-d-learn
I have a block of code that the only thing that change is the 
type passed in one of the template functions called so I'd like 
to make a DRY for this. But I'm not just replacing by a function 
due to control-flow, for example, there are if-statements where 
one just break and the other return 0. I think I could do 
something with mixin() that would kinda mimic C's macro but I 
still find it messy. Any alternatives?


```d
static int doSomething()
{
switch(val)
{
case VAL_FOO:
auto obj = getObject!MyType(someData); // this is the 
type

   // that changes
if(obj.shouldExit()) break;

auto m = Message(...);
if(obj.doSomethingElse(m)) return 0;
break;

   // ...

   default:
}

return doSomethingY();
}
```

Maybe my least resort, if I went to replace by a function, I 
could do something like this:


```d
enum OP { BREAK, RETURN }
pragma(inline, true):
OP foo(T)()
{   
auto obj = getObject!T(someData); // this is the type

   // that changes
if(obj.shouldExit()) return OP.BREAK;

auto m = Message(...);
if(obj.doSomethingElse(m)) return OP.RETURN;

return OP.BREAK;
}
```

then:

```d
static int doSomething()
{
switch(val)
{
case VAL_FOO:
auto r = foo!MyType();
if(r == OP.BREAK) break;
if(r == OP.RETURN0) return 0;
break;

   // ...

   default:
}

return doSomethingY();
}
```

I still find this not much elegant. If anyone knows a better way 
to do this, help are very welcome