Dixie's Lua Thread

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Dixie's Lua Thread

Post by Dixie »

Well, I said I was gonna put myself to Lua, which I have done. For the past few days/weeks, I have read a few tutorials, browsed our wiki, etc. So now at least I understand the basic syntax of the language, I've looked at a few example, and I'm able to understand most of them.

Faithful to my old habits, I have a somewhat ambitious project to go with that. I've been planning it for the past week(s) and now I'm more or less ready to start coding the main engine. I don't have a firmview of exactly all that I'll need, but I'll start with some basic functions nd work from there. I will try to not ask too much for your help and correct as much as I can by myself. Hope I won't be too much of a burden :)

So I have started doing some basic stuff, and I'd need something clarified already. I know in Lua you can build tables inside tables inside tables, etc. I wondered how this behaved in WML, though, as I read the global Lua state was flushed upon closing Wesnoth (and thus the global Lua state not being reliable to store variables, which should be handed over to WML). If, for example, I wanted to store a costum weapon variable containing the values "attack" "hit_chance" and "critical_chance" (which makes it a table) in a unit's variables. I suppose "wesnoth.set_variable" wouldn't be appropriate. I suppose since the keys inside my tables are words and not numbers, "wesnoth.set_variable_array" ain't the right option either (can my_unit.variables even contain arrays, btw?). The wiki also mentions "metatables" and "proxy arrays", but I'm not clear on the meaning of those. I'd naturally tend towards the metatable, but I'm not really sure how it'd behave in my_unit.variables. It mentions "WML objects", I suppose those are big containers such as a unit or a side. Can a unit hold a WML object in its variables?

Hmm... I think that's all for now. Thanks a lot! :)
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Dixie's Lua Thread

Post by Anonymissimus »

So, from one table-confused person to another...
Dixie wrote:(can my_unit.variables even contain arrays, btw?).
yes, on the wml side at least (you can even store a unit to the variables of another one)
The wiki also mentions "metatables" and "proxy arrays", but I'm not clear on the meaning of those.
The meta-thing is only shortcut stuff afaik, that means you don't need to write so much in your lua code. Never used it so far.
Whenever the word "proxy" or "userdata" appears it means it's a reference to a C++ object in the engine, e.g. a unit from get_units. The difference to a wml object representing a unit is e.g. that you don't need to unstore_unit or put_unit your unit to let (some) changes have affect, e.g. you can do unit_var.side = 2 and it has affect instantly.
silene wrote:For instance, the following three scripts are strictly equivalent:

Code: Select all

wesnoth.set_variable("counter", 1 + wesnoth.get_variable "counter")
--
local V = helper.set_wml_var_metatable {}
V.counter = 1 + V.counter
--
helper.set_wml_var_metatable(_G)
counter = 1 + counter
I suggest to write yourself a global debug-message function that outputs not only the value but also the type of a variable (using wesnoth.message and type() which is a function in the "basic" library.)

wml objects are the lua versions of wml code blocks, e.g.

Code: Select all

[tag]
    key=value
    [subtag]
        subkey=subvalue
    [subtag]
[/tag]
corresponds to (untested :P),

Code: Select all

wesnoth.fire("tag", {{key = "value", {"subtag", {subkey = "subvalue"}}}})
so a unit can take a wml object into its variables with e.g. wesnoth.fire("set_variable", ...).

EDIT
Upon rereading this critical "encoding wml objects into lua tables" section the xxxxth time, I see that a "wml object" is in silene's terminology the WML code block, while its lua version is the wml table.
@silene I think the section would be better understanable I you used consistent terminology if you mean the same thing, e.g. Scalar fields = Lua named fields.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Hmmm... interesting. So if I understand correctly:

1) I can store whatever I like in a my_unit.variables, be it an array/table, a dictionnary-table, another unit, anything. That's nice and will definitely make my life easier :)

2) Metatable is useful when you have a big batch of Lua variables you want to transfer to wml all at once. In other words, it is merely a short cut to avoid spamming "wesnoth.set_variable" an infinite amont of times.

3) If I store a wml object (variable?) using the proxy thing, it will automatically be synced to the game, saving me the trouble of unstore or put_unit. For exemple:

Code: Select all

function apply_damage(damage_var, unit_id)
    wesnoth.fire("store_unit", { id=unit_id, variable = "unit_to_damage" })
    local u = get_variable_proxy_array "unit_to_damage"
    u.hitpoints = u.hitpoints - damage_var
    return 
    end
