Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / How to get multiple outputs from a function without using globals or arrays

Author
Message
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 8th May 2013 22:34 Edited at: 8th May 2013 23:04
I'm not sure if everyone knows this method or if it is a bad method, but it just occurred to me this week and I thought I'd share it.

With AppGameKit (and DBPro) we are limited to a single output variable from any user defined function. For the most part I've been working around this by using globals and arrays. This becomes quite sloppy very quickly.

So the other day I thought "why not stuff all o fthe variables I want to be output into a delimited string?"

Sure it takes a little bit of work to delimit the output, but it's not that bad AND it means I can have a recursive function with multiple outputs.

Here's a basic example:


While this example doesn't really illustrate the power of this, I hope that you can see the possibilities. You could have the function handle delimiting of the recursive parameters if you want and you can input an unlimited number of parameters as well as output an unlimited number of returns.

I know this is going to make my code a lot neater and more modular. I hope it helps someone else too!


EDIT:
Out of curiosity to see the impact of a large string on memory, and if there are any limits, I've been running a program for about an hour that simply continues to add a character to a string. So far I've not hit any limit and there is oddly no impact on the memory that the app is allocated in task manager. Just thought I'd share that.

Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 8th May 2013 23:35
Great idea, Naphier. I will start using this immediately!

Cheers

I never want what I know.
Marl
12
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 8th May 2013 23:47 Edited at: 8th May 2013 23:47
Strings are definitely the way to go,I've been using them for stuff like this since the introduction of the Tokenstring commands

And I've yet to hit a limit on the amount of stuff you can pack in there.

One thing I've not tried is comparing access times to that of arrays of strings.
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 9th May 2013 00:03
What you now need are built in commands that will break up the string into an array, using the same token delimiter.

I would suggest a function, but then you cannot return an array from a function. If you could, then you wouldn't need to use this nice, neat solution.

Of course, if they ever fix the issue with returning UDTs from a function, than that could be used.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 9th May 2013 00:09
why not use user defined types and a global variable of them?
i saw it can be used as func. return type but the result must be hold in a global var.
(ohh, i like the lua script from shiva engine, there you can define
more than one return value.)
basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 9th May 2013 01:01
there are many ways to get multiple output, I believe the best one is to put the resulted variables in a memblock. this will be much faster yet using string maybe more comfortable to implement.

JimHawkins
14
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 9th May 2013 01:15
If you passed the index into an array of UDTs you could as many results as you like in.

-- Jim DO IT FASTER, EASIER AND BETTER WITH AppGameKit FOR PASCAL
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 9th May 2013 02:30
Memblock's a good idea too.
A couple of you are missing half of the point.
To increase modularity it is generally not a good idea to rely on globals (and arrays, which are global). There's a ton of reasons for this, but I don't have the time to defend the point right now.

As my original post states, I already understood how to pass values into arrays and globals... UDTs would be equally cumbersome after 30+ functions with multiple outputs.

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 9th May 2013 02:53
Quote: "To increase modularity it is generally not a good idea to rely on globals (and arrays, which are global). There's a ton of reasons for this, but I don't have the time to defend the point right now."


So you'd rather use the inefficiency of have to parse a string every time?

I think the best method is really going to depend on your parameters and what data you need returned.

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 9th May 2013 04:45
I agree, the best method does depend on what parameters and returns are needed. This is probably best for just a couple of outputs and very handy for recursive functions. this wouldn't be very efficient for many outputs that need to be procedurally accessed. That's what arrays are for.

I would definitely rather have very modular code over the inefficiency of parsing relatively short strings. I just parsed a 70,000 character string to get a value near the end and it took 1 millisecond. I think most modern computers can handle parsing strings with great efficiency. Since I doubt I'll use this method on a very large string I'm not overly worried about it.

I'm much more worried about being able to develop complex code where I can easily track bugs and make substantial changes without having to track where I've used globals.

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 9th May 2013 04:53
Quote: " I just parsed a 70,000 character string to get a value near the end and it took 1 millisecond."


