This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
DARKHAWX's profile picture

Executing a function that is saved as a variable

Started by DARKHAWX, 21 September 2015 - 11:00 AM
DARKHAWX #1
Posted 21 September 2015 - 01:00 PM
Hi so I'm having a bit of trouble with creating working buttons. My main problem is how to assign, and later execute, a function to each button (the function in this case is getInfo(), which takes 2 parameters). With my current code it will return an error when the line
buttons[name]["funcF"]
gets called; asking for an equals sign since it thinks that I want to assign a value to buttons[name]["funcF"] (I understand why this is happening).

Does anyone know the proper syntax for this? I just need it so when I call
buttons[name]["funcF"]
it will run
getInfo("reactorComp", "turnOff")
, etc (there will be numerous different buttons with different functions, so the code should be generalised).


Relevant Code:

----- Relevant Code -----
-- Buttons
buttons = {}
buttons["reactorToggle"] = {funcF = getInfo("reactorComp", "turnOff"), funcT = getInfo("reactorComp", "turnOn")}

-- Called when the monitor is clicked, used to check if a button is pressed, and if so execute the relative function
function checkButtons(x, y)
  for name, temp in pairs(buttons) do
	local button = buttons[name]
	if button["active"] == true and y == button["yPos"] then
	  if x >= button["xPos"] and x <= button["xPos"] + math.floor(button["width"]/2) then
		buttons[name]["funcF"] -- error
	  elseif x >= (button["xPos"] + math.ceil(button["width"]/2)) and x <= (button["xPos"] + button["width"]) then
		buttons[name]["funcT"]
	  end
	end
  end
end

-- Calling the creation of the button
displayButton("reactorToggle", "On", "Off", getInfo("reactorComp", "checkPower")[3], 3 + 3*percentBarLength/4 + 3, 5, 7)

----- Semi Relevant Code -----
function displayButton(name, textT, textF, state --[[T/F]], x, y, width)
  buttons[name] = {active = true, xPos = x, yPos = y, width = width}
  if state == true then
	monitor.setBackgroundColor(colors.black)
	monitor.setTextColor(colors.white)
  else
	monitor.setBackgroundColor(colors.red)
	monitor.setTextColor(colors.white)
  end
  monitor.setCursorPos(x, y)
  mWrite(textF..string.rep(" ", math.floor(width/2) - string.len(textF)))

  monitor.setBackgroundColor(colors.black)
  mWrite(" ")
  if state == true then
	monitor.setBackgroundColor(colors.green)
	monitor.setTextColor(colors.white)
  else
	monitor.setBackgroundColor(colors.black)
	monitor.setTextColor(colors.white)
  end
  mWrite(textT..string.rep(" ", width/2 - string.len(textT)))
end

Thanks in advance.
Edited on 21 September 2015 - 11:01 AM
KingofGamesYami #2
Posted 21 September 2015 - 01:31 PM
buttons[ name ][ "FuncF" ] is a function pointer. To call a function in any variable, you use ().


buttons[ name ][ "FuncF" ]() --#calls it
buttons[ name ].FuncF() --#also calls it
local f = buttons[ name ][ "FuncF" ] --#puts it in another variable
f() --#also calls it
Edited on 21 September 2015 - 11:31 AM
DARKHAWX #3
Posted 21 September 2015 - 01:45 PM
buttons[ name ][ "FuncF" ] is a function pointer. To call a function in any variable, you use ().

-snip-

Interesting, I swear I tried using that… maybe I just had my variables messed up when I did…
valithor #4
Posted 21 September 2015 - 02:19 PM
buttons[ name ][ "FuncF" ] is a function pointer. To call a function in any variable, you use ().

-snip-

Interesting, I swear I tried using that… maybe I just had my variables messed up when I did…

Due to the way you define the table and more specifically the functions in the table, is why it did not work. When you define the table you are actually calling the function and setting funcF and FuncT to what these functions return. So as King said, that is how you should call them, but in order for it to function how you want, you would also need to define the functions like the following if you want it to call them without having to manually pass the arguments.


buttons["reactorToggle"] = {funcF = function() getInfo("reactorComp", "turnOff") end, function() funcT = getInfo("reactorComp", "turnOn") end}
Edited on 21 September 2015 - 12:24 PM
DARKHAWX #5
Posted 21 September 2015 - 11:29 PM
Due to the way you define the table and more specifically the functions in the table, is why it did not work. When you define the table you are actually calling the function and setting funcF and FuncT to what these functions return. So as King said, that is how you should call them, but in order for it to function how you want, you would also need to define the functions like the following if you want it to call them without having to manually pass the arguments.


