[solved] Function parameter reference screw-up?

BlitzMax Forums/BlitzMax Programming/[solved] Function parameter reference screw-up?

Derron(Posted 2013) [#1]
Hi

I encountered some strange behaviour:

Type TPoint
	Field x:Float
	Field y:Float
	Field z:Float
...
End Type

Type TSprite
...
	Method DrawClippedNew(target:TPoint, source:TRectangle)
		'take care of offsets
		...
		target.MoveXY(10,10)
		...				
	End Method
End Type

local point:TPoint = TPoint.Create(0,0)
local test:TSprite = TSprite.Create(...)
test.DrawClippedNew( point, TRectangle.Create(0,0,100,100))

'this should print "0,0" but prints "10,10"
print point.x+","+point.y


The above code is not fully functional (because if done "separately" it works as intended).

Seems the variable "point" is passed as parameter - but I did not set a "var" after the function parameter list...


Ideas how that can happen / what makes that happen?


PS: if I modify the method to create another tpoint it works as it should too:
	Method DrawClippedNew(_target:TPoint, source:TRectangle)
		local target:TPoint = TPoint.Create(_target.x,_target.y)
		'take care of offsets
		...
		target.MoveXY(10,10)
		...				
	End Method



bye
Ron


Yasha(Posted 2013) [#2]
This is actually working as designed.

The only data passed "by value", i.e. copied by default, are the primitive numeric types and the pointers to values of object type. All values of object type (i.e. anything you define yourself) are passed by reference anyway - the reference itself is the value in such cases.

If you had defined the function with "var", it would make it possible to change the value of the "point" variable in the calling scope (a reference to the variable, not to the object), but wouldn't change the ability to mutate the contents of the object, because the same object is being referenced in either case, and that means the same fields are being modified.

Because all custom types in BlitzMax describe reference types, it's actually not possible to define a "value" (or "stack") type that exhibits the copy-on-assignment behaviour you're looking for here (like you'd have in C or C++). The manual copy in your modified method is the closest you can get to that - if you don't explicitly copy an object, your references will all still point at the same one.

I believe the standard practice when you want "math" type operations is to simply create and return new objects representing the modified form (e.g. adding two vectors results - at least temporarily - in three vector objects in memory).


Derron(Posted 2013) [#3]
Hmm I think I just had a too long coding session (or shouldn't code in other languages during breaks).

I knew that objects should behave like you described and I had in my app. Somehow my brain said that there is something odd happening.

So thanks for your reminder - and sorry I have taken some of your time writing a proper and long answer.


Rewriting portion of my code just to make the documentation simpler, the code more manageable - and then things like x:float,y:float -> point:TPoint may change the output of your app (especially if you want to save local variable assignments...) ... Refactoring doesn't get easier with that in mind.


bye
Ron