would be the same as:

Code: Select all

function apply_damage(damage_var, unit_id)
    wesnoth.fire("store_unit", { id=unit_id, variable = "unit_to_damage" })
    wesnoth.set_variable("unit_to_damage.hitpoints", unit_to_damage.hitpoints - damage_var)
    wesnoth.fire("unstore_unit", { variable = "unit_to_damage" })
    return
    end
Right? Btw, I don't think I understood/used the function's arguments/return wrong?

Thanks for your fast answer! :)
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:If, for example, I wanted to store a costum weapon variable containing the values "attack" "hit_chance" and "critical_chance" (which makes it a table) in a unit's variables. I suppose "wesnoth.set_variable" wouldn't be appropriate.
It is appropriate:

Code: Select all

wesnoth.set_variable("custom_weapon", { attack = 17, hit_chance = 42, ... })
If you look at a savegame, you will have in the [variables] section the following tags:

Code: Select all

[custom_weapon]
  attack="17"
  hit_chance="42"
  ...
[/custom_weapon]
Dixie wrote:I suppose since the keys inside my tables are words and not numbers, "wesnoth.set_variable_array" ain't the right option either (can my_unit.variables even contain arrays, btw?).
No it isn't. Here is example:

Code: Select all

helper.set_variable_array("custom_weapon", { { attack = 17, hit_chance = 42 }, { attack = 33 } })
If you look at a savegame, you will have in the [variables] section the following tags:

Code: Select all

[custom_weapon]
  attack="17"
  hit_chance="42"
[/custom_weapon]
[custom_weapon]
  attack="33"
[/custom_weapon]
Dixie wrote:The wiki also mentions "metatables" and "proxy arrays", but I'm not clear on the meaning of those.
A metatable is a Lua feature that modifies the behavior of an object; you won't need to define new ones for a while but the engine uses lot of them behind the scenes for proxy objects. A proxy is an object that doesn't get contain its own data; when it is read or written, the data transparently go through the object toward its original location, e.g. a wml variable or a unit on the map.[/quote]
Anonymissimus wrote:Upon rereading this critical "encoding wml objects into lua tables" section the xxxxth time, I see that a "wml object" is in silene's terminology the WML code block, while its lua version is the wml table.
Yes, in the terminology I use, a "WML object" is the content of a WML tag: its attributes, its nested tags, and their contents. A "table" is a Lua base object. A "WML table" is a Lua "table" whose content can be converted to a "WML object" without error. And the other way, whenever you query the engine for a "WML object" (e.g. wesnoth.get_variable or the __cfg fields of proxy objects), you get a "table" which is in fact a "WML table".
Anonymissimus wrote:@silene I think the section would be better understanable I you used consistent terminology if you mean the same thing, e.g. Scalar fields = Lua named fields.
I didn't mean the same thing. A scalar field is a field that contains a scalar value, e.g. boolean, integer, string, translatable string. A named field is a field that has a name. For instance, the following Lua table has three named fields A, B, C:

Code: Select all

{ A = 1, B = { D = 2, E = 3 }, C = { 4, F = 5 } }
Field A contains a scalar value, but B and C don't (they contain tables). As a consequence, the above table is not a WML table since it contains some named fields that are not scalars. Note that B has only named fields while C has one unnamed field and one named field.
Dixie wrote:1) I can store whatever I like in a my_unit.variables, be it an array/table, a dictionnary-table, another unit, anything. That's nice and will definitely make my life easier :)
I'm assuming that "my_unit.variables" represents a WML variable; for instance, you set it by wesnoth.set_variable("my_unit.variables", something). In that case, you can indeed store anything into it, as long as it is a WML object. Note that most things can be encoded as WML objects, so it's not an issue, but the first times, you will probably try to store illformed things.
Dixie wrote:2) Metatable is useful when you have a big batch of Lua variables you want to transfer to wml all at once. In other words, it is merely a short cut to avoid spamming "wesnoth.set_variable" an infinite amont of times.
Almost. Proxy objects are the shortcut. Metatables are just an implementation detail of them.
Dixie wrote:3) If I store a wml object (variable?) using the proxy thing, it will automatically be synced to the game, saving me the trouble of unstore or put_unit. For exemple:

Code: Select all

