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

[Lua] [Question] setting variables to several other variables

Started by Simon, 27 December 2012 - 09:18 PM
Simon #1
Posted 27 December 2012 - 10:18 PM
First post… Here I go.

So, I am making a storage program, and need to send my turtle the deets of what to do,
here is what I have so far(I excluded some unimportant code, like the user imputing the variables, and the GUI I made)


id = os.getComputerId()
getput = get  --or put, if you feel like it
item = 57  --Diamonds
amount = 64  --This should retrieve a stack of diamond blocks form the storage system

message = (id getput item amount)   -- This is the part that breaks (feel free to facepalm if I am doing this totally wrong)

rednet.send(4, message)  -- Sending message details to the turtle


how can I get line 5 to work? Any solution is acceptable as long as the output looks something like this:

0 get 57 64

If all else fails, I could just send the variables in separate rednet.send() messages :/

Btw, really liking CC so far

insert original signature here:

while self.alive() == true do
   self.kill()
end
remiX #2
Posted 27 December 2012 - 10:55 PM
Concatenate them:

message = id .." " .. getput .." " ..  item .." " ..  amount 

the " " between them is so they have a gap between them.
' .. ' is used for concatenation
RunasSudo-AWOLindefinitely #3
Posted 28 December 2012 - 01:53 AM
Seeing as all you're sending is numbers, remiX's solution should work.
I would, however, recommend serialized tables.

messageTable = {id, getput, item. amount}
message = textutils.serialize(messageTable)
Then to receive the message, instead of having to look for spaces and do crazy stuff, you just do

messageTable = textutils.unserialize(message)
id = messageTable[1] --etc
Doyle3694 #4
Posted 28 December 2012 - 02:14 AM
message = textutils.serialize({id, getput, item, amount})

We just made our code more efficient!
remiX #5
Posted 28 December 2012 - 03:29 AM
message = textutils.serialize({id, getput, item, amount})

We just made our code more efficient!

rednet.send(4, textutils.serialize({id, getput, item, amount}))

MORE EFFICIENT!
RunasSudo-AWOLindefinitely #6
Posted 28 December 2012 - 03:33 AM
message = textutils.serialize({id, getput, item, amount})

We just made our code more efficient!

rednet.send(4, textutils.serialize({id, getput, item, amount}))

MORE EFFICIENT!
rednet.send(4,textutils.serialize({id,getput,item,amount}))
EVEN (slightly) MORE EFFICIENT!
remiX #7
Posted 28 December 2012 - 04:08 AM
Also, simon, your second line for 'getput' needs to be in " " for it to be a string:
getput = "get" -- not just get

rednet.send(4,textutils.serialize({id,getput,item,amount}))
EVEN (slightly) MORE EFFICIENT!

No. :<
Simon #8
Posted 28 December 2012 - 10:08 AM
Thanks everyone :)/>
got it working great
Kingdaro #9
Posted 28 December 2012 - 10:43 AM

rednet.send(4, textutils.serialize{id, getput, item, amount})

Just a tadbit more efficient.
ChunLing #10
Posted 28 December 2012 - 11:51 AM
No, it isn't. The textutils.serialize function is for when you actually need the result to be Lua code for a table with all elements defined.

In this case, it doesn't even produce the desired output. Just use:
rednet.send(4,id.." "..getput.." "..item.." "..amount)
RunasSudo-AWOLindefinitely #11
Posted 28 December 2012 - 03:07 PM
No, it isn't. The textutils.serialize function is for when you actually need the result to be Lua code for a table with all elements defined.

In this case, it doesn't even produce the desired output. Just use:
rednet.send(4,id.." "..getput.." "..item.." "..amount)
Using a table is what I use for my bank system (see sig). I could use spaces or semicolons or something, but then I'd have to write a fancy string.explode() system or something.
Any solution is acceptable as long as the output looks something like this:
0 get 57 64
{0, "get", 54, 64} looks something like that…
Pharap #12
Posted 28 December 2012 - 03:21 PM
All these above methods would work.
I don't recommend concatenation as the LuaVitrualMachine causes an overhead when performing concatenation.
Textutils serialising and un-serialising is the best built in system.

However, bear in mind that you haven't actually called get, you are merely referencing it.
get is not a predefined function, so I'm assuming you've made it.
If it's a table or function however, all that will be sent over rednet is the word 'table:' or 'function:' followed by a hexadecimal hash code referring to the table's memory location.
Rednet will only send strings, as such you will need to call tonumber when your numbers reach the other end. You will also need to serialise all tables and string.dump all functions, then restore them with unserialise and loadstring (respectively).
RunasSudo-AWOLindefinitely #13
Posted 28 December 2012 - 03:24 PM
get is not a predefined function, so I'm assuming you've made it.
I believe the OP meant sending the string "get". Why would you bother sending a function through rednet?

rednet.send(4,textutils.serialize({id,getput,item,amount}))
EVEN (slightly) MORE EFFICIENT!

No. :<
My code gets you more "bang for your buck". It fits in (slightly) more code in a (slightly) smaller space.
Pharap #14
Posted 28 December 2012 - 03:42 PM
I believe the OP meant sending the string "get". Why would you bother sending a function through rednet?

My code gets you more "bang for your buck". It fits in (slightly) more code in a (slightly) smaller space.

Rednet file transfer. Because some of us are that crazy. Besides, how else do you extract a function from a large program without editing directly or searching carefully with strings?

