www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - pragma msg field name?

reply Chris Katko <ckatko gmail.com> writes:
inside a static foreach I can do

```
enum rep;

class myObject{
int field1, field2, field3;

static foreach(field; getSymbolsByUDA!(typeof(this), rep))
{
	pragma(msg, field);  // fails
	pragma(msg, fullyQualifiedName!field); // works
}
}
```

error for pragma(msg, field)
```
source/app.d(33,16): Error: value of `this` is not known at 
compile time
source/app.d(33,4):        while evaluating `pragma(msg, field)`

[repeating for every variable in the class]
```

How do I get just the field name? And why does it think this is a 
run-time value? I need to wrap it in some sort of template?

All I see in std.traits docs are: fullyQualifiedName mangledName 
moduleName packageName
Jun 26 2023
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/26/23 21:25, Chris Katko wrote:

 How do I get just the field name?
I know .tupleof, which you can typeof() as well: class myObject{ int field1, field2, field3; static foreach(field; typeof(this).tupleof) { pragma(msg, field.stringof); } static foreach(MemberType; typeof(typeof(this).tupleof)) { pragma(msg, MemberType); } } The output: field1 field2 field3 int int int I had to consult what I wrote years ago: http://ddili.org/ders/d.en/tuples.html#ix_tuples..tupleof Ali
Jun 26 2023
parent reply Chris Katko <ckatko gmail.com> writes:
On Tuesday, 27 June 2023 at 04:56:19 UTC, Ali Çehreli wrote:
 On 6/26/23 21:25, Chris Katko wrote:

 How do I get just the field name?
