Passing array to functions

BlitzMax Forums/BlitzMax Beginners Area/Passing array to functions

Abomination(Posted 2006) [#1]
ok.
I have an enormous array of Types: Cel:TCel[alot]
and a humongous Multidimensional array: Pos:int[many,evenmore].
I also have a bunch of functions that use both of them
Now, should I:
a) Make them global?
b) Do something like UpdateArray(Cel,Pos)?
c) forget about it and eat a coocky?


Who was John Galt?(Posted 2006) [#2]
Make them global or pass them to your array handling functions - they pass by reference so no slowdown.


Cajun17(Posted 2006) [#3]
Depends on how many functions need to use them and how you design your app. Also, it's cookie and yes you may have one.


H&K(Posted 2006) [#4]
Make a type that has fields of Cell:TCell[alot] and Pos:Int[many,evenmore], and fill it with a bunch of Methods that use both of them


Abomination(Posted 2006) [#5]
Since I ate the "cookie" :) i've tested your sugestions.
As for speed, I could not find any significant differance, so I just keep them global.
I don't use the idea of H&K because I don't realy like to work with "nested" arrays and Code. "My brain is not capable to follow that kind of complexity ;) "


Perturbatio(Posted 2006) [#6]
they pass by reference so no slowdown.


Surely things are only passed by reference if you use the Var keyword?


Yan(Posted 2006) [#7]
I thought that too, but things seem to be a bit hazy when it comes to arrays...
Strict

Local myArray[10]

FillArray(myArray)
PrintArray(myArray)

End

Function FillArray(thisArray[])
	For Local c = 0 Until thisArray.length
		thisArray[c] = c * 10
	Next
End Function

Function PrintArray(thisArray[])
	For Local c = 0 Until thisArray.length
		Print thisArray[c]
	Next
End Function
...But...
Strict

Local myArray[10]

FillArray(myArray)
PrintArray(myArray)

End

Function FillArray(thisArray[])'need Var
	thisArray = thisArray[..20]
	For Local c = 0 Until thisArray.length
		thisArray[c] = c * 10
	Next
End Function

Function PrintArray(thisArray[])
	For Local c = 0 Until thisArray.length
		Print thisArray[c]
	Next
End Function



Grey Alien(Posted 2006) [#8]
I don't use var with types as they are *always* passed by reference but I sometimes do with Ints, Floats etc. if I need to. So as TArray isn't clear cut, I guess it's better to use var if you need a reference only? Also what about String? I found you have to use var with that too, even though it's a Type really because it has methods...


Dreamora(Posted 2006) [#9]
Everything extended from Object is always byRef. String and Array are extended from Object.

The only thing that is not by Ref by default are numerics ... Those need VAR if you want to change them within a method / function.


Yan(Posted 2006) [#10]
Classic Dreamora. ;o)


TomToad(Posted 2006) [#11]
Dremora:
Strict

Local mystring:String = "Hello, "

addworld(mystring)

Print mystring
End

Function addworld(thisstring:String)
	thisstring :+ "world!"
	Print thisstring
End Function

Strings are definately not passed by reference. As you can see, World is only appended to a local copy of the string. Change thisstring:String to thisstring:String Var and it works on the original string.


Grey Alien(Posted 2006) [#12]
yeah exactly what I found (and said)


Who was John Galt?(Posted 2006) [#13]
In both those examples I believe the array/string is passed in by reference, but the internal functions used (slicing, array concatenation) do not operate 'in place' - they allocate new memory for the result. In this case the 'var' is required to pass the new handle back.


Yan(Posted 2006) [#14]
...
Strict

Local a$ = "hello"

ChangeMe(a$)

Print a$

End

Function ChangeMe(in$)
	in$ = "HELLO"
End Function



Byteemoz(Posted 2006) [#15]
Prints "hello" as expected...

Edit: Strings are objects. It's the compiler that lets them behave like primitive datatypes.

Edit2: Even _if_ the string where passed by reference your code would change the reference from the old string "hello" to the new string "HELLO" - leaving the old string(-object) untouched...


Who was John Galt?(Posted 2006) [#16]
Hmm weird... I guess Byteemoz' 'edit 1' is the answer. Not what I expected.


Yan(Posted 2006) [#17]
I think it's vitally important to point out at this stage that the sky is, in fact, blue!


Jim Teeuwen(Posted 2006) [#18]
Lies! There is no sky.


Grey Alien(Posted 2006) [#19]
The sky is not an object!


H&K(Posted 2006) [#20]
If the sky is blue, does that mean the Land is yellow? Because when you look at the land from above the sky, it looks green?

Mind you the sky would be filtering colours, not adding them, so the land is probably orange

I still think that a type with the fields in, is the way to do the first question. Dont forget if you are only going to have one instance of the type, you could make the arrays global fields of the type


Abomination(Posted 2006) [#21]
Well, dit we get a bit oftrack!
As for the sky:
It only "looks" blue from sealevel.
The closer (higher) one gets the darker it gets, until it looks black.
If you would travel even higher, the sky doesn't even exist anymore, since you would be in space.

As for the array-question:
For speed it doesn't realy matter wich method I use to access an array within a function.
So it becomes a matter of Programming-Style.
I like to use as many globals as possible and as few Parameters to functions as I can.
So I will go for Globals ;0


H&K(Posted 2006) [#22]
When the sky looks black, its because its behind you.

I Still think you should make them Globals of a Type. But as you said, its just preferance


tonyg(Posted 2006) [#23]
I like to use as many globals as possible

Other than the reuseability and portability factor (which is entirely up to you) multiple globals might cause a performance hit.


Abomination(Posted 2006) [#24]
"the reuseability and portability factor"... do you mean of functions that use globals instead of parameters?
"a performance hit"... As far as I know are locals only 5-10% faster than globals. And using a global inside a function instead of passing it as a parameter is about 10% faster!
So how does it slow things down?


tonyg(Posted 2006) [#25]
No, I mean the reuseability/portability of code that doesn't rely on globals being set anywhere.
Your first post didn't talk about using globals within functions but globals within a program.
Globals used within functions are not global to the program so you'd still have to pass them to other functions unless you're making them global to a type... or am I missing something else?
Mark has recommended using local rather than global variables for the same reason, including speed.
5-10% faster. Not sure where you got the value from but that's still faster... no?


Abomination(Posted 2006) [#26]
Let's see if we can unravel this.
"Using a global" is not "declaring a global".
So: I Declare a bunch of globals in "Main", then use them within functions.
A litle "stupid" example:
'without any globals
local x:int
local y:int
UpdatePos(x,y)

function UpdatePos(xpos:int,ypos:int)
     setcolor 255,255,255
     plot xpos,ypos
end function


now I "tend" to do something like:
'without Function Parameters
Global x:int
global y:int
UpdatePos()

function UpdatePos()
     setcolor 255,255,255
     plot x,y
end function


Now, the latter is not better, but it IS (neglectable) faster.
Do your remarks aboout reuseability/portability/performance
aply to this?


tonyg(Posted 2006) [#27]
Yes.
Imagine you create a function called PLOT_FUNC as follows...
function UpdatePos()
     setcolor 255,255,255
     plot x,y
end function

which relies on gloabl x and y.
Imagine you now create another 1000 functions which you keep in a library. One of these functions happens to be called HI_SCORE()...
Function HI_SCORE()
  If x>y then print "Congratulations!"
end function

When you wrote this function it also relied on global x/y.
To reuse HI_SCORE you would have to change the x,y values top somethign else. Not too bad in a 1 line function but imagine if it's an entire module!
This would affect the use of 3rd party modules as well.
Obviously, you could make the globals very unique but you're then left with hundreds of globals where you have to be worried what they're called.
As for speed, the example you have is reusing the same variables so times should be similar. However, the speed gain will be seen more readily (still nothing huge which is why I baulked at your 5-10%) with multiple variables.
There's some discussion about local variables using CPU registers and cache on these forums.


Abomination(Posted 2006) [#28]
Yes, it requires to keep extra good track of your globals.
But the functions have no use unless they have the proper globals declared, so it's vital and logical to save the globals together with the functions if you store the code to be reused.
A double declared global will pop up if it's in more than one piece of code.
But I agree; it does have disadvantages like that.
But it also has some advantages:
Like when you need multiple results from a function or not having to write a dozen of parameters (in the correct order)
You also don't have to change every bit of code that calls a function of which you want to change or add parameters.


H&K(Posted 2006) [#29]
Adomination you have just descrided the good bits of types (Objects)

In my opinion Its vital that the globals are declared as globals within a type, and any functions that use them are functions/methods of that type. (Or friends of the type, but I dont think BMax has them)

I know you are not going to change your setup, and would not sudjest that you did. But even just concidering the NameSpace aspect of Typeing Globals, it nearly always makes integration of that specific part into the whole, a lot easyer.

I know you feel this is just another layer of abstraction, that you can do without. But at least concider doing it the next time you have a "Petty" Global, even if only as a programing test excersise


Abomination(Posted 2006) [#30]
Ah, H&K; it's nice to see you at least understand my reasoning.
Types are an elegant way to store data and I can see the usefulness of methods, functions and even globals within a Type.
There are 2 reaons why I dont use Types that way.
1). I'm not used to do so. :)
2). Though the ease of sharing code by different Types is improved by the introduction of polymorphism in BMax...well...
An example:
let's say object A needs to know the next position of object B.
Now I would go:
TestObject=B
CalcNewPos()
' now the new position of B would be in Xpos and Ypos and accessible to A.

Now with Methods: (oooow boy!)
Method TestOponent()
xpos=Object[B].CalcNewPosX
ypos=Object[B].CalcNewPosY
End Method
or?:
Method TestOponent()
Object[B].CalcNewPos(xpos,ypos)'by reference'
End Method
?
and if B needs his own next position, can it use the same method?
It still seems a bit like "OverCoding" to me, but I probably messed up and my head hurts already; so there you have it...


H&K(Posted 2006) [#31]
Honestly abomination, there is no reason at all why the code inside the type has to be any different in any fundimental way than when its outside the type.

HOWEVER. It is clear from the way that Objects are described by you at the moment, that you still "Proceduraly" describing the main flow of your program. This is not a bad thing, as OOP doesnt noramly give faster code, and I dont oop nearly as much as I recomend, for the same overcodeing reasons as you've given

The reason I therefore continue to express the belief that you should Type them, is that the the fundimental question you expressed in the first post, is crying out for Types.