Variables & Local Variable in LUA

Posted by Tkl1129 on Thu 07 Jul 2011 05:33 AM — 29 posts, 108,268 views.

Hong Kong #0
I'm using the Immediate Box to testing code...

I found that if I set a = 1,
and then do another caluculation like b = 1+2+3...just for an example, when I close the box, and try /print(a)
it show "1", if like that, why I'm able to SetVariable to Mush, and do local var in script, only type a = xxx also shown as a global var...

Thanks, I'm newbie on Lua & Mush :D
USA Global Moderator #1
It looks like the Immediate box and the input bar just share the same local scope.
USA #2
If you're just using "a = 1", that sets 'a' as a global. You need 'local a' first so Lua knows you want it to be a local. Globals are accessible from anywhere (aliases, triggers, any kind of script except other plugins), which is why you can see 'a' from other places.

If you were to use 'local a = 1' in the Immediate window, you wouldn't have access to that local after the Immediate code is finished running.


SetVariable() is useful for a few things. The big three I know of are: (1) exposing values to other plugins that use GetPluginVariable(); (2) saving the plugin's state between MUSHclient sessions; (3) expanding into the match text of a trigger with "Expand variables" enabled. If you're not doing any of these things, plain Lua variables are probably better. Also SetVariable/GetVariable values can only be strings. Lua values can be strings, numbers, tables, functions, et cetera.
Australia Forum Administrator #3
Fiendish said:

It looks like the Immediate box and the input bar just share the same local scope.


They do.

See http://gammon.com.au/forum/?id=10863 for a discussion of variables.
Australia Forum Administrator #4
Although I should amend that to "scope" not "local scope".

I think the immediate window will be a compilation block and local variables will only have scope there.
Hong Kong #5
Oh..-.-"

Thats mean unless I'm able to share value via different groups or plugins that I will use SetVaribles in mush, if just for normal coding, I use a = 1 is more convinience, right? I still have few questions.

1. Do the Lua Global Variables eat memory? since I don't know how many I'd add before, is that a good practice that always "nil" to delete it? :D

2. In same script
a = 1 -- LUA Global Var
Local a = 2 -- Lua Local Var
print(a) -- return local var

if in this case, I'm sure better won't set in same name is better but if really got same name, can I get the value at the same time?...

I just reading the Programming in Lua ...Ch.1 to 4...-_-!..drive me crazy as I'm only know zscript before...my god~~~
Australia Forum Administrator #6
Anything eats memory, but values are garbage-collected eventually. Setting a variable to nil will encourage that.


print(a)


prints either a local or global variable.
Hong Kong #7
yeah..It print(a) --> LUA local value,
but how do I get the LUA Global value "1"?

Global a is "1"
Local a is "2"

after those code print(a) = 2

then I have no chance to get Global one in this case?
USA #8
Tkl1129 said:
Thats mean unless I'm able to share value via different groups or plugins that I will use SetVaribles in mush, if just for normal coding, I use a = 1 is more convinience

Well, sharing values between plugins is relatively rare, but if that's your aim then SetVariable and GetPluginVariable are definitely what you want. For normal coding, the choice between global and local depends on how long you need the value. If you store the result of a calculation in a variable and only Note() it immediately afterwards, you'd want a local. But if multiple aliases/triggers/times/etc. want use a single variable, a global is the simplest solution.

Tkl1129 said:
1. Do the Lua Global Variables eat memory? since I don't know how many I'd add before, is that a good practice that always "nil" to delete it? :D

If they take more room than a local, it's probably a very small amount. Locals can be used very quickly with a single Lua operation, but globals take an extra operation to load the value from the globals table. In practice it's not going to make any difference.

But yes, it's a good idea to set a global to nil when you're done using that value. It'll at least save space in the globals table. Locals are deleted automatically when they go out of scope, so you don't have to worry about them.

Tkl1129 said:
2. In same script
a = 1 -- LUA Global Var
Local a = 2 -- Lua Local Var
print(a) -- return local var

if in this case, I'm sure better won't set in same name is better but if really got same name, can I get the value at the same time?...

Yes, that's how the code will behave. This is called "shadowing", because the global of the same name is basically hidden in the local's shadow. You can't access a shadowed variable until the name shadowing it goes out of scope. However, globals have a workaround in that you can use _G["a"] to access a global by name. _G is the name given to the special table where globals are stored. Of course, if you had a local named _G as well you'd be out of luck! (Also, the 'local' keyword must be all-lowercase. ;D)