function apply_damage(damage_var, unit_id)
    wesnoth.fire("store_unit", { id=unit_id, variable = "unit_to_damage" })
    local u = get_variable_proxy_array "unit_to_damage"
    u.hitpoints = u.hitpoints - damage_var
    return 
    end
would be the same as:

Code: Select all

function apply_damage(damage_var, unit_id)
    wesnoth.fire("store_unit", { id=unit_id, variable = "unit_to_damage" })
    wesnoth.set_variable("unit_to_damage.hitpoints", unit_to_damage.hitpoints - damage_var)
    wesnoth.fire("unstore_unit", { variable = "unit_to_damage" })
    return
    end
No. While proxy objects automatically transmit data to something, this something is not magically guessed. So, consider

Code: Select all

local u = helper.get_variable_proxy_array "unit_to_damage"
u[1].hitpoints = u[1].hitpoints - damage_var
First, note that I have added "[1]" to your code, since the get_variable_proxy_array function returns a table. So u[1] is the WML container containing the first unit stored by [store_unit], u[2] the second one, u[3] the third one, and so on. In your particular case, [store_unit] stores a single unit, so u[2] and later will contain nil.

Second, u[1] is a proxy to the first WML container with name [unit_to_damage] in the [variables] zone of your scenario. So any access to the proxy will just read and write WML variables, nothing more. You still have to unstore the unit to put it back onto the map.

If you wanted a proxy to a real unit instead of WML variables, you should have used a different function.

Code: Select all

local u = wesnoth.get_units { id = unit_id }
u[1].hitpoints = u[1].hitpoints - damage_var
Note that "hitpoints" is read-only in 1.8, so the above code works on 1.9 only. On 1.8, you need to recover the whole WML of the unit, modify it, and then put it back on the map:

Code: Select all

local u = wesnoth.get_units { id = unit_id }
local u_wml = u[1].__cfg
u_wml.hitpoints = u_wml.hitpoints - damage_var
wesnoth.put_unit(u_wml)
This is equivalent to your code based on set_variable, except that it doesn't involve any WML variable. (In particular, no need to clean them at the end, which you forgot in your code.)
Dixie wrote:Btw, I don't think I understood/used the function's arguments/return wrong?
Function arguments look fine. The return statement is fine too. It is just useless since it is the last statement of your function and it doesn't return any particular value.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Hm, very interesting. And informative. I guess I missed the wesnoth.get_units, it is indeed a great tool. And I'm definitely gonna do my thing for 1.9, since Lua seems to have many significant upgrades in it. Not gonna bother with 1.8 :P

Continuing with variables, tables and dictionnaries, I think I'm able to get this one out by myself, but I'll I'd just like to be confirmed I'm understanding this correctly:

Am I right to assume that:

> string_var = "sub_table"
> table.sub_table.sub_sub_table.key == table["sub_table"].sub_sub_table.key == table[string_var].sub_sub_table.key == table[string_var".sub_sub_table"].key == table["sub_table"."sub_sub_table"].key == table["sub_table.sub_sub_table"].key == table["sub_table.sub_sub_table"."key"]
true

(well, I'm mostly testing the variables names, I'm not 100% convinced this would be a correct expression with that many ==s)
If not, what is wrong/which ones don't work? Are there other ways of doing this I haven't thought of?

Thanks a lot! I'm beginning to get a more global understanding of the thing, it looks promising :)
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Dixie's Lua Thread

Post by Anonymissimus »

String concatenation is done with ..
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Yeah I know. What I'm trying to do, in fact, is variable substitution in order to call another variable. If I am not mistaken, it would have the following wml equivalent:

