Naked parameter.action anomalous behavior

Two odd things with parameter.action at global level. First, given this in project CUbugMain:

-- CUbugMain

function setup()
    print("Hello World!")
end

function draw()
end

parameter.action("main", function()
    print("main")
end)

Pressing the button gets

attempt to call table value

With empty trace back. Given a reference to project CUbug containing:

CodeaUnit = class()

_ = CodeaUnit()

parameter.action("CodeaUnit Runner", function()
    print("runner")
end)

Two buttons appear but the main button prints “runner” and the runner button prints “main”.

Most peculiar. :slight_smile:

Deleted

@RonJeffries What happens if you put the parameter.action code inside functions. Put the “main” one in setup() and I’m not sure about the “CodeaUnit Runner”. Maybe stick that one in setup() also.

All the things i’ve tried inside seem to work. I’ve seen some odd things only when they’re at top level. The idea withnthe testing framework is to require no changes to the app code.

Can setup appear in any tab? There’s always a testing tab somewhere …

@RonJeffries setup() is supposed to be the first function executed. I would say it can be anywhere and Codea will know where it’s at.

I was thinking about having more than one. Some way to get the test button up w/o taking over the function of main.

You’ll only have one. If you create 10 functions with the same name that does 10 different things, the last of those 10 functions read will be the one that’s used. That’s like assigning a variable with 10 different values. The variable will have the last value assigned to it. The same goes for functions. You can assign different code to a function name, but the function will have the last code assigned to it.

Yep. So only way I can see for a thing like CodeaUnit to sneak a test button in is for that trick to work again.

If you want to have multiple functions with the same name, stick them in different tabs. Then depending on which function you want to use, switch the tab order so the tab with the function you want to use comes after the one you don’t want to use.

Something I just found out. If you have a lot of global parameter.action statements, the first action takes the function of the second action. The second action takes the function of the first action. The third thru the next to the last action works OK. The last action causes an error. If you put all of them in setup(), they all work OK.

Yes. I’ve seen similar. I think it’s not quite that regular but may be. I think it’s a bug and I think it wasn’t always there. Something inited wrongly, perhaps?

@RonJeffries I don’t see a big problem with the parameters. The parameter statements should be put inside a function, either in setup() or some other function instead of being defined as global. I don’t see a purpose of global parameters as opposed to putting them in setup() or another function. They may have worked in the past, but in one of the updates something changed and I don’t know if TLL would fix it.

The reason it’s useful is that one wants one’s tests and one’s code to be entirely separate. So with CodeaUnit, for example, you have your app’s main program and classes, you have a separate set of tabs with tests, which are referenced in during development, and the framework, CodeaUnit, also referenced in. The framework pops a test-running button into the UI. When testing’s done, you just unreference the tests and framework, and what’s left is the production code ready to ship without modification.

This is quite clean, and just how it “should” be. It would be a shame, albeit a small one, to lose that.

A bigger concern might be that this is the tip of the iceberg, and that there are other things that don’t work with top-level code, which as far as i can tell, is a legal Lua concept. That, only our TLL overlords can tell us. I, for one, welcome them.

It occurs to me that maybe there should be some defined “hook” that could be used in general to allow classes and tabs to get an initialization call. Imagine, for example, that all functions named setup were guaranteed to be called before things start off. Might be very useful.

@RonJeffries When I was working, I used to write code that ran POS (point of sale) terminals. There were 7 different POS terminals depending on which company division used them. Each of those 7 terminal types had different displays and different keyboards. I had one program and where the code needed to be different for a specific terminal, it was enclosed within a #ifdef. To create code for each of the different terminals, I changed the value of the #ifdef and compiled it. I don’t see why you can’t do the same for your production and test code. Enclose your code that’s either test or production within an if statement and have a variable called testing that’s set to either true or false. If testing only your test parameters/code runs or else your production parameters/code runs. Your parameters can be in either a testing function or a production function eliminating the global parameters.

Can do. I surely know a few ways to do it. Not contaminating the source, and especially not the running code, is nice. I might gin up a thing with a global table where folks register for an init, if I were doing this in anger.