More precisely, 'local' creates a new slot for a local variable, and binds the name to that slot. Until the new binding goes out of scope, you can't access the shadowed variable.
local a = 42  -- slot 0
do
  local a = 50  -- slot 1
  print(a)  -- prints 50
end
print(a)  -- prints 42


Tkl1129 said:
I just reading the Programming in Lua ...Ch.1 to 4...-_-!..drive me crazy as I'm only know zscript before...my god~~~

Hah, it's a pretty big change, yeah. If anything I've explained here is confusing, don't worry too much about it - I'm dipping into some lower-level details in some places. The vanilla mechanisms are really all you need to worry about.
Amended on Thu 07 Jul 2011 07:53 AM by Twisol
Australia Forum Administrator #9
Tkl1129 said:

... then I have no chance to get Global one in this case?


Well you do, but I would reconsider why you would want to. Perhaps different names?

Consider this:


a = 1
print (a) --> 1

local a = 2

print (a) --> 2


However you can get at the global "a" in a couple of ways:


print (_G.a) --> 1 
print (getfenv () . a) --> 1


First the _G table is a table of global variables, therefore getting key "a" from it gives global "a".

However you *could* assign nil to _G (although this might be a strange thing to do). But the getfenv function always returns the "environment" in which you are currently running (which is a table) and thus you can then dereference that to get the global variable "a".

But I recommend against such convoluted programming style.


Amended on Thu 07 Jul 2011 08:00 AM by Nick Gammon
USA #10
Nick Gammon said:
However you *could* assign nil to _G (although this might be a strange thing to do). But the getfenv function always returns the "environment" in which you are currently running (which is a table) and thus you can then dereference that to get the global variable "a".

However you *could* assign nil to getfenv, as well. Lovely!

The most bulletproof thing to do is indeed to just use a different name. :D
Amended on Thu 07 Jul 2011 08:03 AM by Twisol
Hong Kong #11
Oh nice,
I know the concept now XD

slot 0 -> 1

It's a good practice that I always use "do" + "end"..I think :P

ya..as I play zmud for 5+ years, it's really hard to change my mind to accept a new language, but for long term I think LUA is more usful and powerful :P..
Hong Kong #12
*could" XD...I like this :P

and I just do a stupid thing...LUA Global, after quit Mush, reopen world, the LUA global var return to nil XD

thats mean I don't have to "nil" everytime....actually just use another name is more better -_-"

just my logical question about LUA...Thanks to ALL~~ O_O"
USA #13
Yep, no Lua variables are saved when the program ends. MUSHclient does save the contents of the SetVariable/GetVariable variables though, which as I noted is one of their three big uses. :)
Australia Forum Administrator #14
Twisol said:

However you *could* assign nil to getfenv, as well. Lovely!


Lol. Yes you *could* do that.

There are a lot of things you could do. ;)

@Tkl1129 - the language is Lua, not LUA. May as well get the name right.

It is very powerful, that power can be abused. Your ultimate goal would hopefully be to write scripts that work well, and also are very easy to maintain.
USA #15
Mushclient should have a super _G for cross plugin lua variables!

In world

superglobal x="hi"


In plugin

tprint(_SG)

...

"x"="hi"

:)
USA #16
That's awfully difficult to do, since every plugin has its own script space. If you had an _SG table, you'd need to copy anything in it to every other plugin. And some values, like tables, can be changed without affecting _SG, so there's no easy way to tell the other plugins that the table changed.
USA #17
Yes, that was more of an idle thought. A more realistic solution is to just let CallPlugin call functions from the main world, since lua variables can be returned directly from CallPlugin.
Australia Forum Administrator #18
You can get at main world client variables (not Lua variables) easily enough.

But really, the whole idea of plugins is they are self-contained, otherwise they could all have shared the same script space.

I would personally regard "main world" scripts and variables for things like testing scripts before they go into plugins, or for minor additions to a particular world.

Plugins give you the flexibility to have self-contained scripts, variables, etc. and also can easily be shared between different world files (eg. different characters on a particular MUD).

Another useful thing you can do with plugins is impose "source control" on them. That is, install Git and then do a "git commit" from time to time, to keep track of what changes you are making and when. This helps keep track of earlier versions. Often it is helpful when dealing with scripts to look back at an earlier version and see why feature X might have worked before but has stopped working now.

Of course you can do that with the main world file as well, but with everything in together it is less easy to see what purpose each part has.
USA #19
I've thought about doing it that way, but the sacrifice you make with plugins is that it's not easy to edit their trigs and aliases on the fly. What's the point of having mushclient's nice trigger/alias GUI if all your important triggers and aliases are in plugins? Seems a bit like subverting the whole client.
USA #20
Also while I understand the idea of plugins being self-contained, that's already been compromised pretty thoroughly. Plugins have huge amounts of infrastructure for communicating with each other, just not with the main world.
Hong Kong #21
case sensitive..Lua~~~..right -_-"

