Introducing tparameter: parameters for any table

I Found a much simple solution wrt my previous post

  • define WFC = {} in the first tab, then
  • define local myclass = Class() WFC.myclass = myclass in other tabs.
    This way i will have only 1 global variable added by my whole lib. Great!
    [EDIT] havent read you last 2 posts: we were writing simultaneously.

I’ve read your last post (if it is still the last one :wink: ) : sure i am interested! However, my solution above looks really simple and it works, so i might stick to it.

Second thought about your import library:
I remember a post of @Andrew_Stacey where he explained he loaded everything, and then set to nil the libs he does not want. The garbage collector then removes the unwanted libraries. This is brilliant, because this way you do not have to manage explicitly the crosslinks between libs: only the libs really unused will be removed by the garbage collector. Brilliant.

Sure, but even better is to not compile and execute those things in the first place…then there’s nothing to collect :wink:

I was actually pondering a similar idea to @Andrew_Stacey’s to solve the “Codea loads everything” problem when the idea to wrap my tabs in a block comment hit me today. Here’s the basics of how it works:

I wrap my tabs in a block comment, so Codea ignores them when the program executes. Then, whenever I call import(‘tabname’), it loads the file, removes the wrapping block comment, and compiles it. Thus, we only ever load exactly what we need in the first place, and don’t have to churn the garbage collector creating (and then collecting) stuff we never needed (this whole thing is just a workaround of course…optional tab execution would eliminate this problem altogether, and I could just load the files with no special boilerplate). Also, my system memoizes the loaded module so that further calls to import() with the same file name simply return the already loaded module, instead of reloading and recompiling it each time. Furthermore, the (local) table that holds the loaded modules is a weak table, so if at some point in your program a module is not used anymore, it will be automatically garbage collected.

Anyway, there are other advantages to a good module system, but I’ll go into them more next week when I’m ready to show some code. A hacker’s gotta sleep once in awhile :slight_smile:

EDIT: @Jmv38 I was actually going to propose the idea of keeping your classes in a single global table, good on you for figuring that out! You’ve just implemented a simple module system :slight_smile:

@Andrew_Stacey You are correct about pretty much everything you said here regarding locals, globals, function calls, and speed. Forget I mentioned it please :slight_smile:

EDIT: Also, I’m not concerned with slowdown due to everything being loaded, I’m concerned with memory usage. If I have a game that has 50 large levels, each being a tab, each of those will always be loaded if I don’t take some sort of action. There’s a very real possibility of running out of memory.

Lua does allow nested block comments, if you do it the right way. You just can’t nest the same kind of block comment. For example:

-- this is fine:
--[[ --[=[ this is a nested comment --]=] --]]

-- and this is fine:
--[=[ --[[ this is a nested comment --]] --]=]

-- and this is fine:
--[===[ --[=[ this is a nested comment --]=] --]===]

-- but this is not fine:
--[[ --[[ this will not work --]] --]]

For flexibility, I’ve implemented it such that you can use whichever kind of block comment you want to wrap your file (the system figures out how many ‘=’ you used on the opening one, and finds the matching closing one).

Anyway, I’m not going to bother waiting…this is a work in progress, is quite ugly, and is unstable right now, but I want to post it to show the concepts and to solicit feedback, so here it is:

https://gist.github.com/apendley/5411561

Let me know what you think.

I didn’t know that about block comments - extremely useful.

In case it’s not clear, I agree with both that a module system is useful and that a system that makes it easy to do good practices is also useful.

(This local/global thing often catches me out. The two languages I program most in are Lua and TeX. In Lua everything is global unless explicitly declared otherwise. In TeX everything is local unless explicitly declared otherwise. You can see how I get confused! Especially when using luatex which combines the two.)

I’ll take a look at your code. I’m sure that there’s much I could learn from it.

@Andrew_Stacey: Actually cmodule addresses that as well…every module is loaded with it’s own table as it’s global environment, with a metatable indexing _G. This means that:

print(myVariable)

will print _G’s myVariable, but:

myVariable = 10

will actually set _M.myVariable (_M is the module’s environment table, analogous to _G, but for the module…see note at the bottom about _M). Btw, I totally copied the _M concept from Lua’s own module system…that’s probably the only thing I like about it.

You can however still set globals, you just have to qualify them:

_G.myVariable = 10

will do what you expect.

The downside of exposing _G via a metatable index is that real global variable lookups now gain the cost of a metatable lookup. This can be somewhat ameliorated by importing them into locals:

local print = print
local sprite = sprite

Of course, this is a good practice anyways as far as efficiency is concerned, so really I don’t view this drawback as being much of a drawback.