Much quicker than I'd expect.

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 9th May 2013 04:54
Yeah actually I figured it would take SOME time, but nothing.
I bet on Android it takes a bit more, but even if it is 100 times more it doesn't matter with smaller strings.

Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 9th May 2013 09:29
have you an example of variables+values what you need to return from a function?
haliop
User Banned
Posted: 9th May 2013 12:21
Naphier GREAT WORK!
simple and amazing. good thinking i was wondering myself about it..

baxslash
Valued Member
Bronze Codemaster
17
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 9th May 2013 15:26
Aren't you just over complicating things though? Why not use UDTs or globals? It's a clever way around a problem but it's more complicated than just using a global variable or an array which are the existing ways around the same problem.

What exactly is wrong with using an array or UDT? They can contain as much data as you like.


this.mess = abs(sin(times#))
Van B
Moderator
21
Years of Service
User Offline
Joined: 8th Oct 2002
Location: Sunnyvale
Posted: 9th May 2013 16:18
It could be handy for scripting as well. Like, if your adding tokenizing, why not add basic scripting as well.

I tend to seperate values by ( , and =

So I can parse a script file like:

health=10
anim(1,2,3,4,5)

Then the first string is checked and the 2nd 3rd etc strings are parameters. Just thinking that you might as well use tokenizing to make your life easier wherever you can - there's no point in inventing the perfect mouse trap just to catch 1 mouse

I got a fever, and the only prescription, is more memes.
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 9th May 2013 17:18
@baxslash - It's just a tad more complicated than using globals/arrays/UDTs, but the point of using it is to increase the level of modularity of the program.

I don't have enough computer science background to effectively defend its usage, but I do see its value. Of course there are times when an array is more efficient, but this helps cut down on those. This argument is quite similar to not using subs or gotos. Everything has its place and some things should be avoided to achieve specific results (easier to understand and more modular code).

Here's some more reading on reasons not to use globals (which includes arrays in AGK).
http://c2.com/cgi/wiki?GlobalVariablesAreBad

@Van B - I use something similar to that when reading my files for my chat program.

@Markus - If the example in the first post isn't enough, then wait a few days and look on the snippets forum for me to announce an update to my chat program. It'll have a few more examples in there.

baxslash
Valued Member
Bronze Codemaster
17
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 9th May 2013 18:31
I understand you wanting to keep things modular and I also understand why globals are not the ideal solution but passing a UDT out is equally modular. Try this example, it uses a locally created variable (UDT) which is passed out and not global at all:



this.mess = abs(sin(times#))
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 9th May 2013 18:34
So, that now works? I guess that is one of the quiet fixes.

I remember this as an issue in v1076 that caused me a lot of grief because I couldn't get it to work.

Moot point for me now, since I flipped to Tier 2.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Marl
12
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 9th May 2013 19:32 Edited at: 9th May 2013 20:06
Strings allow the ability to have a variable number of parameters passed to and from functions, something which UDTs could not address in their current form.

I have such a function to creates sprites, which uses parameters such as "X:100,Y:100,W:240,H:240,D:50,I:400,F:25". It uses only what is passed to it, but allows all the sprite parameters to be set in one call.

It uses the select / case structure so additional parameters are easy to add.

Quote: "Aren't you just over complicating things though? "

There is obviously no point for a lot of functions but such as the example with sprite make it worthwhile as sprites require more parameters than can be passed in a single conventional call.

It's just another option which can be used when needed.

Edit: then/than Typo
baxslash
Valued Member
Bronze Codemaster
17
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 9th May 2013 19:41
I agree it's certainly more flexible than the current set up. I just think it's worth making sure people are aware of what AppGameKit can do to address this as well. It's certainly an option I had never considered.


this.mess = abs(sin(times#))
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 10th May 2013 02:58 Edited at: 10th May 2013 05:33
Here is a colorpicker using this Idea.



I never want what I know.
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 10th May 2013 09:06 Edited at: 10th May 2013 09:06
@Timshark
ok, but also you can get the rgba as 4 Bytes integer/return and later mask the r g b a values.
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 10th May 2013 13:59
Markus, show me - I want to learn.

I never want what I know.
Van B
Moderator
21
Years of Service
User Offline
Joined: 8th Oct 2002
Location: Sunnyvale
Posted: 10th May 2013 14:27
Isn't there a command that returns a pixel colour from a sprite at a specified XY location?

Not that Tim shouldn't do his own of course - but it might be worth doing a speed comparison between the methods.

I got a fever, and the only prescription, is more memes.
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 10th May 2013 14:32 Edited at: 10th May 2013 14:34
Van B, I'm all for speed.
But then you have to be sure there actually is a sprite there (like a color wheel, of course).

But I've sidetracked this thread a little, though. Sorry

I never want what I know.
baxslash
Valued Member
Bronze Codemaster
17
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 10th May 2013 14:32
No, but you could easily get that using GetSpriteXFromPixel( iSpriteIndex, x ) and it's Y counterpart then using Timsharks method to get the colour "on screen" at that point. It won't work if something's in the way though...


this.mess = abs(sin(times#))
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 10th May 2013 14:50
@Timshark
like that:
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 10th May 2013 16:53 Edited at: 10th May 2013 17:10
@Markus
But that needs 3 output variables divided by 3 functions...

I never want what I know.
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 10th May 2013 19:49
@Timshark
no, color is 4 byte integer (rgba),
you can read integer from memblocks too.
this is shorter:
Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 10th May 2013 20:16
Woh woh woh, wait a second.... We can return UDTs from functions now?! I have code to go clean up!

"You're all wrong. You're all idiots." ~Fluffy Rabbit
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 10th May 2013 21:23
Phaelax, try a couple of simple tests before you redo stuff.

This is something that hadn't been working in v1.76.

But they very well may have fixed it for v10811.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 11th May 2013 05:09 Edited at: 11th May 2013 05:10
@Markus
You're not showing me how to return these variables back from a single function. That was the point of naphiers creative workaround. To return multiple values from a single function...

I never want what I know.
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 11th May 2013 09:50 Edited at: 11th May 2013 10:24
@Timshark
in your colorpick example you can return 4 bytes in one integer.
its similar as the string with includes chars.
(in the memblock is a color value always 32 bit.)
i am sure naphiers suggestion is useful in some way.

@Phaelax
a simple test works.
JimHawkins
14
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 11th May 2013 11:06
One the few languages that will do this is Lua:

http://www.lua.org/pil/5.1.html

Normally, in say Pascal, you would use call-by-reference:



Although this only returns true or false, the values of x and y are increased by the amount in int, which cannot be changed by the function because it is copied (call by value).

Unfortunately, AppGameKit Basic does not have call by reference.

-- Jim DO IT FASTER, EASIER AND BETTER WITH AppGameKit FOR PASCAL
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 11th May 2013 11:57
@JimHawkins
i agree,byref will be very useful, also for user defined types.
JimHawkins
14
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 11th May 2013 13:45
I've said several times that Lua would be the salvation of AppGameKit Basic. Putting all your program logic into Lua files means you can use different front-ends for the graphics etc. It's powerful, small, fast, free and cross-platform.

-- Jim DO IT FASTER, EASIER AND BETTER WITH AppGameKit FOR PASCAL
MikeMax
AGK Academic Backer
12
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 11th May 2013 15:50
Quote: "Phaelax, try a couple of simple tests before you redo stuff.

This is something that hadn't been working in v1.76.

But they very well may have fixed it for v10811."


Yes .. Returning an UDT is OK now.

But i've not verified that using an UDT through 2 functions is working in beta 11 (didn't works in beta 10) : https://code.google.com/p/agk/issues/detail?id=449#c3
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 11th May 2013 16:17
@Markus
Ok. I'm not comfortable yet when it comes to math operations on bit numbers. Can you please show a stupid potato how to add those bytes together and then take them apart again to make 4 separate red,green,blue,alpha values?
Then I promise I will shut up

I never want what I know.
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 11th May 2013 18:23
@Timshark
this way, the other i show before without alpha.


@MikeMax
hm, don't work with b11 :-(
Timshark
16
Years of Service
User Offline
Joined: 30th Jun 2007
Location: Oslo, Norway
Posted: 11th May 2013 18:36 Edited at: 11th May 2013 18:39
@Markus
I must be really dim but how do you split the returned Color=GetColor(r,g,b,a) into 4 different values again...

That was the whole point of my pickcolor snippet. To return 1 variable that could be used.

I never want what I know.

Login to post a reply

Server time is: 2024-05-07 04:01:24
Your offset time is: 2024-05-07 04:01:24