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

Parallel variable issues

Started by ShadowDisruptor, 30 November 2014 - 06:01 PM
ShadowDisruptor #1
Posted 30 November 2014 - 07:01 PM
Hello! I'm running a script that uses a parallel to run 2 functions. The functions work fine without being called in parallel, but when in parallel, they cannot access variables outside from that function. Any help?
Dragon53535 #2
Posted 30 November 2014 - 07:06 PM
Post the code so we can see what you're doing to the variables in question.
Exerro #3
Posted 30 November 2014 - 07:07 PM
I don't believe parallel messes around with function environments, so I don't really see what's going on here. Seeing some code would be very useful.

Are you sure you're passing the functions into parallel, and not calling them? Sometimes people do this:

parallel.waitForAny( foo(), bar() )
when instead it should be this:

parallel.waitForAny( foo, bar )
Edited on 30 November 2014 - 06:08 PM
ShadowDisruptor #4
Posted 30 November 2014 - 07:10 PM
Post the code so we can see what you're doing to the variables in question.

Sending them via rednet.

if message == "does_exist" then
  serverHad = true
  rednet.send(servers[i], "LOL", "delete_"..variable)--'variable' is the variable outside the function. Note, this is a snip of the 100 line function.
  value = "deleted."
  writeValue()
 end

I don't believe parallel messes around with function environments, so I don't really see what's going on here. Seeing some code would be very useful.

Are you sure you're passing the functions into parallel, and not calling them? Sometimes people do this:

parallel.waitForAny( foo(), bar() )
when instead it should be this:

parallel.waitForAny( foo, bar )


while true do
  parallel.waitForAny(clickDetect, rednetDetect)
end
Positive.
Exerro #5
Posted 30 November 2014 - 07:30 PM
Is 'variable' global or local? Is that erring "attempt to concatenate string and nil" or is it just not being updated? Posting the whole code would help, or at least a bit more than that.
TurtleHunter #6
Posted 30 November 2014 - 07:32 PM
You should use a while true loop with parallel as it creates some issues
ShadowDisruptor #7
Posted 30 November 2014 - 07:37 PM
Is 'variable' global or local? Is that erring "attempt to concatenate string and nil" or is it just not being updated? Posting the whole code would help, or at least a bit more than that.
It is "attempt to concatenate string and nil" The variable isn't local, nor is it global. (Example: variable = "click to edit.")

You should use a while true loop with parallel as it creates some issues
I am using a while loop, do you mean shouldn't use?

For those asking for source, have fun.
http://pastebin.com/0wdZbZN9
Exerro #8
Posted 30 November 2014 - 07:49 PM
'variable = "blah" ' means it is global, just so you know.

I might be wrong about parallel messing with function environments, so just to be safe I'd put 'variable' and 'value' at the top as local variables. That way, no matter how hard parallel tries, it can't make either of them nil.

It is a pretty weird error though, I can't see anywhere where 'variable' could be made equal to nil.

Just for future reference, using global variables is pretty much always a bad idea. They are slower, can be changed by other programs, and use up memory even after the code they are used in stops.
Dog #9
Posted 30 November 2014 - 07:55 PM
Is 'variable' global or local? Is that erring "attempt to concatenate string and nil" or is it just not being updated? Posting the whole code would help, or at least a bit more than that.
It is "attempt to concatenate string and nil" The variable isn't local, nor is it global. (Example: variable = "click to edit.")

You should use a while true loop with parallel as it creates some issues
I am using a while loop, do you mean shouldn't use?

For those asking for source, have fun.
http://pastebin.com/0wdZbZN9

Using parallel within a while loop works fine (as well as using it outside of a while loop), I'm not sure where TurtleHunter got the idea that it there are 'issues' with one way or the other.

As for local/global variables - your example (variable = "click to edit") defines a global variable - basically if it's not localized then it's global. Keep in mind that some variables are 'automatically' localized - (e.g. loops - for example a generic loop like 'for k, v in pairs' … the k and v are automatically localized), but when you declare a variable like you did, it needs to be explicitly localized or it is a global.

:ph34r:/> 'd
Edited on 30 November 2014 - 06:57 PM
ShadowDisruptor #10
Posted 30 November 2014 - 07:56 PM
'variable = "blah" ' means it is global, just so you know.

I might be wrong about parallel messing with function environments, so just to be safe I'd put 'variable' and 'value' at the top as local variables. That way, no matter how hard parallel tries, it can't make either of them nil.

It is a pretty weird error though, I can't see anywhere where 'variable' could be made equal to nil.

