digitalmars.D.learn - switch to member
- Ignacious (21/21) Jan 13 2017 When doing common functionality for a switch, is there any way to
- Nicholas Wilson (21/43) Jan 13 2017 if `q` is the only data structure that you are wanting to do
- Meta (5/20) Jan 14 2017 IMO this is massive overkill to save some typing. To the OP, it's
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/22) Jan 13 2017 Sounds like opDispatch may be useful.
- Marc =?UTF-8?B?U2Now7x0eg==?= (34/34) Jan 14 2017 You can utilize a little-known `switch` syntax trick in
- Ivan Kazmenko (3/8) Jan 14 2017 That looks concise. Perhaps enum Which can also be automatically
- Ignacious (6/40) Jan 14 2017 Cool, pretty straightforward and somewhat easy to use. I suppose
- Ivan Kazmenko (17/30) Jan 14 2017 Do you mean that verbatim? Or are the case values strings, like:
When doing common functionality for a switch, is there any way to
optimize:
switch(x)
{
case X:
q.X = e;
break;
case Y:
q.Y = e;
break
etc...
}
e is basically a value that, depending on the what kind(x), we
assign it to a field in q. The name of the field and the case
label are identical(in fact, it wouldn't hurt to do it either
automatically(if x's enum name, if exists, matches a field, auto
assign) or create the field in the class q automatically if the
label matches a certain range or set).
Basically the idea is to avoid duplicating a lot of code.
I imagine one could write a string mixin that generates the cases
and assignments but I'm hoping for a more elegant solution.
Jan 13 2017
On Saturday, 14 January 2017 at 03:20:24 UTC, Ignacious wrote:
When doing common functionality for a switch, is there any way
to optimize:
switch(x)
{
case X:
q.X = e;
break;
case Y:
q.Y = e;
break
etc...
}
e is basically a value that, depending on the what kind(x), we
assign it to a field in q. The name of the field and the case
label are identical(in fact, it wouldn't hurt to do it either
automatically(if x's enum name, if exists, matches a field,
auto assign) or create the field in the class q automatically
if the label matches a certain range or set).
Basically the idea is to avoid duplicating a lot of code.
I imagine one could write a string mixin that generates the
cases and assignments but I'm hoping for a more elegant
solution.
if `q` is the only data structure that you are wanting to do
this for
(or a 1:1 mapping for enum and type) then you can make
the enumeration values of x equal to the offsetof of q.
e.g. where typeof(q) == Q
enum XX
{
X = Q.X.offsetof,
Y = Q.Y.offsetof
//ect.
}
and then
*(cast(void*)(this) + x) = e; //if inside struct/class
or
*(cast(void*)(q) + x) = e; // if outside
Unfortunately this loses you ` safe`ty, but as long as you trust
the value of x then it should be safe to ` trusted` that code.
If you are trying to avoid code duplication the enum declaration
of X
could also be done with a string mixin.
Jan 13 2017
On Saturday, 14 January 2017 at 05:29:49 UTC, Nicholas Wilson
wrote:
enum XX
{
X = Q.X.offsetof,
Y = Q.Y.offsetof
//ect.
}
and then
*(cast(void*)(this) + x) = e; //if inside struct/class
or
*(cast(void*)(q) + x) = e; // if outside
Unfortunately this loses you ` safe`ty, but as long as you trust
the value of x then it should be safe to ` trusted` that code.
If you are trying to avoid code duplication the enum
declaration of X
could also be done with a string mixin.
IMO this is massive overkill to save some typing. To the OP, it's
not really worth it to go to so much trouble. Just write some
slightly duplicated code and move on.
Jan 14 2017
On Saturday, 14 January 2017 at 08:30:04 UTC, Meta wrote:On Saturday, 14 January 2017 at 05:29:49 UTC, Nicholas Wilson wrote:Go join the Nazi Youth group, you OSS Sympathizer!enum XX { X = Q.X.offsetof, Y = Q.Y.offsetof //ect. } and then *(cast(void*)(this) + x) = e; //if inside struct/class or *(cast(void*)(q) + x) = e; // if outside Unfortunately this loses you ` safe`ty, but as long as you trust the value of x then it should be safe to ` trusted` that code. If you are trying to avoid code duplication the enum declaration of X could also be done with a string mixin.IMO this is massive overkill to save some typing. To the OP, it's not really worth it to go to so much trouble. Just write some slightly duplicated code and move on.
Jan 14 2017
On Saturday, 14 January 2017 at 16:05:33 UTC, Ignacious wrote:Go join the Nazi Youth group, you OSS Sympathizer!What?
Jan 14 2017
On 01/13/2017 07:20 PM, Ignacious wrote:
When doing common functionality for a switch, is there any way to optimize:
switch(x)
{
case X:
q.X = e;
break;
case Y:
q.Y = e;
break
etc...
}
e is basically a value that, depending on the what kind(x), we assign it
to a field in q. The name of the field and the case label are
identical(in fact, it wouldn't hurt to do it either automatically(if x's
enum name, if exists, matches a field, auto assign) or create the field
in the class q automatically if the label matches a certain range or set).
Basically the idea is to avoid duplicating a lot of code.
I imagine one could write a string mixin that generates the cases and
assignments but I'm hoping for a more elegant solution.
Sounds like opDispatch may be useful.
Ali
Jan 13 2017
You can utilize a little-known `switch` syntax trick in
combination with `foreach`. Because a `foreach` over tuples is
unrolled at compile time, it works even if your fields don't have
exactly the same types:
--------------------------------------------------------------
struct Foo {
int x, y;
long a, b, c;
short i, j, k;
}
enum Which {
x, y, a, b, c, i, j, k,
}
void assignValue(ref Foo q, Which member, short e) {
import std.traits : EnumMembers;
import std.conv : to;
final switch(member) {
// foreach over a tuple is unrolled at compile time
foreach(w; EnumMembers!Which) {
case w:
// expands to: q.x, q.y, ...
mixin("q." ~ w.to!string) = e;
break;
}
}
}
void main() {
import std.stdio : writeln;
Foo q;
writeln("before: ", q);
assignValue(q, Which.a, 42);
assignValue(q, Which.x, 1);
writeln("after: ", q);
}
Jan 14 2017
On Saturday, 14 January 2017 at 11:32:10 UTC, Marc Schütz wrote:You can utilize a little-known `switch` syntax trick in combination with `foreach`. Because a `foreach` over tuples is unrolled at compile time, it works even if your fields don't have exactly the same types: <snip>That looks concise. Perhaps enum Which can also be automatically filled by __traits (allMembers) or std.traits.Fields if needed.
Jan 14 2017
On Saturday, 14 January 2017 at 11:32:10 UTC, Marc Schütz wrote:
You can utilize a little-known `switch` syntax trick in
combination with `foreach`. Because a `foreach` over tuples is
unrolled at compile time, it works even if your fields don't
have exactly the same types:
--------------------------------------------------------------
struct Foo {
int x, y;
long a, b, c;
short i, j, k;
}
enum Which {
x, y, a, b, c, i, j, k,
}
void assignValue(ref Foo q, Which member, short e) {
import std.traits : EnumMembers;
import std.conv : to;
final switch(member) {
// foreach over a tuple is unrolled at compile time
foreach(w; EnumMembers!Which) {
case w:
// expands to: q.x, q.y, ...
mixin("q." ~ w.to!string) = e;
break;
}
}
}
void main() {
import std.stdio : writeln;
Foo q;
writeln("before: ", q);
assignValue(q, Which.a, 42);
assignValue(q, Which.x, 1);
writeln("after: ", q);
}
Cool, pretty straightforward and somewhat easy to use. I suppose
it might be easier to mark the enum members with an attribute
though and use that rather than having two enums? I didn't know
about the foreach in the switch, cool idea!
Thanks.
Jan 14 2017
On Saturday, 14 January 2017 at 03:20:24 UTC, Ignacious wrote:switch(x) { case X: q.X = e; break; case Y: q.Y = e; break etc... }Do you mean that verbatim? Or are the case values strings, like: switch(x) { case "foo": q.foo = e; break; case "bar": q.bar = e; break }I imagine one could write a string mixin that generates the cases and assignments but I'm hoping for a more elegant solution.In any case, I also can imagine a mixin answer, but not much better. Unless you want to actually look at the broader picture and maybe redesign the surrounding code to somehow cleverly get rid of the switch altogether. The question as it is however doesn't give the context to make it possible. Ivan Kazmenko.
Jan 14 2017









Meta <jared771 gmail.com> 