buttons["reactorToggle"] = {funcF = function() getInfo("reactorComp", "turnOff") end, function() funcT = getInfo("reactorComp", "turnOn") end}

Interesting. I tried doing the way you have, but this doesn't work either… just says "attempt to call nil" whenever the line
buttons[name]["funcT"]()
is called…
I changed the buttons["reactorToggle"] to exactly the code you have, but this doesn't work… I have also tried formatting it like
buttons[name].funcT()
but to no avail…

What am I doing wrong here? If need be I can upload the entire code to pastebin.

Just a thought, but would the order I put these in have any effect? Right now the getInfo() gets created, then the checkButtons() and then afterwards the buttons variable gets created. Then there is the while loop for getting when a player clicks the monitor, which then executes the checkButtons() code…
Bomb Bloke #6
Posted 21 September 2015 - 11:42 PM
Can't say I've reviewed the whole script, but I see a little typo in valithor's line that'd lead to that error:

buttons["reactorToggle"] = {funcF = function() getInfo("reactorComp", "turnOff") end, funcT = function() getInfo("reactorComp", "turnOn") end}
DARKHAWX #7
Posted 22 September 2015 - 03:07 AM
Can't say I've reviewed the whole script, but I see a little typo in valithor's line that'd lead to that error:

buttons["reactorToggle"] = {funcF = function() getInfo("reactorComp", "turnOff") end, funcT = function() getInfo("reactorComp", "turnOn") end}

Still not working, even after changing that… Still saying "attempt to call nil". So I'm really confused, because as far as I can see everything exists… I get the feeling that its probably the order I have everything in, or because some variable is local/not local or something.

Here is the full code (most of which doesn't matter atm): http://pastebin.com/cmLbdcv0
TYKUHN2 #8
Posted 22 September 2015 - 03:43 AM
Where is the error? Should be something like :scriptName:lineNumber Error (Though I cannot remember off the top of my head, I have been working with other stuff lately)

Extraneous informationTechnically a function IS a variable. :)/>
DARKHAWX #9
Posted 22 September 2015 - 03:54 AM
Where is the error? Should be something like :scriptName:lineNumber Error (Though I cannot remember off the top of my head, I have been working with other stuff lately)

Extraneous informationTechnically a function IS a variable. :)/>
Its a line 140 and 142, when I attempt to run the function that is stored in the variable…
TYKUHN2 #10
Posted 22 September 2015 - 03:55 AM
No attempt to call nil here. Only hundreds upon hundreds of replacing Montior with Term because CCEmuRedux and non-functioning buttons (probably becuase I am clicking a terminal)
Edited on 22 September 2015 - 02:01 AM
DARKHAWX #11
Posted 22 September 2015 - 09:59 AM
No attempt to call nil here. Only hundreds upon hundreds of replacing Montior with Term because CCEmuRedux and non-functioning buttons (probably becuase I am clicking a terminal)
Huh?
I don't understand. I have working buttons that are hardcoded in, but I'm trying to make a working function that will create buttons for me, rather than having to hardcode them…
Edited on 22 September 2015 - 10:17 PM
TYKUHN2 #12
Posted 23 September 2015 - 12:17 AM
Huh?

Sorry for some reason forums hate me and didn't update correctly so I didn't see your error lines for a while.

As for my post about not having issues, it's becuase the function isn't called until I click, which technically I cannot do.

Maybe it is ran? I'll boot up minecraft real fast and check.
Edited on 22 September 2015 - 10:21 PM
TYKUHN2 #13
Posted 23 September 2015 - 12:39 AM
What is the monitor size intended to be? It throws a negative array error because apparently mine is too small.
DARKHAWX #14
Posted 23 September 2015 - 02:33 AM
What is the monitor size intended to be? It throws a negative array error because apparently mine is too small.
Mine is currently 6 wide and 3 tall…
Edited on 23 September 2015 - 12:34 AM
TYKUHN2 #15
Posted 23 September 2015 - 08:45 PM
Mine is currently 6 wide and 3 tall…