Just for future reference, using global variables is pretty much always a bad idea. They are slower, can be changed by other programs, and use up memory even after the code they are used in stops.

Adding the local at the top of function dosent work. Any other suggestions?
Exerro #11
Posted 30 November 2014 - 07:58 PM
Not at the top of the function, at the top of the whole code.
Like this…

local variable = "blah"
function setVariable()
end
...
ShadowDisruptor #12
Posted 30 November 2014 - 07:58 PM
Is 'variable' global or local? Is that erring "attempt to concatenate string and nil" or is it just not being updated? Posting the whole code would help, or at least a bit more than that.
It is "attempt to concatenate string and nil" The variable isn't local, nor is it global. (Example: variable = "click to edit.")

You should use a while true loop with parallel as it creates some issues
I am using a while loop, do you mean shouldn't use?

For those asking for source, have fun.
http://pastebin.com/0wdZbZN9

Using parallel within a while loop works fine (as well as using it outside of a while loop), I'm not sure where TurtleHunter got the idea that it there are 'issues' with one way or the other.

As for local/global variables - your example (variable = "click to edit") defines a global variable - basically if it's not localized then it's global. Keep in mind that some variables are 'automatically' localized - (e.g. loops - for example a generic loop like 'for k, v in pairs' … the k and v are automatically localized), but when you declare a variable like you did, it needs to be explicitly localized or it is a global.
Changing to local at the top keeps the same errors.

Not at the top of the function, at the top of the whole code.
Like this…

local variable = "blah"
function setVariable()
end
...
Same error.

EDIT: Also getting another error, "window:155: bad argument: string expected, got nil" on initial startup of the script
Edited on 30 November 2014 - 07:01 PM
MKlegoman357 #13
Posted 30 November 2014 - 08:00 PM
After looking at the code I saw that you are giving 'variable' a value and the only function that could somehow set 'variable' to nil is 'read()' which never returns nil. Just to be sure, have you tried to reboot the computer and run this, and only this, program?

EDIT: try this:


resetGraphics()
while true do
  print( type(variable) ) <-- #right here
  parallel.waitForAny(clickDetect, rednetDetect)
end
Edited on 30 November 2014 - 07:04 PM
ShadowDisruptor #14
Posted 30 November 2014 - 08:03 PM
I'm running this in CCEmuRedux, could this be the issue? If someone could try running this script in a real game, it would help to know if that's the error.

After looking at the code I saw that you are giving 'variable' a value and the only function that could somehow set 'variable' to nil is 'read()' which never returns nil. Just to be sure, have you tried to reboot the computer and run this, and only this, program?

This is the only program I'm running. Rebooted multiple times.
MKlegoman357 #15
Posted 30 November 2014 - 08:07 PM
I'm running this in CCEmuRedux, …

Yeah.. you could have said that earlier. If something doesn't work in an emulator, try it in-game. Emulators are not 100% perfect, especially if you are using Rednet with them.
ShadowDisruptor #16
Posted 30 November 2014 - 08:09 PM
I'm running this in CCEmuRedux, …

Yeah.. you could have said that earlier. If something doesn't work in an emulator, try it in-game. Emulators are not 100% perfect, especially if you are using Rednet with them.
Just thought about saying it, my bad. I don't currently have a modpack set up with the correct version of CC. I guess I will work on making a pack to test it. Thanks for the help :)/>
ShadowDisruptor #17
Posted 30 November 2014 - 08:18 PM
snip
Turns out nothing happens at all ingame.. the clicks work, but none of the rednet transactions occur. When I press a button, everything freezes up.
Edited on 30 November 2014 - 07:19 PM
MKlegoman357 #18
Posted 30 November 2014 - 08:19 PM
Check your IDs. Also, you define the 'servers' variable two times in the code.
ShadowDisruptor #19
Posted 30 November 2014 - 08:21 PM
Check your IDs. Also, you define the 'servers' variable two times in the code.
Where's the second call? That's probably the issue, I did have the correct ID's.

EDIT: Found it! Sadly we're back where we started, same issue.
Edited on 30 November 2014 - 07:26 PM
Exerro #20
Posted 30 November 2014 - 08:29 PM
I think something external must be setting variable to nil, as read() NEVER returns nil. Are there any other programs or coroutines running?

The only other thing I can think of is this:

local function test()
	return 2 + nil
end
test() -- the error pops up here, not line 2
And rednet.send is returning an error, like above.
Edited on 30 November 2014 - 07:29 PM
ShadowDisruptor #21
Posted 30 November 2014 - 08:40 PM
I think something external must be setting variable to nil, as read() NEVER returns nil. Are there any other programs or coroutines running?