On _M: Incidentally, if your module doesn’t return anything, then cmodule returns the module table (_M) from import(), so every ‘global’ you exposed there is now accessible via the exported table. This idea was somewhat inspired by CommonJS.

Hi you two. Interesting discussing. However, i still favor the idea of loading everything, then letting the garbage collecTort reject what is not used. This manages the crosslinks for me, that saves my brain space (i dont hve too much of that) for other tasks. Of course the pitfall of memory explosion has to be avoided, if it appears to be a real problem. The other problem, the initial slow down, is probably not a major problem, because it occurs only once, on launch. The real slow down we must avoid are the reccurent ones, the fps-eaters.

Hi @toadkick. I am starting to work with your lib.
Many questions:
1/ last lines are:

-- export to global environment
_G.tparameter = tparameter

but line 710 you define tparameter = setmet...etc so why do need the last line? It is already there in _G?
2/ when i scroll the parameter windows, codea draw stops. I had not noticed that before. Is it codea or your code?

@Jvm38

  1. Actually if you look at the top of the file you’ll see that I’ve forward declared it as local.
  2. Yeah, that’s a codea thing unfortunately :frowning:

3/ I’ve seen you are pretty much 60 fps. However i dont like the accumulator. Do you think it is possible to isolate in one compact piece of code all the recurring actions & computations, so i can study exactly what is happening there (i am maniac on fps, sorry…). If not, i’ll have to go through all the code to track and understand them. And since Codea will,crash quite often, it is going to be painfull… (see next post)

4/ the tparameter tab is great. But the 900 lines crash my ipad1 codea from time to time. Is it possible to split it into tabs no longer than 300 lines? Of course keeping everything local and unexposed… :smiley: …if not i can live with it.

  1. No, I’m not going to refactor the code, sorry :frowning: You are stressing this way too much, the overhead from the timers used in tparameter is quite minimal. There are 3 timers that I use, only one of which fires every frame (the update timer, and only when the parameters window is open)…the other two are only ever active for 1 frame at a time (they are used as a workaround to avoid recursively creating the controls when parameter list changes). Furthermore, the timer update functions don’t even get called by tparameter’s update if the timers aren’t active.

  2. Also, no. You are the one who asked me to put it all in one file! :smiley:

Basically, I’m not going to touch this code again for awhile, except to fix bugs, and maybe add more examples. I want it to be stable for awhile so people might be more inclined to adopt it, and anyway I have like 3 other projects that I want to move onto for a little bit.

You are of course welcome to make any changes or improvements you like to the code, and if you do I will of course consider integrating them.

Ok. No problem. Your code is great as it is anyway. Since i really want to use your code i’m probably still going to ask lots of questions, if it is ok for you? Your code is very complex (for me, because there a lot of notions i dont master at all, metatables etc…), and will have to dig into it a little bit to feel where are the corners and the handles. Actually, if you are done with changes that’s even better: that way i can customize your code a little bit without having to keep up with updates. I’ll post the changes if they seem worth it. Thanks!

If i make changes i should make very clear where i do them. Do you recommand or wish some specific syntax to indicate my changes? (they should be very minor though)…

Hi. You say somewhere that :

Since you can’t really use Codea’s parameter class if you are using tparameter due to the way tparameter must frequently clear and reload the parameter list.

Can you comment a little bit more? This means i cannot at all use the std parameters function? Is there some changes i could make so that your lib adds your awsome tparameters without subtracting anything from Codea?

Hi. I have done some test with your lib, and i found a misunderstanding from myself: when you said you would make a parameter for local variables: i understood that you would do that without creating any global variables. This Is what i dont like about parameters., because that can pollute the name space and even kill others programs that would use the same global variable. But when i run your example, for instance Ellipse.x, i have the feeling that a global variable _Ellipse_x is created and passed to parameter.? is this correct?

@Jvm38: Please do ask me questions, I will be happy to explain anything about the code that you don’t understand :slight_smile: One of things that I really ended up liking about this project was the plethora of different Lua programming techniques and tricks, and there’s a few cool things going on in there.

As for changes, don’t worry about it trying to communicate them to me…I can just use a diff tool on my version and yours to see what’s changed.

@Jvm38: no, I have to use some global variables, since I’m piggybacking on Codea’s parameter system, and that’s all it allows. You really shouldn’t have to worry about polluting the global namespace…there should be very little chance those generated global variable names will clash with any of your variables. Also, those variables only exist while the parameter window is open…I remove them when it closes. Unless I want to write my own parameter controls and renderer (I don’t, not right now anyway), this is just gonna have to be the way it is.

Sorry @Jmv38, just saw your question about how the variables are mapped to globals, and you are correct, that’s how it works.

when you said you would make a parameter for local variables:

I never said that. I said I made a parameter that could work with any table.