TYPEs variable names

Previous topic - Next topic

matchy

I hope this is not too much of a weird question but is there a way to get the names of the variable in a TYPE?

For example:
Code (glbasic) Select

TYPE TList
apple
orange
potatoe
ENDTYPE

GLOBAL list as TList

list.apple = 8
list.orange = 5
list.potatoe = 12

DEBUG list.variable_name[0], 0, 0

Output: apple

MrTAToad

No, I dont see it being possible....

matchy


Kitty Hello

For small platforms that would mean, that each variable also would have to store a string containing the name.
That would be some sort of meta programming language, which is usually only available for interpreted languages. The binary does not know of any names anymore. It's just a set of address numbers.


Moru

Not totally related but I keep using variables called "type" in glbasic... Always throws me off since I use them a lot in PHP and other languages :-)

Kitty Hello

TYPE is a keyword. Use typ, tp or kind instead?

Moru

Yes, I end up using typ instead but that is swedish and it feels a bit strange in programming :-)

Slydog

#7
I'm not sure what your specific needs are by looking at your example code, but a dictionary concept may help you.
(Apples, Oranges, and Potatoes? . . . it sounds like one awful recipe!  :noggin:)

Here's a dictionary library I created, but have never used beyond simple testing.
Check the example usage at the end where I tried to apply it to your sample code.

BTW, just to clarify, does GLB have a 'null' concept for integer or float data types?
I've been using a 'BLANK' constant for my 'null' detection, but if you happened to use the value of 'BLANK' for a dictionary item, it could cause havoc.
ie. i'm trying to return a 'null' if a 'Get' call can't find the item.

Code (glbasic) Select
CONSTANT BLANK% = -12345

TYPE TDictionaryItem
name$
value
ENDTYPE

TYPE TDictionary
table[] AS TDictionaryItem

FUNCTION Clear:
DIM self.table[0]
ENDFUNCTION

FUNCTION Add: name$, value
// If 'name$' already exists, call 'Set' instead
IF self.Exists(name$)
self.Set(name$, value)
RETURN
ENDIF

LOCAL item AS TDictionaryItem
item.name$ = name$
item.value = value
DIMPUSH self.table[], item
ENDFUNCTION

FUNCTION Get: name$, defaultValue=BLANK
LOCAL rv# = defaultValue

FOREACH item IN self.table[]
IF item.name$ = name$
rv = item.value
BREAK
ENDIF
NEXT

RETURN rv
ENDFUNCTION

FUNCTION Set%: name$, value
LOCAL hx%
// If the 'name$' doesn't exist in the table, call 'Add' instead
IF NOT self.Exists(name$)
self.Add(name$, value)
RETURN
ENDIF

FOREACH item IN self.table[]
IF item.name$ = name$
item.value = value
BREAK
ENDIF
NEXT
ENDFUNCTION

FUNCTION Exists%: name$
FOREACH item IN self.table[]
IF item.name$ = name$
RETURN TRUE
ENDIF
NEXT
RETURN FALSE
ENDFUNCTION

ENDTYPE


LOCAL dictionary AS TDictionary
dictionary.Clear()
dictionary.Add("apple", 8)
dictionary.Add("orange", 5)
dictionary.Add("potatoe", 12)

DEBUG "table name at pos 0: " + dictionary.table[0].name$ + "\n"
DEBUG "apple: " + dictionary.Get("apple") + "\n"
DEBUG "banana: " + dictionary.Get("banana") + "\n\n"

dictionary.Set("apple", 99)
DEBUG "apple: " + dictionary.Get("apple") + "\n"
dictionary.Add("apple", 77) // 'apple' aleardy exists, so library just 'Sets' the existing 'apple' to 77
DEBUG "apple: " + dictionary.Get("apple") + "\n\n"

DEBUG "pear: " + dictionary.Get("pear") + "\n"
dictionary.Set("pear", 44) // 'pear' doesn't already exist, so library 'Adds' it instead, and sets it to 44
DEBUG "pear: " + dictionary.Get("pear") + "\n"



Output:
Code (glbasic) Select
table name at pos 0: apple
apple: 8
banana: -12345

apple: 99
apple: 77

pear: -12345
pear: 44


[Edit] The 'Add' and 'Set' seem to do the same thing (Add: If exists set it instead, Set: Add it if doesn't exist) but I kept them separate for the usage clarity, and in case you want to handle them differently by modifying the code.  I just did it this way to make my game more robust so it wont mess up if I expect something to be in the library and it isn't.  The 'proper' way to do the 'Add' would be to return FALSE if the item exists and TRUE if it doesn't, and 'Set' would return FALSE if the item doesn't exist, or else set the item and return TRUE.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

matchy

Cheers for useful dictionary code although it is similar to how I manage data, that is to initialize values in an array.  :P

The reason for metadata look up is because I like to use types just to store a lot of constants.  ;)

This example demonstrates how I can efficiently import constants without initialization or function look-up.  :rtfm:
Code (glbasic) Select

// CONSTANT COLORS_RED = 0x0000ff // old way

TYPE _colors
none = -1
white = 0xffffff
black = 0x000000
red = 0x0000ff
green = 0x00ff00
blue = 0xff0000
ENDTYPE

main_colors()

FUNCTION main_colors:
LOCAL colors AS _colors

CLEARSCREEN colors.white
DRAWRECT 0, 0, 320, 15, colors.red
DRAWRECT 0, 20, 320, 15, colors.green
DRAWRECT 0, 40, 320, 15, colors.blue
SHOWSCREEN
MOUSEWAIT
ENDFUNCTION

Slydog

#9
This leads to a missing feature of GLB: enumerations
I have about a dozen places in my game where I would have used them.
They keep the code clean when used properly, plus allow you to limit inputs to functions by specifying an ENUM variable instead of a data type.

In C#:
Code (glbasic) Select
enum Colours {
none = -1,
white = 0xffffff,
black = 0x000000,
red = 0x0000ff,
green = 0x00ff00,
blue = 0xff0000
}

rect_colour = Colours.red;


In GLB?:
Code (glbasic) Select
ENUM Colours%     // The '%' specifies that values in this enum are integer
none = -1
white = 0xffffff
black = 0x000000
red = 0x0000ff
green = 0x00ff00
blue = 0xff0000
ENDENUM

DRAWRECT 0, 0, 320, 15, Colours.red

// . . or in a function call
FUNCTION DrawRectange: x, y, w, h, colour AS Colours
  IF colour = Colours.none THEN colour = Colours.white
  DRAWRECT x, y, w, h, colour
ENDFUNCTION


BTW, I currently use the 'CONSTANT' method, your 'old way'.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]