The only other thing I can think of is this:

local function test()
	return 2 + nil
end
test() -- the error pops up here, not line 2
And rednet.send is returning an error, like above.

I'm not 100% sure it's the rednet. It's something we're doing inside clickDetect() the rednetDetect() function works flawlessly. There's nothing else running on that computer.

EDIT: Variable and value could be set to nil if it's not getting the data from the rednet, but my code is made to prevent that. (Communicates with the database to make sure something exists before asking for it)
Edited on 30 November 2014 - 07:41 PM
ShadowDisruptor #22
Posted 30 November 2014 - 11:14 PM
Got some data that might help break it down.

1) It's in this section of code

if(y == 8) then
    if((x >= 3) and (x <= 7)) then
      serverHad = false
      for i=1, #servers do
        rednet.send(servers[i], "LOL", "has_"..variable)
        while true do
          id,message = rednet.receive()
          if id == servers[i] then
            if message == "does_exist" then
              serverHad = true
              rednet.send(servers[i], "LOL", "get_"..variable)
              while true do
                id,message = rednet.receive()
                if id == servers[i] then
                  value = message
                  writeValue()
                  break
                end
              end
            end
            break
          end
        end
      end
      if not(serverHad) then
        value = "Dosen't exist :(/>"
        writeValue()
      end
    end
    if((x >= 9) and (x <= 13)) then
      serverHad = false
      for i=1, #servers do
        rednet.send(servers[i], "LOL", "has_"..variable)
        while true do
          id,message = rednet.receive()
          if id == servers[i] then
            if message == "does_exist" then
              serverHad = true
              rednet.send(servers[i], value, "set_"..variable)
            end
            break
          end
        end
      end
      if not(serverHad) then
        local randomNum = math.random(#servers)
rednet.send(servers[randomNum], value, "set_"..variable)
      end
    end
if((x >= 15) and (x <= 22)) then
      serverHad = false
      for i=1, #servers do
        rednet.send(servers[i], "LOL", "has_"..variable)
        while true do
          id,message = rednet.receive()
          if id == servers[i] then
            if message == "does_exist" then
              serverHad = true
              rednet.send(servers[i], "LOL", "delete_"..variable)
 value = "deleted."
 writeValue()
            end
            break
          end
        end
      end
      if not(serverHad) then
        value = "Dosen't exist :(/>"
        writeValue()
      end
    end
    if((x >= 24) and (x <= 37)) then
      shell.run("edit servers")
      resetGraphics()
    end
  end

2) The 'does exist' check always runs


--This is what that looks like
rednet.send(servers[i], "DERP", "has_"..tempVar)
        while true do
          id2,message2 = rednet.receive()
          if id2 == servers[i] then
            if message == "does_exist" then
              goodMatch = true
              rednet.send(servers[i], message, "set_"..tempVar)
            end
            break
          end
        end

3) If both servers have the variable, it also does the action and crashes after. Otherwise, only the exist check works
jaredallard #23
Posted 01 December 2014 - 06:16 PM
'variable = "blah" ' means it is global, just so you know.

I might be wrong about parallel messing with function environments, so just to be safe I'd put 'variable' and 'value' at the top as local variables. That way, no matter how hard parallel tries, it can't make either of them nil.

It is a pretty weird error though, I can't see anywhere where 'variable' could be made equal to nil.

Just for future reference, using global variables is pretty much always a bad idea. They are slower, can be changed by other programs, and use up memory even after the code they are used in stops.

Not true, _G['variable'] and variable are very different things. variable is global to it's scope, while _G['variable'] is global to all scopes.
Exerro #24
Posted 01 December 2014 - 06:32 PM
'variable = "blah" ' means it is global, just so you know.

I might be wrong about parallel messing with function environments, so just to be safe I'd put 'variable' and 'value' at the top as local variables. That way, no matter how hard parallel tries, it can't make either of them nil.

It is a pretty weird error though, I can't see anywhere where 'variable' could be made equal to nil.

Just for future reference, using global variables is pretty much always a bad idea. They are slower, can be changed by other programs, and use up memory even after the code they are used in stops.

Not true, _G['variable'] and variable are very different things. variable is global to it's scope, while _G['variable'] is global to all scopes.
Not always, that's just how CraftOS does it. You can give a _G when you set a function environment (and if you don't it isn't given automatically), and setting a variable in the current scope is almost always referred to as setting a global.

Edit: also, a (function) scope includes local variables to that function.
Edited on 01 December 2014 - 05:39 PM