{VARIABLE string_var "sub_table"}
{IF_VAR table.sub_table.sub_sub_table.key equals table.$string_var|.sub_sub_table.key (
# etc.

And, in the mean time, I wondered how mixing the "table[sub_table]" notation with the "table.subtable" one behaved (I would think it follows the same rules in WML, but I'm not sure how it behaves in there either).

Sorry if it was not clear, I hope it is better this time, thanks anyway :)

EDIT: Sorry, I just realised what you probably meant with your string concatanation reply: my "table[string_var .. ".sub_sub_table"].key attempt, right?
Last edited by Dixie on August 12th, 2010, 2:38 pm, edited 1 time in total.
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:Am I right to assume that:

> string_var = "sub_table"
> table.sub_table.sub_sub_table.key == table["sub_table"].sub_sub_table.key == table[string_var].sub_sub_table.key
Yes. Note that you have nonscalar named fields, so, either table is a plain Lua table (not a WML table), or it is a proxy object to a WML variable.
Dixie wrote: == table[string_var".sub_sub_table"].key == table["sub_table"."sub_sub_table"].key == table["sub_table.sub_sub_table"."key"]
Syntax errors. (See below for the behavior of the fixed versions.)
Dixie wrote: == table["sub_table.sub_sub_table"].key
No if it is a plain Lua table.
Yes if it is a proxy object to a WML variable.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

silene wrote:
Dixie wrote: == table["sub_table.sub_sub_table"].key
No if it is a plain Lua table.
Yes if it is a proxy object to a WML variable.
So I can't do this in Lua, unless I got it through wesnoth.get_variable_proxy_array, is that it?

Either way, I guess this would give the same result? :
table["sub_table"["sub_sub_table"]].key

Would this version be true? :
table.sub_table.sub_sub_table.key == table["sub_table"]["sub_sub_table"].key
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:
silene wrote: No if it is a plain Lua table.
Yes if it is a proxy object to a WML variable.
So I can't do this in Lua, unless I got it through wesnoth.get_variable_proxy_array, is that it?
Yes and no. The exact same mechanism is enabled by helper.set_wml_var_metatable:

Code: Select all

-- In the code below, V can be used to transparently access any WML variable:
local V = helper.set_wml_var_metatable {}
assert(V.table["sub_table.sub_sub_table"].key == V.table.sub_table.sub_sub_table.key)

-- In the code below, you don't even need a prefix any longer.
helper.set_wml_var_metatable(_G)
assert(table["sub_table.sub_sub_table"].key == table.sub_table.sub_sub_table.key)
Dixie wrote:Either way, I guess this would give the same result? :
table["sub_table"["sub_sub_table"]].key
Syntax error, and I can't even imagine what it would actually mean.
Dixie wrote:table.sub_table.sub_sub_table.key == table["sub_table"]["sub_sub_table"].key
Yes for both plain Lua tables and proxies to WML variables.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Thanks for your answers :) I'm still not 100% clear with metatables and proxies, but I'm trying to complete my understanding with the Lua 5.1 user guide. It isn't really a decisive concern right now, anyway, it's just for my personnal growth as a Lua user.

More importantly, I have run into the following two errors. I have narrowed down what seems to cause the problem, but I don't really understand why there is a problem.

Error 1:
Error 1
Error 1
Is produced by the following code:

Code: Select all

[event]
  name=preload
  first_time_only=no

  [lua]
    code=<<
	wesnoth.dofile "~add-ons/The_Fall_of_Wesnoth/lua/fow_inventory.lua"
>>
  [/lua]
[/event]
So I guess I am not understanding correctly how to call a function defined in a lua file. I thought it was so. I defined them with wesnoth.dofile, like this:

Code: Select all

  [lua]
    code=<< wesnoth.set_variable("inventory", fow_inventory.generate_inventory()) >>
  [/lua]
How should I call the function instead? Directly with generate_inventory()?


Error 2:
Error 2
Error 2
Is caused by this code (which is in the generate_inventory() function) and apparently has something to do with one of the two dots, but I don't understand what I did wrong:

Code: Select all

  if eq.weight < 0 
  then
    local eq.weight = 0
  end
Writing this, I realise I haven't tried using eq[weight] instead of eq.weight but they are supposed to be equivalent, afaik :hmm:

By the way, I think I've seen places where they use a semi colon (";") at the end of such statements, and others where there weren't. Is there a rule about that?

Thanks again! :)
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Note that you don't have to perform screen captures to get the error messages. You can just open the console or the stderr.txt file and copy-paste them.
Dixie wrote:

Code: Select all

wesnoth.set_variable("inventory", fow_inventory.generate_inventory())
How should I call the function instead? Directly with generate_inventory()?
If that is the name you gave to your function, then yes.
Dixie wrote:

Code: Select all

  if eq.weight < 0 
  then
    local eq.weight = 0
  end
That's a serious misunderstanding of what a local variable is. A local variable defines a new temporary object whose name lives only for the time of the current block, that is, between "then" and "end" in your example. (The content of the temporary object may live for a longer time though, if it is transfered elsewhere.) You shouldn't be creating a new object there, you should be modifying the value of an existing one. So get rid of local.

