function returns two values

BlitzMax Forums/BlitzMax Beginners Area/function returns two values

hub(Posted 2010) [#1]
i need a sample code to show me how a function could return two values. For example x,y. (no globals)

using Type ?

Thanks !


Arabia(Posted 2010) [#2]
Funny you should ask. I was just reading up on the VAR (command? operator?)

http://www.blitzbasic.com/bmdocs/command.php?name=Var&ref=2d_a-z

It's not actually returning 2 values as such, but passing the argument to the function by reference (it's memory location, not it's value)


Zeke(Posted 2010) [#3]
Function randomposition:Int[]()
	Local x:Int = Rand(255) 
	Local y:Int = Rand(255)
	Return [x,y]
End Function

Local pos:Int[] = randomposition()

Print "x=" + pos[0] 'x
Print "y=" + pos[1] 'y



Arabia(Posted 2010) [#4]
That's fine Zeke (To be honest, I never knew you could return an array) but it will only work if the data types are the same won't it?


hub(Posted 2010) [#5]
arrays seems more interesting than type : lot of code just for returns two values with type (type was my method) !

Strict

Type TCoord

	Field X
	Field y

	Function Test : TCoord (a: Int)
	
		Local r:TCoord = New TCoord
	
		r.x = a
		r.y = a * 2
	
		Return r
	
	End Function

End Type


Local t:TCoord

t = TCoord.Test(10)

Notify t.x
Notify t.y


Last edited 2010


Oddball(Posted 2010) [#6]
You could also try the 'by reference' approach.
Function MultReturnVals( vInt:Int Var, vFloat:Float Var, vString:String Var )
	vInt=Rand(0,100)
	vFloat=Rnd(0.5,1.5)
	vString="This is a string"
End Function



GfK(Posted 2010) [#7]
I use this method:
Strict

Local a:Int = 1
Local b:String = "Hello"

cheeseMite(a,b)
Print a
Print b

Function cheeseMite(foo:Int Var, bar:String Var)
   foo:*10
   bar="Goodbye"
End Function



Czar Flavius(Posted 2010) [#8]
Instead of picking only one method, think carefully about what you need to return and pick the best method.

With the array method, you should store the return value in a local variable because it's inefficient to call the same function repeatedly for each index.

An array of Object can store different types, but you'd have to be rather crazy to go down that route.

Returning a type I would say is the best way. The type's fields can have meaningful names and the type's content layout is preset, so less chance of messing something up.

Using Var is also possible, but I'd exercise caution - it's usually expected that basic types sent to functions as parameters are not changed by this action. For something obvious, such as GetCoordinates(x, y, z), then it might be a good solution.

So to summarize, there are three ways, going with the same example of getting coordinates:

Return an array of three numbers.
Return a "Vector" type with three number fields.
Pass three number variables as Var parameters and change them.

Last edited 2010


John G(Posted 2010) [#9]
This may be extremely inelegant, but can't you simply use Globals inside a function?


Czar Flavius(Posted 2010) [#10]
You can, but having sets of globals for each function is difficult to maintain and prevents recursion and multithreading, so is a bad habit to get into. I'm sure at least one of the above methods should be good enough for somebody to use.


John G(Posted 2010) [#11]
Ah yes, my suggestion didn't sound as intended. I meant declare program-wide globals and use them inside the function -- or several functions. No Return necessary. (Erecting shield for rotten tomatoes.) Cheers


Matty(Posted 2010) [#12]
Not having used blitzmax, but used plenty of blitz3d/blitzplus/blitzbasic:

Why not use a bank? Return a reference to a bank which you then peek into to get the values, then free the bank afterwards.


Czar Flavius(Posted 2010) [#13]
Because then you might as well just return an array or list of values, and it will even free itself afterwards.


dmaz(Posted 2010) [#14]
I do by reference when it HAS to be the fastest... otherwise I like the array method because code is clean and it is still fast.

Function FromARGB:Int[]( argb:Int )
	Local array:Int[] = New Int[4]
	array[0] = (argb Shr 24) & $FF
	array[1] = (argb Shr 16) & $FF
	array[2] = (argb Shr 8) & $FF
	array[3] = argb & $FF
	Return array
End Function


it's especially nice when you only sometimes need one value so you can do:
local alpha:int = FromARGB(color)[0]

in some other languages like perl you can do:
(alpha,red,green,blue) = FromARGB(color)

which is awesome. I once asked Mark about that for bmx, he seemed to think it would be pretty cool but nothing did come of it.


Czar Flavius(Posted 2010) [#15]
It's not really very nice as you waste time calculating the other values and then wasting them, and you seem very interested in performance. It's more tedius to write, but more efficient to have a different function for each thing.


dmaz(Posted 2010) [#16]
Not everything is about performance. The functions extracts all 4 values and that it's main function. I'm not going write 4 different functions or place the bit operation in plain code when every cycle doesn't need to be counted like it would in a tight loop isn't. The key to optimization is knowing when to do it and when not to care!


Czar Flavius(Posted 2010) [#17]
You mentioned for yourself that speed was important, now it isn't. It would take 20 seconds to make a function for each channel of colour? Then you can use whatever one you need, and you don't need to remember which element is what.

Last edited 2010