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

[Lua][Error] go:35: bad argument: string expected, got table

Started by kelif, 13 March 2013 - 06:15 PM
kelif #1
Posted 13 March 2013 - 07:15 PM
So I'm writing a couple of programs using rednet, rom/programs/turtle/go, and shell. I want to use my program bcast to broadcast strings from one computer/turtle, to my receiving program attention from another computer/turtle. It broadcasts strings in a specific format in order to run programs using shell.run(). An example of using would be like running attention on a wireless turtle and doing this on a computer with bcast:

bcast <cmd> [args]
>bcast dance
>bcast go left
>bcast go up 3

The program should run with the given arguments on any receiving machine. So far my program works perfectly fine with "bcast dance", but the moment I try any arguments such as "bcast go left", i get the error in the Title. So anyway here's my source

attention:

rednet.open("right") --this is the turtle, so he needs to turn wireless on too
 --variables/////////////////////////////
 local id, msg, far
 local junk, cmd
 local args = {}    --args will represent an array of the arguments. 
                    --They will broadcast one at a time (line 19)
 --functions/////////////////////////////
function reset()
 id = 0
 msg = ""
 far = 0
 cmd = ""
 args = nil
 args = {}
end

 function startProgram( numArgs )
  --print( "getting commands and arguments..." )
  for xx = 0, numArgs do
   if xx == 0 then        --As I said in bcast, the first broadcast in the loop (after the one telling how
                          --many args) will represent the command (cmd) that I will use during shell.run()(line 31)
    junk, cmd, junk = rednet.receive()
    print( "Command: "..cmd ) --debugging purposes, I get to see that the command is correct
   else
    junk, args[xx], junk = rednet.receive()
    args[xx] = tostring( args[xx] )
    print( "Argument "..tostring( xx )..": "..args[xx] )--Debuggin purposes. List of my arguments for the command.
   end
  print( "Got all args! executing command:" )

  shell.run( cmd, args )    --So I want to figure out how to be able to send it like this so that
                            --number of arguments is not limited: shell.run( string, array ) 
                            --shell.run acceps an array, but it seems that when it sends it to
                            --the program go, it is not taking each element of the array as an extra
                            --argument. Rather it thinks of it as a single element, the table (array).
                            --I can not say any of this with 100% certainty... I just learned Lua yesterday,
                            --but this is my speculation. I hope I could get some help by other programmers.
  end
 end 

 function go()
  startProgram(msg)
 end 

 function stop()
  sleep(2)--Timing issue resolved
  id, msg, far = rednet.receive() --Any input after go() will stop the program and start attention over (line 57)
  print("Stopping program")
 end

while true do
 reset()
 sleep(2) --Timing issue resolved
 print( "Waiting for signal..." )
 id, msg, far = rednet.receive() --Very first broadcast of bcast will be a number representing how many arguments
                                 --passed into bcast                                 
 print( "Received "..tostring( msg ).." from "..tostring( id ) ) --Debugging purposes. So far I managed to make sure all
                                                                 --variables got the correct data they were supposed to get
 parallel.waitForAny( go, stop )
end

rednet.close("right")

bcast:

rednet.open("left")
local tArgs = { ... }--[[examples: bcast dance       <- this command works perfectly fine
                                   bcast go forward  <- this command will give an error from go saying
                                                     something about a string expected, got table instead  ]]--

if #tArgs == 0 then
 return
else
 rednet.broadcast(tostring(#tArgs)) --The first broadcast. Represents a number (msg in attention) to let attention
                                    --know how many arguments that bcast will broadcast, including the first
                                    --argument which represents the command (cmd in attention)
 for x = 1, #tArgs do
  sleep(1) --Just a timing issue fix. As far as I am aware
           --there are no more errors concerining this

  rednet.broadcast(tostring(tArgs[x]))  --All the arguments broadcasted one at a time through this loop
                                        --There does not seem to be any errors sending/recieving, or matching
                                        --up data to correct variables
 end

end
rednet.close("left")

When I run "bcast go right", I get this output:

&amp;gt;Recieve 2 from 3
&amp;gt;Command: go
&amp;gt;Got all args! executing command:
&amp;gt;go:35: bad argument: string
&amp;gt;expected, got table
&amp;gt;Argument 1: left
&amp;gt;Got all args! executing command:
&amp;gt;go:35: bad argument: string
&amp;gt;expected, got table
&amp;gt;Stopping program
&amp;gt;Waiting for signal…

As you see in my source, I kinda figure what's wrong… but I don't know how I'm going to fix this. I want to keep the flexibility with unlimited number of arguments and shell.run() accepts an array as an argument, but go doesn't seem to like it. If only there was a way to like to convert between Lua line code and string… or something of a similar nature. Maybe you guys of the forums have a better idea. I really appreciate your investment of time.
Thank you,

kelif</cmd>
Lyqyd #2
Posted 14 March 2013 - 05:36 AM
Split into new topic.

shell.run(cmd, unpack(args))

or

shell.run(cmd, table.concat(args, " "))

Also, if you are looking for a more interactive remote shell solution, check out nsh in the Programs section.
kelif #3
Posted 14 March 2013 - 07:27 AM
Thanks so much! It works great now! I found a couple of other bugs afterwards, but I fixed them and this program does exactly what I want. Thank you again :lol:/>/&amp;gt; After I'm done doing minor details such as handling human input errors, I can put this up under completed projects :)/>/&amp;gt;

Here's the updated startProgram()

function startProgram( numArgs ) --numArgs includes the arg that is supposed to represent the command, so the real args start at 2
for x = 1, numArgs do --Started at one now because numArgs starts at 1.. i guess i could have just said (numArgs - 1) but whatever.
  if x == 1 then
   junk, cmd, junk = rednet.receive()
   print( "Command: "..cmd )
  else
   junk, args[x - 1], junk = rednet.receive()
   args[x - 1] = tostring( args[x - 1] ) -- (x - 1) because by the time this line is accessed, x is at least 2 and I have to start index at 1
   print( "Argument "..tostring( x - 1 )..": "..args[x - 1] )--Debuggin purposes. List of my arguments for the command.
  end
end --ended the for loop before starting shell. I overlooked that before I got past this bug
print( "Got all args! Executing command:" )

shell.run( cmd,unpack( args ) ) --Works perfect, thanks, Lyqyd
end