Sorry this is taking a while. I am having to break your code to get it to work in my enviroment. Also I havn't used rednet in a while.
TYKUHN2 #16
Posted 23 September 2015 - 09:14 PM
It is printing the weirdest things to the terminal so be careful when I give you a possible solution, your reactor *MIGHT* explode.
TYKUHN2 #17
Posted 23 September 2015 - 09:59 PM
buttons[name][funcF]
and
buttons[name][funcT]
are nil

buttons[name]["reactorToggle"][funcT]
buttons[name]["reactorToggle"][funcT]
Are the functions your looking for. Again there IS weirdness so be careful.

P.S. Sorry it took so long for something so simple. I had to brutalize your code to get it to work. That and relearning the Rednet API
Edited on 23 September 2015 - 08:00 PM
valithor #18
Posted 23 September 2015 - 11:13 PM
buttons[name][funcF]
and
buttons[name][funcT]
are nil

buttons[name]["reactorToggle"][funcT]
buttons[name]["reactorToggle"][funcT]
Are the functions your looking for. Again there IS weirdness so be careful.

P.S. Sorry it took so long for something so simple. I had to brutalize your code to get it to work. That and relearning the Rednet API

Where is it actually calling that exactly? Unless if i am misreading the function calls at lines 140 and 142 they are:

buttons[name]["tFunc"]()
buttons[name]["fFunc"]()


nvm lol… misread what you said

Since you already have it all set up could you do a few tests for me?

What does V return

print(type(buttons[name]["tFunc"]))
print(type(buttons[name]["fFunc"]))

And what does V print:

for k,v in pairs(buttons[name]) print(k) end
Edited on 23 September 2015 - 09:15 PM
TYKUHN2 #19
Posted 23 September 2015 - 11:19 PM
Valithor on what lines would you like me to inject them into? Right as they are called?

And I do not have it set up as I said in the solution. I actually deleted "reactorToggle" and put it on a higher level of the table, and I also had it reset everytime DisplayButtons() was called.
Edited on 23 September 2015 - 09:20 PM
valithor #20
Posted 23 September 2015 - 11:32 PM
Valithor on what lines would you like me to inject them into? Right as they are called?

And I do not have it set up as I said in the solution. I actually deleted "reactorToggle" and put it on a higher level of the table, and I also had it reset everytime DisplayButton() was called.

Yea I spent about 5 minutes following the order of everything that was called and it appears his problem is in his displayButton function. The displayButton function is overwriting his table (line 191), and deleting the two functions from the table.

Those two things would best be put on line 137 right after that for loop, although I doubt it is really necessary since now that I have fully read the code I have a pretty good assumption of what both will be.

Assumption:
first one will print nil on both (they are being deleted from the table because of displayButton function)
second one will print the things, which are added in the displayButton function

edit:

I might as well provide a solution…

I can think of one easy way to fix this and a few over complicated ones

The easiest way would be to simply change everything manually in the table, which needs to be changed instead of redefining the table itself.

  local updateTable = {active = true, xPos = x, yPos = y, width = width}
  for k,v in pairs(updateTable) do
	buttons[name][k] = v
  end
Note: I used another table and a for loop because I was too lazy to type out the four lines for changing the table manually, although it would be faster/more efficient that way.
Edited on 23 September 2015 - 11:54 PM
TYKUHN2 #21
Posted 24 September 2015 - 02:58 AM
I barely read the code, execpt the parts that didn't work without spoofing/minor editing.

But I fixed it by moving the definitions to

buttons[name] = {active = true, xPos = x, yPos = y, width = width, funcF = function () funcT = getInfo("reactorComp", "turnOff") end, funcT = function () funcT = getInfo("reactorComp", "turnOn") end}
valithor #22
Posted 24 September 2015 - 04:09 AM
I barely read the code, execpt the parts that didn't work without spoofing/minor editing.

But I fixed it by moving the definitions to

buttons[name] = {active = true, xPos = x, yPos = y, width = width, funcF = function () funcT = getInfo("reactorComp", "turnOff") end, funcT = function () funcT = getInfo("reactorComp", "turnOn") end}

The only problem is it is a button system, so each button (if he adds more) will do a different thing. If he only plans to have the one button then this will work.
TYKUHN2 #23
Posted 24 September 2015 - 04:15 AM
Passing variables about the table and handling them from the function itself would work… or just different function names.
valithor #24
Posted 24 September 2015 - 04:52 AM
Passing variables about the table and handling them from the function itself would work… or just different function names.

Those would fall under the overly complicated solutions I mentioned earlier :P/>