Actually I check via wiki, Lua is a script language that mainly for Game purpose, do there any other usage of it? just like Javascript for web, I just want to know the benifit besides mud and game developing if I learn "Lua" very well XD....

For sure, my mainly purpose is enjoy the fun from make AI robot system for mud, great UI and plugin but I decide change from z/cmud to mush, it really take time to learn, and no zscript that I learn jscript / VBscript / Lua is no difference for me :D...
I choose Lua because everybody said it's powerful only -.-"...

I have further question about mush, I make it in other post, thanks for all guys suuuuuport me to learn...lol
Hong Kong #22
plugins....

I'm also considering about the script structure of my new trigger in mush...which part put in script file...which part put in core world file..which part put in plugin file...it's totally different concept with Cmud..-.-"
Australia Forum Administrator #23
Candido said:

I've thought about doing it that way, but the sacrifice you make with plugins is that it's not easy to edit their trigs and aliases on the fly. What's the point of having mushclient's nice trigger/alias GUI if all your important triggers and aliases are in plugins? Seems a bit like subverting the whole client.


It's not that bad. The XML in the triggers is pretty self-documenting, so changing something like:


enabled = "y"


isn't that much harder to follow then checking or unchecking a box.

To add whole new batches of triggers/aliases you can do what I do ... set one or more up up in the GUI interface, then hit the Copy button, switch to the plugin, and paste the resulting XML in.

You can also organise plugins better by using the XML comments, and grouping related things together (you can have more than one set of triggers in a plugin).

Australia Forum Administrator #24
Tkl1129 said:

case sensitive..Lua~~~..right -_-"

Actually I check via wiki, Lua is a script language that mainly for Game purpose, do there any other usage of it? just like Javascript for web, I just want to know the benifit besides mud and game developing if I learn "Lua" very well XD....


Lua is pretty widely used, whereas zscript is for a particular MUD client.

Apart from other game-related instances (eg. World of Warcraft) it is a powerful general tool. For example, a while back I used a Lua script to process hundreds of email messages in individual files, locate the message headers, etc. and then put the resulting messages into a MySQL database.

Compared to things like Javascript, Lua is very compact and easy to learn IMHO.
Hong Kong #25
Oh..thats mean if I want to manage plugins well...except makes new plugin copy from tri & alias...I'm also able to learn the format of XML ?

-_-"...what a big project..
USA #26
It's really pretty easy to deal with. I usually just copy the <plugin> prologue from another plugin and change the name, id, etc., add a <script> section for my code, and export aliases/triggers from MUSHclient and paste them somewhere else. For example, this is a good skeleton plugin:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>

<!-- Change everything here to fit your plugin -->
<!-- Get a new ID from Edit -> Generate Unique Id -->
<plugin
   name="MyPlugin"
   author="Soludra"
   id="043e0976013412f26cf9a395"
   language="Lua"
   purpose="Stuff"
   date_written="2011-07-07"
   requires="4.74"
   version="1.000"
   >
</plugin>

<!-- Paste aliases, triggers, etc. here. -->

<script><![CDATA[

-- Code goes here!

]]></script>
</muclient>
Amended on Fri 08 Jul 2011 04:03 AM by Twisol
Australia Forum Administrator #27
Tkl1129 said:

Oh..thats mean if I want to manage plugins well...except makes new plugin copy from tri & alias...I'm also able to learn the format of XML ?

-_-"...what a big project..


It's not that big. ;)

Triggers, aliases and timers are either easily modified or copied from the GUI interface. The rest is basically the script part or stuff you are unlikely to modify often.

I suggest you stop thinking along the lines of "how do I convert zscript to MUSHclient scripting?" and start thinking about what is the underlying problem you are trying to solve.

There are a lot of examples on this website, and various plugins that other people have written are a good guide to how you can go about things. Stuff like mappers, healing systems, health bars, etc.

Hong Kong #28
I'm trying my best to do it /_\"...

I'd read many many post and reading the book "programming in Lua" already..-.-"

Lua basics I can learn from book...those function also can, but I keep ask here because I want to find a shortcut to access which part I'm able to learn...or some part even I read book and read post still don't understand XD...zscript, I throw it away already XD, when I decide to learn Lua :P

I will try harder to read the post in forum..hope can answer my "stupid" questions :P