This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
FuuuAInfiniteLoop(F.A.I.L)'s profile picture

goroutine:182: attemp to index ? (a nil value)

Started by FuuuAInfiniteLoop(F.A.I.L), 10 March 2013 - 12:03 PM
FuuuAInfiniteLoop(F.A.I.L) #1
Posted 10 March 2013 - 01:03 PM
Im having an error when i run my program PASTEBIN it gives me that error

Im trying to make an window-based OS and this is the start

This gonna hava a lot of more features
SuicidalSTDz #2
Posted 10 March 2013 - 01:09 PM
Im having an error when i run my program PASTEBIN it gives me that error
Edit: read below
SuicidalSTDz #3
Posted 10 March 2013 - 01:20 PM
There is no line 182, so it is obviously a nil value. Please post your entire code or post the correct line at which the code errors.
Sphexish #4
Posted 10 March 2013 - 01:36 PM
Error is in goroutine
Pastebin
Pharap #5
Posted 10 March 2013 - 02:27 PM
shell.run, lines 3 and 4.
shell.run does not work as if you were typing something into the shell, it takes arguments.
Argument 1 is the program name, the other arguments are the arguments to pass to the program (as per here: http://computercraft.info/wiki/Shell.run)
So lines 3 and 4 need to be:

shell.run("pastebin", "get", "SUW8cq9j", "goroutine")
shell.run("pastebin", "get", "fU9Kj9zr", "redirect")

To be safe, I recommend changing that first if statement to:

if not fs.exists("goroutine") then
        shell.run("pastebin", "get", "SUW8cq9j", "goroutine")
        shell.run("pastebin", "get", "fU9Kj9zr", "redirect")
end
os.loadAPI("goroutine")
os.loadAPI("redirect")
That way you're handling the API stuff all at once.
Lyqyd #6
Posted 10 March 2013 - 03:16 PM
shell.run does not work as if you were typing something into the shell, it takes arguments.

Yes, it does. It did not do so previously, but it does now.
Pharap #7
Posted 10 March 2013 - 03:58 PM
shell.run does not work as if you were typing something into the shell, it takes arguments.

Yes, it does. It did not do so previously, but it does now.

In that case, the wiki needs updating again.
Sphexish #8
Posted 10 March 2013 - 05:31 PM
Excuse me, but to fix his error…
Something is wrong in your API.
Goroutine file line 182
ChunLing #9
Posted 10 March 2013 - 06:37 PM
Your program calls goroutine.spawnWithRedirect("Desktop", desktopf, desktop)

The relevant code from goroutine is:

local function _spawn(name,method,redirect,parent,args)
	if activeRoutines[name] then
	  return nil, "Couldn't spawn; a coroutine with that name already exists!"
	end

	local routine={name=name,co=coroutine.create(method),redirect={redirect}, parent=parent,children={}}
	if routine.co==nil then
	  error("Failed to create coroutine '"..name.."'!")
	end
	parent.children[#parent.children+1]=routine --this is 182
	activeRoutines[name]=routine
	os.queueEvent("coroutine_start",name)


	numActiveCoroutines=numActiveCoroutines+1
	--run it a bit..
	sendEventTo(routine,args)

	return routine
end

function spawnWithRedirect(name,method,redirect,...)
  return _spawn(name,method,redirect,running(),{...})
end

The table parent is supposed to be provided by running(), which is this:
	local function findCoroutine(co)
	  for _,routine in pairs(activeRoutines) do
		if routine.co==co then
		  return routine
		end
	  end
	  return nil
	end
	
	function findNamedCoroutine(name)
	  return activeRoutines[name]
	end
	
	function running()
	  return findCoroutine(coroutine.running())
	end
As you can see, it is possible for running to return nil, and thus it is possible that parent is nil, and thus parent.children[letAloneThisNonesense] is an attempt to index a nil.

Actually, looking over this more closely it seems a bit screwy. Who wrote this goroutines API?
Edited on 10 March 2013 - 05:57 PM
FuuuAInfiniteLoop(F.A.I.L) #10
Posted 11 March 2013 - 04:08 AM
Your program calls goroutine.spawnWithRedirect("Desktop", desktopf, desktop)

The relevant code from goroutine is:

local function _spawn(name,method,redirect,parent,args)
	if activeRoutines[name] then
	  return nil, "Couldn't spawn; a coroutine with that name already exists!"
	end

	local routine={name=name,co=coroutine.create(method),redirect={redirect}, parent=parent,children={}}
	if routine.co==nil then
	  error("Failed to create coroutine '"..name.."'!")
	end
	parent.children[#parent.children+1]=routine --this is 182
	activeRoutines[name]=routine
	os.queueEvent("coroutine_start",name)


	numActiveCoroutines=numActiveCoroutines+1
	--run it a bit..
	sendEventTo(routine,args)

	return routine
end

function spawnWithRedirect(name,method,redirect,...)
  return _spawn(name,method,redirect,running(),{...})
end

The table parent is supposed to be provided by running(), which is this:
	local function findCoroutine(co)
	  for _,routine in pairs(activeRoutines) do
		if routine.co==co then
		  return routine
		end
	  end
	  return nil
	end
	
	function findNamedCoroutine(name)
	  return activeRoutines[name]
	end
	
	function running()
	  return findCoroutine(coroutine.running())
	end
As you can see, it is possible for running to return nil, and thus it is possible that parent is nil, and thus parent.children[letAloneThisNonesense] is an attempt to index a nil.

Actually, looking over this more closely it seems a bit screwy. Who wrote this goroutines API?
Gopher….
ChunLing #11
Posted 11 March 2013 - 11:25 AM
Hmm…I'm not entirely certain, but I think that you cannot use goroutine.spawnWithRedirect until after you've used goroutine.spawn at least once. You'd need to ask the API creator or someone fairly experienced with it to be sure how to do that properly…I'm not sure what the intended usage is.
FuuuAInfiniteLoop(F.A.I.L) #12
Posted 11 March 2013 - 02:24 PM
Hmm…I'm not entirely certain, but I think that you cannot use goroutine.spawnWithRedirect until after you've used goroutine.spawn at least once. You'd need to ask the API creator or someone fairly experienced with it to be sure how to do that properly…I'm not sure what the intended usage is.
I have asked if he could add supprot for this on goroutine and he said me that i can use goroutine.spanwWithRedirect(its like pararell but you redirect to the window object(created with redirect) every time you resume the coroutine)
GopherAtl #13
Posted 11 March 2013 - 04:33 PM
Sorry for slow response, out of town at the moment, haven't been watching the forums.

As the documentation and examples in my api thread clearly explain and demonstrate, respectively, you have to either call goroutine.run to start your top-level coroutine before calling spawn, or use goroutine.launch to run a goroutines in the background from your startup file.

There is no getting around this. The closest you could get would be if I modified the rom files so that the master coroutine is started before the shell runs, but that would amount to the same thing, just hide what's happening. Given there is significant overhead involved in running additional coroutines, having every computer and turtle always do so as part of their normal startup process is not something I would want to do myself, or would recommend to others.

All that said, beefing up the error handling is at the top of my to-do list for the next update to the goroutine api, it's a little sketchy at the moment.

tl;dr: It works if you read the detailed documentation and use it right; if you don't, it's error messages currently aren't helpful.



To fix this error, you'd just need to change the goroutine.spawnWithRedirect call with a simple goroutine.run call, then just call term.redirect at the start of the desktopf function. spawnWithRedirect you would use from in the desktop to launch windowed programs, there's no reason to use it for the top-level desktop coroutine.