Page 1 of 2
ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 3:00 pm
by charvista
Returning more than one value can be very handy.
I saw in another programming language this code:
Code: Select all
def Geo::dec2dms(dec)
s = dec * 3600
d = (s / 3600).floor
s -= d * 3600
m = (s / 60).floor
s -= m * 60
return d, m, s
end
Can this be implemented in PureBasic too?
Thanks for thinking about that...
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 3:25 pm
by c4s
I know this could be annoying but try using an structure for that.
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 3:36 pm
by TomS
c4s wrote:I know this could be annoying but try using an structure for that.
How?
Code: Select all
Structure myStruct
minutes.i
hours.i
EndStructure
Procedure bla(a,b)
Protected time.myStruct
time\hours = a
time\minutes = b
ProcedureReturn time
EndProcedure
Debug bla\minutes ; Error in this line
=> The variable has a structure
Code: Select all
Structure myStruct
minutes.i
hours.i
EndStructure
Procedure.myStruct bla(a,b) ; Error in this line
Protected time.myStruct
time\hours = a
time\minutes = b
ProcedureReturn time
EndProcedure
Debug bla\minutes
=> A structure can't be used with ProcedureReturn
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 3:39 pm
by Fred
Try this (not tested):
Code: Select all
Structure myStruct
minutes.i
hours.i
EndStructure
Procedure bla(a,b, *result.myStruct)
*result\hours = a
*result\minutes = b
EndProcedure
bla(10, 20, @minutes.myStruct)
Debug minutes\hours
Debug minutes\minutes
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 3:59 pm
by TomS
Thank you.
I know this method and similar ones, but it's just not like PB. It looks more like C++
But it's an OK workaround, I guess.
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 4:12 pm
by blueznl
Fred, as you're reading this topic anyway

