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

Repeating a function every minute

Started by xWizz, 19 October 2013 - 11:42 AM
xWizz #1
Posted 19 October 2013 - 01:42 PM
Hi, I have a question that I can't find the answer to. I want to make a program which repeats the same function (In my case saying something through a speaker) every minute or so. Now my question is: How could I do that? (If it's possible to do) I have searched but not found answers yet. If someone would put the lines that are necessary I would be very grateful.

I also don't know a lot about lua so excuse me if I don't understand something.

Greetings
Lyqyd #2
Posted 19 October 2013 - 09:06 PM
Split into new topic.

You might look into while loops and use sleep(60) in the loop.
jay5476 #3
Posted 20 October 2013 - 02:48 AM
try learning a bit more the reference manual and PIL are great but here's a piece of code you can use

function functionThatsRun()
--code you want to repeat here
print("it has been 60 seconds")
end
while true do
functionThatsRun()
sleep(60)
end
alakazard12 #4
Posted 20 October 2013 - 01:16 PM
try learning a bit more the reference manual and PIL are great but here's a piece of code you can use

function functionThatsRun()
--code you want to repeat here
print("it has been 60 seconds")
end
while true do
functionThatsRun()
sleep(60)
end

And if you want to also run something else at the same time, you can do something like this:

function functionThatsRun()
  -- code you want to repeat here
  print("it has been 60 seconds")
end

function functionThatKeepsRunning()
  -- Your code
  print("I'm also running")
end

local function F1()
  while true do
    functionThatsRun()
    sleep(60)
  end
end

parallel.waitForAll(F1, functionThatKeepsRunning)

theoriginalbit #5
Posted 20 October 2013 - 04:08 PM
And if you want to also run something else at the same time, you can do something like this:

function functionThatsRun()
--code you want to repeat here
print("it has been 60 seconds")
end

function functionThatKeepsRunning()
-- Your code
print("I'm also running")
end

local function F1()
while true do
functionThatsRun()
sleep(60)
end
end

parallel.waitForAll(F1, functionThatRuns)
I believe you meant

function functionThatsRun()
  --# code you want to repeat here
  print("it has been 60 seconds")
end

function functionThatKeepsRunning()
  --# Your code
  print("I'm also running")
end

local function F1()
  while true do
    functionThatsRun()
    sleep(60)
  end
end

parallel.waitForAll(F1, functionThatKeepsRunning)
xWizz #6
Posted 20 October 2013 - 04:31 PM
Thanks guys!

I really want to learn coding but I'm completely new to it and English isn't my main language so It's sometimes hard to understand something.
ATMunn #7
Posted 20 October 2013 - 05:24 PM
try learning a bit more the reference manual and PIL are great but here's a piece of code you can use
 function functionThatsRun() --code you want to repeat here print("it has been 60 seconds") end while true do functionThatsRun() sleep(60) end 
And if you want to also run something else at the same time, you can do something like this:
 function functionThatsRun() --code you want to repeat here print("it has been 60 seconds") end function functionThatKeepsRunning() -- Your code print("I'm also running") end local function F1() while true do functionThatsRun() sleep(60) end end parallel.waitForAll(F1, functionThatRuns) 

Those are great examples.
awsmazinggenius #8
Posted 20 October 2013 - 11:04 PM
Scrolled to bottom immediately, so sorry if this was already answered.

while true do
  function_you_want_to_repeat()
  sleep(60)
end
theoriginalbit #9
Posted 21 October 2013 - 02:33 AM
Scrolled to bottom immediately, so sorry if this was already answered.

while true do
  function_you_want_to_repeat()
  sleep(60)
end
It was, several times. Here in Ask a Pro we aim to provide high quality answers, in order to this it is always recommended to read all subsequent replies in a topic as quite often the OP will add more information and/or clarify their needs further, just jumping directly to the end and replying is both disrespectful to the OP and anyone else that has already replied to the topic, in the future please make sure to read the replies in a topic before even considering typing up your answer.
Engineer #10
Posted 23 October 2013 - 06:52 AM
-snip-
Did you even read the post above yours?!
MR_nesquick #11
Posted 23 October 2013 - 05:35 PM
you can also use os.startTimer if you want the computer to "multitask" without using parallel…

function func()
--code
timer = os.startTimer(60)
end

func()

while true do
event = os.pullEvent()
if event == "timer" then
  func()
end
end

os.startTimer
os.pullEvent

–not tested
Kingdaro #12
Posted 23 October 2013 - 05:44 PM
you can also use os.startTimer if you want the computer to "multitask" without using parallel…

Some comments:
  • It's almost always better to use local variables as to not pollute the global namespace. It can be speedier in some cases as well.
  • I would exclude the timer from the func() function to separate looping and action logic and implement the timing entirely in the looping section of the code. With that in mind, I would also use a "period" variable that can easily be edited for ease of tweaking and to suit multiple use cases.
  • The code compares the wrong parameter with the timer object.


local function func()
 --code
end

local period = 60
local timer = os.startTimer(period)
while true do
 local event, p1 = os.pullEvent()
 if event == "timer" and p1 == timer then
  func()
  timer = os.startTimer(period)
 end
