Shortcut to refer to a type field?

BlitzMax Forums/BlitzMax Beginners Area/Shortcut to refer to a type field?

ImaginaryHuman(Posted 2005) [#1]
Is there a shortcut of some kind that lets you refer to fields of nested types easily without having to do loads of field.field.field.x ? I'm kinda new to using types. Didn't the original BlitzBasic have such a feature?

e.g.
Type mytype
   Field avar:Int
End Type

Type mytype2
   Field bvar:mytype
   Field cvar:Int
End Type

Type mytype3
   Field dvar:mytype2
   Field evar:Int
End Type

Thing:mytype3=New mytype3

'How do I do this with less code:
Print Thing.dvar.bvar.avar

Is there some command that lets you refer only to the `mytype` fields? e.g.

Print .avar?

Or am I getting confused with `Self` and should be doing Object Oriented?


Bot Builder(Posted 2005) [#2]
Nope. No shortcut.


AaronK(Posted 2005) [#3]
There's no shortcut, but you'll find that normally things like this aren't too much of a problem. Not often, in the real world, if you're abstracted your design out, would you find going more than 1 deep. Sure sometimes you do, of course, but generally not. When you're working with an object, you call stuff etc on it's immediate fields, or maybe call a method on one of it's field objects.

Aaron


Robert(Posted 2005) [#4]
If you intend to use Thing.dvar.bvar.avar often in the same function, you could create a reference to bvar at the top:

Local bvar:mytype=Thing.dbar.bvar

bvar.avar=whatever




teamonkey(Posted 2005) [#5]
Or use pointers. Something like:
Type mytype
   Field avar:Int
End Type

Type mytype2
   Field bvar:mytype
   Field cvar:Int
End Type

Type mytype3
   Field dvar:mytype2
   Field evar:Int
End Type

Local Thing:mytype3=New mytype3

Local a:Int Ptr = Varptr(Thing.dvar.bvar.avar)

Print a[0] ' Thing.dvar.bvar.avar

Which will save typing if you use it a lot.


Bot Builder(Posted 2005) [#6]
With TeaMonkey's example you could also use this to access other variables in the type, since bmax stores its types with the variables in the same order. For instance:
Type mytype
   Field avar:Int
   Field fvar:Int
End Type

Type mytype2
   Field bvar:mytype
   Field cvar:Int
End Type

Type mytype3
   Field dvar:mytype2
   Field evar:Int
End Type

Local Thing:mytype3=New mytype3
Thing.dvar=New mytype2
Thing.dvar.bvar=New mytype

Thing.dvar.bvar.avar=5
Thing.dvar.bvar.fvar=10

Local a:Int Ptr = Varptr(Thing.dvar.bvar.avar)

Print a[0] ' Thing.dvar.bvar.avar
Print a[1] ' Thing.dvar.bvar.fvar
A bit cryptic and dangerous if mark changes something but hey :)


Robert(Posted 2005) [#7]
Using pointers is messy and will confuse the garbage collector - not recommended unless you have to.


Beaker(Posted 2005) [#8]
Whats wrong with doing it this way?
Type mytype
   Field avar:Int
End Type

Type mytype2
   Field bvar:mytype
   Field cvar:Int
End Type

Type mytype3
   Field dvar:mytype2
   Field evar:Int
End Type

Local Thing:mytype3=New mytype3
 Thing.dvar=New mytype2
 Thing.dvar.bvar=New mytype

Local temp:mytype = Thing.dvar.bvar
Print temp.avar



ImaginaryHuman(Posted 2005) [#9]
Thanks Robert, you were the first one to clue me in on what I had in mind. I figured something like that was possible but I just couldn't see it.

Setting a variable to the nested type will be very much what I need, thanks..

ie

Local temp:mytype = Thing.dvar.bvar
Print temp.avar

(as in beakers example above).

I just wanted to be able to go whatever.field, like relative to what type I wanted to work with, rather than give the whole absolute path. Thanks!

The pointer method is interesting, you sure can do some sneaky things with those, but I think the variable shortcut will be just fine.


teamonkey(Posted 2005) [#10]
Using pointers is messy and will confuse the garbage collector - not recommended unless you have to.

Yeah, it's only worth using the pointer method for non-object types like Int. Objects are passed by reference anyway.


FlameDuck(Posted 2005) [#11]
Accessor methods.


AaronK(Posted 2005) [#12]
Exactly FlameDuck. AngelDaniel, don't use that crappy pointer solution (NO offense Rob - it worked, but really it's sort of going about things the hard way and circumventing the whole reference thing going on with BlitzMax). Not BlitzMax is here and offers a lot of new (Old) techniques for doing programming, use them. They have lots of advantages. Resorting to oldschool stuff will just make your job more of a pain in the arse.


Make an accessor method. e.g. Have a method in mytype3 that gets you a mytype2. Then you just go

Thing.bvar().avar=23

OR do this.

Thing.setAvar(23)
Thing.getAvar(34)


These things should be methods anyway, cause accessing other Types' field sort of breaks the whole encapsulation thing just a tad.

Aaron


altitudems(Posted 2005) [#13]
Do you mean somthing like the "With" command in actionscript:
with (object) {
  _x = 50;
  _y = 100;
}
In BMX it might be:
With Player.Sprite
   x = 50
   y = 100
   width = .5
   height = .5
   alpha = .5
End With
Instead of:
Player.Sprite.x = 50
Player.Sprite.y = 50 
Player.Sprite.width = .5 
Player.Sprite.height = .5 
Player.Sprite.alpha = .5 



jhague(Posted 2005) [#14]
"with" (which is also in Pascal, BTW), has some subtle scoping issues. If you have a local or global named X, and also a field named X, then which one is referenced in the "with" block? It's easiest in Blitz Max to simply create another local variable, as others have mentioned above. It's neat and clean!


Robert(Posted 2005) [#15]
That isn't a bad idea actually, it saves typing and looks a whole lot neater.


Perturbatio(Posted 2005) [#16]
Yes, I too would like to see with (although I can code perfectly well without it, it saves a lot of typing).


AaronK(Posted 2005) [#17]
Why would you go Player.Sprite.x and Player.Sprite.y?

E N C A P S U L A T E

Player.SetSpriteDetails(50,50,.5,.5,.5)

In SetSpriteDetails(x,y,w,h,a)

sprite.SetDetails(x,y,w,h,a)

Aaron


ImaginaryHuman(Posted 2005) [#18]
Um... an accessor method sounds all very well but personally I'm not going to add extra methods to a type just so that I can get access to a subtype, when it would be far less code and probably quicker to just do it the long way ie field.field.field etc. All very well adding all this OO stuff but not for the sake of it.


AaronK(Posted 2005) [#19]
It's not just for the sake of it. What if you decide to change your implementation later, and you get to that object a different way? If you've got an accessor method, then you just change it in one place and the rest of your code works.

Good programming isn't about making it always quicker to implement. Think about maintenance, flexibility, reuse etc.

Software engineering has changed over the years, for a reason. Someone just didn't invent this stuff cause they were being 'cute'.


Sure if your program consists of plotting some points and making them go up and down, you might not bother. But any sort of large application benefits from strong design and impementation methods.



Aaron


FlameDuck(Posted 2005) [#20]
Actually it's probably about the same ammount of code (and besides which any good IDE, will generate them automatically for you) and chances are it's actually going to be faster.

Oh, and "what Aaron said". Again.


Bot Builder(Posted 2005) [#21]
"With" seems good. Oh, and I wasn't actually very serious about the whole pointer thing, its a very bad way to do it :) Just pointing out you can.

Personally, overiding functions, private member types, and properties (I've said this in about 6 places to make sure someone in BRL sees it) are much more important.