The processing difference is minimal. If anything it does more obfuscation than speeding up processing.
RunasSudo-AWOLindefinitely #15
Posted 28 December 2012 - 10:21 PM
The processing difference is minimal. If anything it does more obfuscation than speeding up processing.
When did I say it sped up processing? When I said efficiency, I meant bytes/program, not cycles/program.
Both are technically correct interpretations of "efficiency". My "obfuscated" code increases "storage efficiency", not "processing efficiency". It doesn't improve the latter in any way at all.
ChunLing #16
Posted 29 December 2012 - 03:12 AM
Have you tried this? Because it doesn't send "{0, "get", 54, 64}", it sends {[1]=0,[2]="get",[3]=54,[4]=64}
RunasSudo-AWOLindefinitely #17
Posted 29 December 2012 - 01:52 PM
Have you tried this? Because it doesn't send "{0, "get", 54, 64}", it sends {[1]=0,[2]="get",[3]=54,[4]=64}
Okay, let me rephrase. It sends a serialized representation of the table represented by {0, "get", 54, 64}.
You could send the string "{0, \"get\", 54, 64}" or the string "0 get 54 64" but that would just make things more complicated, unless you have a need for string.explode() somewhere else in your code, in which case it would depend on the processing efficiency of textutils.[un]serialize() vs your string.explode() implementation.
ChunLing #18
Posted 29 December 2012 - 04:20 PM
The point is that your code isn't just less efficient in the normal sense of the term (using more processing power and requiring more code), but it doesn't accomplish the desired result, whereas the other code does while being more efficient (except in your special sense of being less actually efficient).
RunasSudo-AWOLindefinitely #19
Posted 30 December 2012 - 05:11 PM
The point is that your code isn't just less efficient in the normal sense of the term (using more processing power and requiring more code), but it doesn't accomplish the desired result, whereas the other code does while being more efficient (except in your special sense of being less actually efficient).
It does accomplish the desired result - the sending of multiple variables. The format may be different, but I am merely suggesting a method requiring less code - you'd have to write a string.explode or do lots of string.sub/string.find with the other method - rather than assuming that the OP is completely inflexible and the data MUST be sent in PRECISELY the format given.
Kingdaro #20
Posted 30 December 2012 - 06:54 PM
I think the word we were looking for in this thread was "cleaner", as opposed to "efficient".
ChunLing #21
Posted 30 December 2012 - 06:54 PM
Ah…the unspoken assumption is finally spoken.

Yes, if we assume that the OP is simply wrong about how the sent message should be formatted, and further assume that it is to be used on the other side as separate variables, then it does make a good bit more sense to put them in a table, serialize it, and then unserialize it on the other end.

I will not comment on whether those assumptions are "good". But when you are basing your argument on assumptions not previously stated, it is better to plainly state them.
RunasSudo-AWOLindefinitely #22
Posted 31 December 2012 - 02:04 AM
Ah…the unspoken assumption is finally spoken.

Yes, if we assume that the OP is simply wrong about how the sent message should be formatted, and further assume that it is to be used on the other side as separate variables, then it does make a good bit more sense to put them in a table, serialize it, and then unserialize it on the other end.

I will not comment on whether those assumptions are "good". But when you are basing your argument on assumptions not previously stated, it is better to plainly state them.
Yes, I see how that might work… However, I do believe that, given the following clues, the OP intends to use the data separately:
1) "need to send my turtle the deets of what to do" A string containing a bunch of numbers and letters and spaces would be an odd thing for a turtle to act on, without needing to separate the variables.
2) "I could just send the variables in separate rednet.send() messages" If the OP wanted the variables as the string "0 get…", sending the variables separately would make no difference. If he did want the variables as a string, he would still need to concatenate the bits at the other end (which, if this was his intention, he still wouldn't know how to do).

I think the word we were looking for in this thread was "cleaner", as opposed to "efficient".
Because I just can't help defending my code, *ahem*
My code:

--Send
local message = textutils.serialise({id, getput, item, amount})
--Receive
local mT = textutils.unserialise(message)
id = mT[1]; getput = mT[2]; item = mT[3]; amount = mT[4]
The other code:

--Send
local message = id .. " " .. getput .. " " .. item .. " " .. amount

--Receive (string.explode from http://snippets.luacode.org/?p=snippets/stringexplode_90)
function string.explode ( str , seperator , plain )
	assert ( type ( seperator ) == "string" and seperator ~= "" , "Invalid seperator (need string of length >= 1)" )

	local t , nexti = { } , 1
	local pos = 1
	while true do
		local st , sp = str:find ( seperator , pos , plain )
		if not st then break end -- No more seperators found
		
		if pos ~= st then
			t [ nexti ] = str:sub ( pos , st - 1 ) -- Attach chars left of current divider
			nexti = nexti + 1
		end
		pos = sp + 1 -- Jump past current divider
	end
	t [ nexti ] = str:sub ( pos ) -- Attach chars right of last divider
	return t
end

local messageTable = string.explode(message, " ", true)
id = mT[1]; getput = mT[2]; item = mT[3]; amount = mT[4]

Now which is cleaner?
Edited on 31 December 2012 - 01:30 AM
ChunLing #23
Posted 31 December 2012 - 10:44 PM
Okay, my receive function might look more like:
local mT,ndx = {},1
for v in message:gmatch("%S+") do mT[ndx] = v ndx = ndx+1 end
id = mT[1]; getput = mT[2]; item = mT[3]; amount = mT[4]
I mean, nice complicated code you wrote there, but it's a total strawman.

You're code still looks slightly cleaner, I grant that. If your assumptions about the intended use of the messages are correct, then textutils.serialize/unserialize are the appropriate tools for this task.

I'm just saying that you should have explicitly stated your assumptions.