Print data type of a variable?

Started by Yellownakji, February 23, 2019, 23:46:35

Previous topic - Next topic

Yellownakji

Hello.  I'm wondering if i can print the data type of a stored variable?

For example, let's say i have a global string called "myvariable1"...   Is there someway i can check what type of data "myvariable1" is and print it?  In this case, print "string".
:P

Derron

if you use "Framework" at the top of your programm - add below of it: "import BRL.Reflection".


Then in your code:
Code (BlitzMax) Select

local t:TTypeId = TTypeID.ForObject(yourVariable)
if t then print "type: " + t.Name()



bye
Ron

Yellownakji

Quote from: Derron on February 24, 2019, 07:27:09
if you use "Framework" at the top of your programm - add below of it: "import BRL.Reflection".


Then in your code:
Code (BlitzMax) Select

local t:TTypeId = TTypeID.ForObject(yourVariable)
if t then print "type: " + t.Name()


Thank you, Ron.  This was very helpful.


bye
Ron

Yellownakji

#3
Quote from: Derron on February 24, 2019, 07:27:09
if you use "Framework" at the top of your programm - add below of it: "import BRL.Reflection".


Then in your code:
Code (BlitzMax) Select

local t:TTypeId = TTypeID.ForObject(yourVariable)
if t then print "type: " + t.Name()



bye
Ron

Ron,  so i've been playing around with this and it's been very helpful.   However, i'm still stumped on something.  If i'm not mistaken, BlitzMax isn't interpreted and what i'm trying to do requires interpretation.  I'm still going to inquire anyways.

So, what i'm trying to do is make a quick and easy inject feature for my Save/Load module.   Basically, it's Add(Val:object) and what it does is it takes the VAL:OBJECT and adds it's value to a list.  then it adds the TYPE ID to another list.    the list is saved to a file, the ID list is saved in ram, as it's only needed in ram for reading.

Basically, i want to get the name of the variable that was used in place of VAL:TOBJECT...  for instance, let's say i used MyName:String (and i set it to = "jon" above;global) for VAL:TOBJECT (and of course, the type id would be "string" and the value would be "jon").

I would like to get the name of the variable (MyName:String) and then set it to the value i saved in my binary.   So basically, something like this:


*determine data type* (in this case, string)
OBJNAME:TOBJECT = ReadString(binary,len)

basically.   but i don't think that's allowed in BlitzMax.

What do you think?

Derron

This is not possible for "globals" in default (reflection has no "global" support). NG and "ReflectionExtended" allow to access globals (not checked but thought so).

Regardless of this: to have savegames in TVTower(.org) I use "bah.persistence" (github.com/maxmods/bah.git). It serializes data into XML - and of course allows deserialization of xml into objects.

To keep stuff "centralized" I am using "collections". They are "global types" with other "globals" stored as fields. This is (partly) called "Singleton" approach - only one instance of this type exists.

In essence it is like this:
Code (BlitzMax) Select

Type TGameConfig
  Field playername:string = "Jon"
  Field difficulty:int = 0
End Type
Global GameConfig:TGameConfig = new TGameConfig


Now when saving I pass "GameConfig" to a new "TPersistence" instance and let it serialize into an XML. When loading it back I let a new "TPersistence" instance deserialize the given XML and get back a "TGameConfig" instance. This I _manually_ assign back to "GameConfig"

Code (BlitzMax) Select

GameConfig = myPersistenceInstance.DeserializeFromFile("serializedGameConfig.xml")


As only one "GameConfig" exists all parts of my game will from now on access the very same "TGameConfig" instance.

---

As said with Grable's ReflectionExtended (for vanilla/legacy BlitzMax) or NG's Reflection you can access "globals" too. But for it to work you need a "type" containing the globals. So you can only modify/access globals _within_ a type.

That said you could also use this:
Code (BlitzMax) Select

Type GameConfig
  Global playername:string = "Jon"
  Global difficulty:int = 0
End Type

No need to have a custom instance of this type (directly access now via "typename.globalname" -> "GameConfig.playername").
To access the Global you could try

Code (BlitzMax) Select

'read
stream.WriteLine( TTypeID.ForName("GameConfig").FindGlobal("playername").GetString() )

'set
TTypeID.ForName("GameConfig").FindGlobal("playername").SetString( stream.ReadLine() )

As you see here: there is stuff in "quotes" - which means you can easily access this stuff dynamically from a string array or such stuff (iterate over various things like ["playername", "shipname"]) but make sure you check for existence of the global first - so do not blindly use "GetString()" on something you do not know if it exists or not).


bye
Ron

Yellownakji

Quote from: Derron on February 26, 2019, 06:56:03
This is not possible for "globals" in default (reflection has no "global" support). NG and "ReflectionExtended" allo...

I see.  I figured it wasn't possible, so i'm taking a different approach to my design.   The rest isn't what i'm looking for but thank you.

Derron

I think it is exactly what you are looking for: a way to store and load data without actually writing the name of the variable in the code.

My approach allows to reference stuff either "automatically" (just pass the "GameConfig" or however you name your "global collection" to TPersist) or you reference it eg. via an array of strings and handle it on your own via brl.Reflection.


Writing complex types (with eg. references to other objects) cannot be done in a "write memory blob of object to file" way as the "reading back" wont restore the references to the other object (which eg. is not read back already - or is now at a different position). It only works if the references are based on "loose coupling". So eg you do not store "Field ship:TShip" but an "Field shipID:int" which then fetches the actual "ship:TShip" from a "ShipCollection".


bye
Ron