...
Would there ever be a change of procedures returning structures, or procedures returning multiple variables? It would be a great enhancement to the language, and clearly distinguish it from its lesser brethern

Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 5:14 pm
by Little John
I just want to mention that it's also possible for a procedure, to return a pointer to a static structure inside the procedure. Here is a modification of Fred's example:
Code: Select all
Structure myStruct
hours.i
minutes.i
EndStructure
Procedure bla (a, b)
Static result.myStruct
result\hours = a
result\minutes = b
ProcedureReturn @result
EndProcedure
Define *time.MyStruct
*time = bla(10, 20)
Debug *time\hours
Debug *time\minutes
Regards, Little John
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 5:45 pm
by TomS
It has to be static. I don't know why, but otherwise I get a very high number (unknowing me guesses it is the pointer address?) and 0 as debugger-ouput.
But since a pointer to the static content is returned, every call of the procedure overrides everything, and every pointer is the same after all.
Code: Select all
Structure myStruct
hours.i
minutes.i
EndStructure
Procedure bla (a, b)
Static result.myStruct
result\hours = a
result\minutes = b
ProcedureReturn @result
EndProcedure
Define *time.MyStruct
*time = bla(10, 20)
*blub = bla(13,30)
Debug *time\hours ;With normal returns this would still be 10, but it is 13 now.
Debug *time\minutes
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 5:54 pm
by Little John
TomS wrote:It has to be static.
Yes, I did write that. (Global or Shared would work as well.)
A local variable in a procedure does not exist anymore after the procedure has finished.
Regards, Little John
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 5:58 pm
by charvista
We can also do it by adding the needed pointers-variables as parameters:
Code: Select all
Procedure.d zDec2Dms(Dec.d,*D.integer,*M.integer,*S.integer)
Seconds.d=Dec*3600
Degrees.d=Int(Seconds/3600)
Seconds-Degrees*3600
Minutes.i=Int(Seconds/60)
Seconds-Minutes*60
*D\i=Int(Degrees)
*M\i=Int(Minutes)
*S\i=Int(Seconds)
EndProcedure
However, my wish here is just about returning more than one variable from a simple procedure without complications like pointers, structures,....
so I could export D, M, S easily.
I see that Blueznl is seconding this wish. (thanks!)
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 5:59 pm
by TomS
Little John wrote:A local variable in a procedure does not exist anymore after the procedure has finished.
Thus the feature request for structured returns
I was aware of that method, too, but I dumped it, since it is only useful for one-time-calls like InitMyFramework().
Though Init-Functions mostly (always?) return only True or False or maybe ID or False^^
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 6:10 pm
by DarkDragon
Little John wrote:TomS wrote:It has to be static.
Yes, I did write that. (Global or Shared would work as well.)
But you should also mention that this is not threadsafe. For threadsafety you can use this:
Code: Select all
Structure TheStructure
a.i
b.i
c.i
EndStructure
Procedure.i ThreadSafeMultiReturn()
Protected *Result.TheStructure
*Result = AllocateMemory(SizeOf(TheStructure))
If *Result
*Result\a = 10
*Result\b = 20
*Result\c = 30
ProcedureReturn *Result
EndIf
Debug "Not enough memory?"
ProcedureReturn #Null
EndProcedure
*Result.TheStructure = ThreadSafeMultiReturn()
If *Result <> #Null
Debug *Result\a
Debug *Result\b
Debug *Result\c
FreeMemory(*Result)
EndIf
[EDIT]
Or use the new Threaded keyword.
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 6:11 pm
by TomS
Ok.
Some people want this feature in everyday coding, which is fine. I'd like that too.
Others want to offer includes with commands that 'feel' like native PB-Commands.
If somebody is looking for that, here is what I do.
I use a global array for my objects.
Code: Select all
Structure Object
size.i
state.i
EndStructure
Global Dim id.Object(1)
Procedure CreateObject(size.i, state.i)
Protected count.i = ArraySize(id())-1
id(count)\size = size
id(count)\state = state
ReDim id(ArraySize(id())+1)
ProcedureReturn count
EndProcedure
Procedure SetObjectState(state.i, id.i)
id(id)\state = state
EndProcedure
Procedure GetObjectState(id.i)
ProcedureReturn id(id)\state
EndProcedure
c = CreateObject(1, 2)
d = CreateObject(1, 4)
SetObjectState(78, d)
Debug GetObjectState(c)
Debug GetObjectState(d)
End
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 6:15 pm
by DarkDragon
An example with "Threaded" keyword for threadsafety:
Code: Select all
Structure TheStructure
a.i
b.i
c.i
EndStructure
Threaded Result.TheStructure
Procedure.i ThreadSafeMultiReturn()
Result\a = 10
Result\b = 20
Result\c = 30
ProcedureReturn @Result
EndProcedure
*Result.TheStructure = ThreadSafeMultiReturn()
If *Result
Debug Result\a
Debug Result\b
Debug Result\c
Else
Debug "Failed?"
EndIf
But notice that you can't call ThreadSafeMultiReturn a second time inside the same Thread without loosing the old result and its just leading to bugs if you return the pointer as you might not remember the first part of my sentence.
Re: ProcedureReturn returning more than one value
Posted: Tue Aug 31, 2010 7:20 pm
by jamirokwai
charvista wrote:Returning more than one value can be very handy.
I saw in another programming language this code:
Code: Select all
def Geo::dec2dms(dec)
s = dec * 3600
d = (s / 3600).floor
s -= d * 3600
m = (s / 60).floor
s -= m * 60
return d, m, s
end
Can this be implemented in PureBasic too?
Thanks for thinking about that...
Would be great to have a ProcedureReturn with multiple values
I encountered a problem, where I like to have a String and two Integers given back from a function.
My approach was to use String + "|" + Str(i1) + "|" + Str(i2) and to use StringField to get back the info.
But you couldn't use this when your need Full Speed... :-O
Maybe like this!? Would be a great enhancement!!!
Procedure xyz(a,b,c)
return a,b,c
EndProcedure
(x,y,z) = xyz(a,b,c)