Local variables are useful for giving shorter name to complex expressions and avoid to compute them again and again. In the case of the apply_damage function, the variable u is declared local, because once the function has ended, nobody no longer care that there was something called u in the function; the name was useful only for the duration of the function. The name shouldn't escape the function and pollute the namespace of other functions.
Dixie wrote:By the way, I think I've seen places where they use a semi colon (";") at the end of such statements, and others where there weren't. Is there a rule about that?
Semi-colons are mandatory only when there is an ambiguity about the end of the previous statement and the start of the next one. I think the only such case in Lua is when a statement starts with a parenthesis. This hardly happens, so you usually never need to put semi-colons.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Hm, good catch about local. The variable eq is local to the function it's in. Would that if statement write eq.weight to _G, or would it still keep it local to the function? Would I need to specifically do eq.weight = nil at some later point? A truncated version of the function, for the sake of exemple:

Code: Select all

local get_eq_stats = function(get_mat, get_equip)

  local eq = { weight = material[get_mat].weight + equipment[get_equip].weight }

  if eq.weight < 0 
  then
    eq.weight = 0
  end

return eq 
end
Edit:

I think I understood something wrong with functions and the return part. I thought that if a function returned a table, it would be treated as a table when it is called, not a function returning a table. Or is that what the metatable thing is used for?

This line:

Code: Select all

wesnoth.set_variable("inventory", generate_inventory())
generates this error:
error wrote:[string " wesnoth.set_variable("inventory", generate..."]:1: in main chunk
20100813 09:36:45 error scripting/lua: [string "wesnoth.set_variable("inventory", generate_..."]:1: bad argument #2 to 'set_variable' (WML table or scalar expected, got table)
Here's the function it calls:

Code: Select all

generate_inventory = function()
  local inv_var = {}
  for i,v in ipairs(item) 
  do
    table.insert(inv_var, { amount=0, equip=0, stats=v })
  end
  for i,v in ipairs(inv_var, material) 
  do
    pair_mat_eq(i)
  end
  for i,v in ipairs(relic) 
  do
    table.insert(inv_var, { amount=0, equip=0, stats=v })
  end
return inv_var
end
Would it work better if I had something like this?

Code: Select all

default_inventory = generate_inventory()
wesnoth.set_variable("inventory", default_inventory)
default_inventory = nil
Last edited by Dixie on August 13th, 2010, 1:56 pm, edited 1 time in total.
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Dixie's Lua Thread

Post by Anonymissimus »

The scope of a variable declared local where it's valid is limited to the function or file where it appears first, until the end of that function or file. (It's the same principle in other languages.)
Would I need to specifically do eq.weight = nil at some later point?
not in lua (it can be very important in C++...)

EDIT
In your case above, deducting from silene above, who said that it's limited to the "current block" which can also be an if then end statement, eq lives until the end of the function but its content may live further at that point where get_eq_stats is called if you catch the returned value in a variable.

EDIT2
Regarding your problem, you probably create subtables instead of named fields so I'd try leaving away the {} when inserting the fields. That's what I call table confusion, it's somehow hard to get a good debug message of inv_var (in your case) that shows the structure of the table.
Last edited by Anonymissimus on August 13th, 2010, 2:14 pm, edited 2 times in total.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:Hm, good catch about local. The variable eq is local to the function it's in.
More precisely, the name of the variable is local to the function. But the content of the variable stays alive as long as needed. Once the function has ended, you can no longer use the name to access the content, but if you have other ways to access it, it will stay around.
Dixie wrote:Would that if statement write eq.weight to _G, or would it still keep it local to the function?
Nothing writes to _G in your function. "eq.weight" is just a field of the table "eq". As long as this table exists (under this name or another), its fields exist too.
Dixie wrote:Would I need to specifically do eq.weight = nil at some later point?
It probably won't be called "eq.weight" since the name "eq" no longer exists, unless you have decided to give the value returned by the function the name "eq".

Anyway, while uncommon, there are situations where one wants to write nil to a field of a table or to a global variable (which is just a field of _G). As I said above, values will stay around as long as there is still a way to access them. Writing nil to all the names of a value ensures that the value can no longer be accessed, hence freeing memory earlier. For now, I doubt you have a use for this optimization. A better usage of nil is to make a field disappear from a table: once you have done "eq.weight = nil", all the users will see the table as empty (no "weight" field at all).
Post Reply