Re: How do I set a class member value by its name in a string?

2017-12-28 Thread Marc via Digitalmars-d-learn

Always helpful. Thank you very much guys.


Re: How do I set a class member value by its name in a string?

2017-12-28 Thread Mengu via Digitalmars-d-learn

On Wednesday, 27 December 2017 at 23:47:14 UTC, Biotronic wrote:

[...]


much, much better. thanks biotronic.


Re: How do I set a class member value by its name in a string?

2017-12-27 Thread Biotronic via Digitalmars-d-learn

On Wednesday, 27 December 2017 at 21:42:53 UTC, Mengu wrote:

On Wednesday, 27 December 2017 at 21:39:49 UTC, Mengu wrote:

On Wednesday, 27 December 2017 at 20:54:17 UTC, bitwise wrote:

[...]


there's also a simple workaround for fields with the same 
type: https://run.dlang.io/is/dsFajq


import std.stdio;

struct S {
  int x;
  int y;
}

auto setValue(ref S s, string field, int value) {
  foreach (fieldName; __traits(allMembers, S)) {
if (fieldName == field) {
  __traits(getMember, s, fieldName) = value;
  break;
}
  }
}

void main() {
  S s;
  s.setValue("x", 5);
  s.setValue("y", 25);
  writeln(s);
}


you can play with it to make it more generic. you can also 
create a mixin template that would generate setters for each 
field you would need a setter for and then in the run time 
you'd just be able to call them.


return type should just be void. that's just my muscle memory. 
:-D


More generic, for more better:

void setValue(T, V)(auto ref T aggregate, string field, V value)
{
import std.traits : FieldNameTuple;
import std.meta : Alias;
switch (field)
{
foreach (fieldName; FieldNameTuple!T)
{
case fieldName:
static if (is(typeof(__traits(getMember, 
aggregate, fieldName) = value)))

{
__traits(getMember, aggregate, fieldName) = 
value;

return;
}
else assert(false, T.stringof ~ "."~field~" 
cannot be assigned from a "~V.stringof~".");

}
default:
assert(false, T.stringof ~ " has no field named 
"~field~".");

}
}

unittest {
import std.exception : assertThrown;
import core.exception : AssertError;

static struct S {
int x;
string s;
}

S s;
s.setValue("x", 14);
assert(s.x == 14);
assertThrown!AssertError(s.setValue("q", 14));
assertThrown!AssertError(s.setValue("s", 14));
s.setValue("s", "abc123");
assert(s.s == "abc123");
}

unittest {
import std.exception : assertThrown;
import core.exception : AssertError;

static class C {
int x;
string s;
}

C c = new C;
c.setValue("x", 14);
assert(c.x == 14);
assertThrown!AssertError(c.setValue("q", 14));
assertThrown!AssertError(c.setValue("s", 14));
c.setValue("s", "abc123");
assert(c.s == "abc123");

(new C).setValue("x", 143);
}

--
  Biotronic


Re: How do I set a class member value by its name in a string?

2017-12-27 Thread Mengu via Digitalmars-d-learn

On Wednesday, 27 December 2017 at 21:39:49 UTC, Mengu wrote:

On Wednesday, 27 December 2017 at 20:54:17 UTC, bitwise wrote:

[...]


there's also a simple workaround for fields with the same type: 
https://run.dlang.io/is/dsFajq


import std.stdio;

struct S {
  int x;
  int y;
}

auto setValue(ref S s, string field, int value) {
  foreach (fieldName; __traits(allMembers, S)) {
if (fieldName == field) {
  __traits(getMember, s, fieldName) = value;
  break;
}
  }
}

void main() {
  S s;
  s.setValue("x", 5);
  s.setValue("y", 25);
  writeln(s);
}


you can play with it to make it more generic. you can also 
create a mixin template that would generate setters for each 
field you would need a setter for and then in the run time 
you'd just be able to call them.


return type should just be void. that's just my muscle memory. :-D


Re: How do I set a class member value by its name in a string?

2017-12-27 Thread Mengu via Digitalmars-d-learn

On Wednesday, 27 December 2017 at 20:54:17 UTC, bitwise wrote:

On Wednesday, 27 December 2017 at 20:04:29 UTC, Marc wrote:
I'd like to set the members of a class by its name at runtime, 
I would do something like this:



__traits(getMember, myClass, name) = value;


but since name is only know at runtime, I can't use 
__traits(). What's a workaround for this?


I think you could write something using a combination of these 
two things:


https://dlang.org/phobos/std_traits.html#FieldNameTuple
https://dlang.org/phobos/std_traits.html#Fields

or maybe '.tupleof':

https://dlang.org/spec/struct.html#struct_properties


there's also a simple workaround for fields with the same type: 
https://run.dlang.io/is/dsFajq


import std.stdio;

struct S {
  int x;
  int y;
}

auto setValue(ref S s, string field, int value) {
  foreach (fieldName; __traits(allMembers, S)) {
if (fieldName == field) {
  __traits(getMember, s, fieldName) = value;
  break;
}
  }
}

void main() {
  S s;
  s.setValue("x", 5);
  s.setValue("y", 25);
  writeln(s);
}


you can play with it to make it more generic. you can also create 
a mixin template that would generate setters for each field you 
would need a setter for and then in the run time you'd just be 
able to call them.


Re: How do I set a class member value by its name in a string?

2017-12-27 Thread bitwise via Digitalmars-d-learn

On Wednesday, 27 December 2017 at 20:04:29 UTC, Marc wrote:
I'd like to set the members of a class by its name at runtime, 
I would do something like this:



__traits(getMember, myClass, name) = value;


but since name is only know at runtime, I can't use __traits(). 
What's a workaround for this?


I think you could write something using a combination of these 
two things:


https://dlang.org/phobos/std_traits.html#FieldNameTuple
https://dlang.org/phobos/std_traits.html#Fields

or maybe '.tupleof':

https://dlang.org/spec/struct.html#struct_properties





Re: How do I set a class member value by its name in a string?

2017-12-27 Thread Benjamin Thaut via Digitalmars-d-learn

On Wednesday, 27 December 2017 at 20:04:29 UTC, Marc wrote:
I'd like to set the members of a class by its name at runtime, 
I would do something like this:



__traits(getMember, myClass, name) = value;


but since name is only know at runtime, I can't use __traits(). 
What's a workaround for this?


You will have to use a combination of compile time and runtime 
methologies.


Essentially what you want is this:

void setMemberValue(string name, int value)
{
  switch(name)
  {
case "member1":
  member1 = value;
  break;
case "member2":
  member2 = value;
  break:
...
  }
}

As you don't want to write this for all members by hand you 
should write a function which generates the source code for this 
switch using static foreach and __traits(allMembers) and then 
mixin the generated string into the setMemberValue method. If 
your members can have different types you will also need runtime 
type that can hold multiple types. For simplicity I just used 
"int" in the above example. You could use "std.variant" for this.


How do I set a class member value by its name in a string?

2017-12-27 Thread Marc via Digitalmars-d-learn
I'd like to set the members of a class by its name at runtime, I 
would do something like this:



__traits(getMember, myClass, name) = value;


but since name is only know at runtime, I can't use __traits(). 
What's a workaround for this?