end
MR_nesquick #13
Posted 23 October 2013 - 06:04 PM
#1. ofc, but none of my naming is used globaly
#2[1]. you can, but in your case you need to wait 1 min for the program to start
#2[2]. you can do that, but the OP asked about 1 min
#3. ??? param is used if you're running multiple timers
Kingdaro #14
Posted 23 October 2013 - 06:20 PM
#1. ofc, but none of my naming is used globaly
#2[1]. you can, but in your case you need to wait 1 min for the program to start
#2[2]. you can do that, but the OP asked about 1 min
#3. ??? param is used if you're running multiple timers
The one of the problems with global naming is the potential of being run by another program that uses the same global variable. The variable can change to an unexpected value and even an unexpected value type, and can cause errors through conflict. It can be fair to assume that any programs you're using are created by you and are run under your systems, but keeping track of variable names to avoid conflict can become a massive headache.

If you want the program to execute immediately, adding an additional call to func() is trivial. The "period" variable isn't necessary by any means, but future proofing is always nice.

I'm not sure what you mean by #3. From my experience, timer events always return "timer" and the timer object as the first and second parameters respectively.
Engineer #15
Posted 23 October 2013 - 06:53 PM
The one of the problems with global naming is the potential of being run by another program that uses the same global variable. The variable can change to an unexpected value and even an unexpected value type, and can cause errors through conflict. It can be fair to assume that any programs you're using are created by you and are run under your systems, but keeping track of variable names to avoid conflict can become a massive headache.
However I really do agree with you, I want to state something that is not always seen.
As we know we have one global table: _G
If you define a global variable, it comes into the environment of the function where it is in, aka the program.
Why programs are functionsThose program files get read by the shell, which dumps it into loadstring. Loadstring returns a function and a potential compile error.

That file executing is probably (I didnt look it up in the shell though):

function shell.run( sPath, ... )
    local sPath = ( type( sPath ) == "string" and sPath or error( "String expected, got " .. type( sPath ), 2 )
    if fs.exists( sPath ) then
       local file = fs.open( sPath, "r" )
       local content = file.readAll()
       file.close()

       local func, compileError = loadstring( content, fs.getName( sPath ) )
       if func then
          setfenv( func, getfenv(3) )
          local ok, runtimeError = pcall( func, ... )
          if not ok then
             error( runtimeError, 2 )
          end
          return true
       else
          error( compileError, 2 )
       end
   else
       error( "File not found", 0 )
   end
end
Actual shell.run

local function run( _sCommand, ... )
	local sPath = shell.resolveProgram( _sCommand )
	if sPath ~= nil then
		tProgramStack[#tProgramStack + 1] = sPath
   		local result = os.run( tEnv, sPath, ... )
		tProgramStack[#tProgramStack] = nil
		return result
   	else
    	printError( "No such program" )
    	return false
    end
end

local function runLine( _sLine )
	local tWords = {}
	for match in string.gmatch( _sLine, "[^ \t]+" ) do
		table.insert( tWords, match )
	end

	local sCommand = tWords[1]
	if sCommand then
		return run( sCommand, unpack( tWords, 2 ) )
	end
	return false
end

function shell.run( ... )
	return runLine( table.concat( { ... }, " " ) )
end
Okay, I really did miss how it should look. But okay, as you can see, it still uses one environment :P/>/>/>
It all makes sense now, for me that is. Dont hesitate to ask.
As you can see in the spoiler, it would set the environment to the shell environment. So on that we can conclude that global variables come into the shell environment.

#1. ofc, but none of my naming is used globaly
If you arent using local, your variables are "global". See above why I put that into quotes.

#3. ??? param is used if you're running multiple timers
You should always add the second check. What if other programs, or functions, queues timers and they are ran parallel wih your program? Then I can say, you are getting irreliable events.

Thats why you should add as many checks as possible for this kind of things. What if the program is getting ran on a multitasking OS? Then again, you can get irreliable results.
theoriginalbit #16
Posted 24 October 2013 - 12:10 AM
It's almost always better to use local variables as to not pollute the global namespace. It can be speedier in some cases as well.
In all cases.
Quotes
It is good programming style to use local variables whenever possible. Local variables help you avoid cluttering the global environment with unnecessary names. Moreover, the access to local variables is faster than to global ones.

Reference: http://www.lua.org/pil/4.2.html
Given that large number of registers, the Lua precompiler is able to store all local variables in registers. The result is that access to local variables is very fast in Lua. For instance, if a and b are local variables, a Lua statement like a = a + b generates one single instruction: ADD 0 0 1  (assuming that a and b are in registers 0 and 1, respectively). For comparison, if both a and b were globals, the code for that addition would be like this:

GETGLOBAL 0 0 ; a
GETGLOBAL 1 1 ; b
ADD			   0 0 1
SETGLOBAL 0 0 ; a

So, it is easy to justify one of the most important rules to improve the performance of Lua programs: use locals!

Reference: http://www.lua.org/gems/sample.pdf (p.17)
Now while the above references pure Lua of course, its fairly similar in LuaJ where it has to go find a global from the environment, read it, then set it, where local variables are stored within its Object, so it does not need to go get its local variables, it just uses it immediately.