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

Using _G/ How To Use Varibles

Started by willwac, 30 September 2013 - 07:15 PM
willwac #1
Posted 30 September 2013 - 09:15 PM
So I wan't to do something like this


function save(var,text)
var = text
end
But, it will save the text to "var" and not the variable that the user provided.

Also, need a good tutorial on using _G
  • What is it?
  • how to use it
  • when to use it
  • why to use it
Grim Reaper #2
Posted 30 September 2013 - 10:50 PM
When it comes to using LUA, functions have what are referred to as 'environments' or, in more common programming terminology, 'scope'. When a function has parameters, the parameters are called "formal parameters" because functions hold copies of variables rather than the actual variables themselves unless we're referring to tables, but I'll get to that in a second.

In your example, the function 'save' has two formal parameters: var and text. These values are copies of the actual values, bringing me to my next point. The variables that are ACTUALLY passed to the function are called 'actual parameters'. Hehe.

So, when you write the statement: var = text in your function, you're actually stating that the copy of whatever value given for var isn't that original copied value anymore. You're saying that this copied identifier (name) is actually equal to the copy of whatever value is assigned to 'text'.

When you're using tables, however, you get what's called a reference or an address to the actual parameter. So, if I have a function like this:

function func (_table)
  print (_table)
end
and I do the following:

local myTable = { 1, 2, 3, 4, 5 }

print (myTable)
func (myTable)
I'll get the SAME value printed out which is simply the address of the table. Therefore, if you want to copy tables, you'll have to do it using what's called recursion or just going through the table and copying the non-table values if the table is simple enough (not really any tables within the table).

I digress. The function that you've got as an example is pretty much unnecessary because you could just state:

var = text
without a function or, superfluously:

local var = nil

function save (text)
  var = text
end
or even

local var = nil

function save (text)
  return text
end

var = save ("Test.")
All of the which are unnecessary except for the first example without any functions.



Now, for environments, the environment shared by pretty much all functions is name _G (global environment). This global environment is just a table which is within the scope of any function that hasn't had its environment specified otherwise. For example, the terminal API and other APIs, are loaded into the _G table as tables which contain API related functions or data. So, when you call term.write, you're actually doing this:

-- term.write ("Test.")
_G["term"]["write"] ("Test.")

You'd want to use the _G table when you're trying to have data or functions available later on when, maybe, you're program isn't running. Although, you have to be careful with this because you can easily pollute the table with tons of your personal functions/data if you don't organize it. Another REALLY important thing to remember about storing data/functions in the _G table: ANY FUNCTION CAN ACCESS THE TABLE (unless specified otherwise by setfenv()). So, you can have some other malicious function mess up some data or function that you've got hanging around in the _G table.

If you have too many things in the _G table (or any table, for that matter), although this probably won't happen, is you could run out of memory because the garbage collector might think you're still using the things you've placed in the _G table since its used all the time.

When you want to store things in the _G table, you can simply do the following:

_G["index"] = ...
-- or even (if you know exactly what you want the index to be)
_G.totallyAwesomeTable = {}

Feel free to message me via the PM system or reply to this topic if you have more questions ;)/>
willwac #3
Posted 01 October 2013 - 05:52 PM
That was just an example function, I know that I can just do
local var = text
But I thought that there was a way to take whatever is in the variable "text", and save it as whatever text in the variable "var".
Wojbie #4
Posted 01 October 2013 - 06:28 PM
Sorry to piggyback on this topic but its kinda relevant - so i could per example overwrite all turtle movement functions with my own to add positioning code and store current turtle position inside _G table? would that even be good idea?

That way programs created by other people would still conserve turtle position in memory allowing for gps-less positioning system?

Would just require some kind of additional save position to file and read from file on startup.

Again sorry for piggyback but i feel its relevant to _G discussion.
Yevano #5
Posted 01 October 2013 - 07:52 PM
Sorry to piggyback on this topic but its kinda relevant - so i could per example overwrite all turtle movement functions with my own to add positioning code and store current turtle position inside _G table? would that even be good idea?

It's not necessarily a good idea to store the position in _G. You shouldn't really put anything in _G unless you want everything else to be able to access it, and you don't mind the possibility of name collisions. A better way is to just have local variables accessible to your custom turtle functions.

local x, y
function replacement.up() ... end
function replacement.down() ... end
function replacement.forward() ... end
...
Grim Reaper #6
Posted 01 October 2013 - 08:12 PM
Sorry to piggyback on this topic but its kinda relevant - so i could per example overwrite all turtle movement functions with my own to add positioning code and store current turtle position inside _G table? would that even be good idea?

It's not necessarily a good idea to store the position in _G. You shouldn't really put anything in _G unless you want everything else to be able to access it, and you don't mind the possibility of name collisions. A better way is to just have local variables accessible to your custom turtle functions.

local x, y
function replacement.up() ... end
function replacement.down() ... end
function replacement.forward() ... end
...

Yevano is right; putting things in the _G table isn't a good idea due to access issues and you run the risk of forgetting to copy the original functions and causing a recursive stack overflow by calling turtle.up which calls turtle.up forever and ever.
jay5476 #7
Posted 03 October 2013 - 12:25 AM
@OP if you want to do a save function you can do something like

function save(text)
 return text
end
a = save("Hello world")
--# a is now "Hello world"
Yevano #8
Posted 03 October 2013 - 04:17 PM
@OP if you want to do a save function you can do something like

function save(text)
return text
end
a = save("Hello world")
--# a is now "Hello world"

OP's question was already answered a long time ago four days ago, and your code does nothing more than return the value it was given as an argument.