I know .tupleof, which you can typeof() as well: class myObject{ int field1, field2, field3; static foreach(field; typeof(this).tupleof) { pragma(msg, field.stringof); } static foreach(MemberType; typeof(typeof(this).tupleof)) { pragma(msg, MemberType); } } The output: field1 field2 field3 int int int I had to consult what I wrote years ago: http://ddili.org/ders/d.en/tuples.html#ix_tuples..tupleof Ali
That seems to do the trick, I was really not expecting so much text just to get something so simple! At the moment I'm trying to take variables with an attribute (rep) and then make a duplicate of them inside the struct. It seems to work. If I had duplicate names, it fails. However, the new fields don't appear to be showing up on a second enumeration: enum rep; struct multiplayerObject2 { rep ushort type; ("rep2") ushort type2; float x, y; static foreach(t; typeof(this).tupleof) { // no if rep/rep2 here, i'm just testing: pragma(msg, t.stringof); // does not see any new fields! mixin("bool " ~ t.stringof ~ "25;"); // copy the fieldname with a suffix } pragma(msg, "-----separator-----"); static foreach(t; typeof (this).tupleof) // again { pragma(msg, t.stringof); // does not see any new fields! } } output ``` type type2 x y -----separator----- type type2 x y ``` However, if I do try to force the names to duplicate (say "type2") I get an error involving some sort of __anonymous subobject. ``` source/app.d-mixin-123(123,6): Error: variable `app.multiplayerObject2.__anonymous.type2` conflicts with variable `app.multiplayerObject2.type2` at source/app.d(116,19) ``` I also never realized you could put a static/static foreach inside the body of a struct (and not a function) so I'm still having trouble wrapping my head around that. Is it processing top-down? Jonathan M Davis: Yeah, it does what I listed if you add the UDA to it.
Jun 26 2023
parent reply Chris Katko <ckatko gmail.com> writes:
Does anyone know why the new variables don't show up after the 
static foreach?

I have a struct, it has some marked fields. I want to note those 
fields at compile time and make some similarly named fields like 
myField becomes myField__replicated.

The code doesn't _have_ to be inside the struct/class itself. It 
could be:
```
auto replicatedObject = makeReplicated!(myObject);
```
for example.

I'm not sure the high-level best way right now, as I'm currently 
having issues with the nitty-gritty implementation of templates.




snippetcode (drop right into run.dlang.io):
```D
import std;

struct multiplayerObject2
	{
	ushort type;
	ushort type2;
	float x, y;
	
	static foreach(t; typeof(this).tupleof)
		{
		pragma(msg, t.stringof);
		mixin("bool " ~ t.stringof ~ "25;"); // copy the fieldname with 
a suffix
		}

	pragma(msg, "-----separator-----");

	static foreach(t; typeof (this).tupleof) // again
		{
		pragma(msg, t.stringof); // does not see any new fields!
		}
	}

void main()
{

}
```



```D
// Output
type
type2
x
y
-----separator-----
type
type2
x
y
```
Jun 27 2023
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 27 June 2023 at 22:20:22 UTC, Chris Katko wrote:
 		pragma(msg, t.stringof); // does not see any new fields!
D's declarations are all order-independent, in theory those foreaches are done simultaneously, so it is kinda a race condition. In practice, the compiler does them in two passes but both based on the same initial state. Adding stuff and then reflecting over the stuff you add must be done as explicit steps on the outside, like you can make a `struct step1 {}` then `alias step2 = transform!step1;` then `alias step3 = transform_again!step2;` or something.
Jun 27 2023
next sibling parent Chris Katko <ckatko gmail.com> writes:
On Tuesday, 27 June 2023 at 22:34:17 UTC, Adam D Ruppe wrote:
 On Tuesday, 27 June 2023 at 22:20:22 UTC, Chris Katko wrote:
 		pragma(msg, t.stringof); // does not see any new fields!
D's declarations are all order-independent, in theory those foreaches are done simultaneously, so it is kinda a race condition.
Thank you, that's what I thought, but then I started adding them and there was no warning and I was like "wait... is this top-down???"
 In practice, the compiler does them in two passes but both 
 based on the same initial state.

 Adding stuff and then reflecting over the stuff you add must be 
 done as explicit steps on the outside, like you can make a 
 `struct step1 {}` then `alias step2 = transform!step1;` then 
 `alias step3 = transform_again!step2;` or something.
Okay again makes more sense. The amount of stuff that was "kinda" working, plus learning through tiny 3 liner code snippets in docs, was making my brain explode a bit. A constructor/factory pattern for this makes way more sense. Sometimes it's hard to tell where things are symbolic / functional, verses procedural/linear.
Jun 27 2023
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/27/23 6:34 PM, Adam D Ruppe wrote:
 On Tuesday, 27 June 2023 at 22:20:22 UTC, Chris Katko wrote:
         pragma(msg, t.stringof); // does not see any new fields!
D's declarations are all order-independent, in theory those foreaches are done simultaneously, so it is kinda a race condition.
In particular the practice of adding new members based on introspecting other members is suspect. I've done it too, but I think it probably would be better if we didn't allow this kind of stuff, or came up with a sane way to do this. This leads to all kinds of weird stuff. Like if you instantiate a template with the current type being compiled, that template is locked to that type *at that point in compilation*. Then you look at it outside the type, and the value is already cached. -Steve
Jun 27 2023
prev sibling next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, June 26, 2023 10:25:13 PM MDT Chris Katko via Digitalmars-d-learn 
wrote:
 inside a static foreach I can do

 ```
 enum rep;

 class myObject{
 int field1, field2, field3;

 static foreach(field; getSymbolsByUDA!(typeof(this), rep))
 {
   pragma(msg, field);  // fails
   pragma(msg, fullyQualifiedName!field); // works
 }
 }
 ```

 error for pragma(msg, field)
 ```
 source/app.d(33,16): Error: value of `this` is not known at
 compile time
 source/app.d(33,4):        while evaluating `pragma(msg, field)`

 [repeating for every variable in the class]
 ```

 How do I get just the field name? And why does it think this is a
 run-time value? I need to wrap it in some sort of template?

 All I see in std.traits docs are: fullyQualifiedName mangledName
 moduleName packageName
Well, on my machine, once the import for std.traits is added, that code compiles but prints nothing, so I suspect that you paired it down too much (likely related to the fact that none of the fields in question actually have UDAs on them). However, I would point out that getSymbolsByUDA gives you symbols, not strings, whereas pragma(msg, ...) wants a string. fullyQualifiedName works, because it results in a string. You can see what field is by using typeof on it, but presumably, it's complaining about being a runtime value, because when you use it, it's trying to evaluate the symbol (e.g. get the value of field1). Using .stringof on field will give you a string, though I don't know if it'll give you what you're looking for. In general, FieldNameTuple would probably be what you would want for getting the names of the fields in a struct or class, though obviously, that wouldn't be just getting the ones with a specific UDA. - Jonathan M Davis
Jun 26 2023
parent Dennis <dkorpel gmail.com> writes:
On Tuesday, 27 June 2023 at 05:03:01 UTC, Jonathan M Davis wrote:
 However, I would point out that getSymbolsByUDA gives you 
 symbols, not strings, whereas pragma(msg, ...) wants a string.
For some time now, it accepts any number of objects, which will all be converted to strings and concatenated to form the message. The same applies to `static assert()`.
Jun 27 2023
prev sibling parent Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 27 June 2023 at 04:25:13 UTC, Chris Katko wrote:
 How do I get just the field name?
__traits(identifier, field)
 And why does it think this is a run-time value?
It is the same as if you wrote `Class.field`
Jun 27 2023