Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Due to spam on this forum, all posts now need moderator approval.
Entire forum
➜ MUSHclient
➜ Lua
➜ tables, and functions as keys?
|
tables, and functions as keys?
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Pages: 1 2
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Sun 08 Apr 2007 08:19 PM (UTC) |
| Message
| Is there anyway to use a function as a key in a table, say from your healing script idea?
such as:
afflictions = { }
afflictions = {
{name = 'paralysis', cure = eat_bloodroot (), }
{name = 'stupidity', cure = eat_goldenseal (), }
}
This way I could reference the name and call the appropriate function to cure?
| | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #1 on Sun 08 Apr 2007 08:52 PM (UTC) |
| Message
|
Quote:
afflictions = { }
afflictions = {
{name = 'paralysis', cure = eat_bloodroot (), }
{name = 'stupidity', cure = eat_goldenseal (), }
}
You mean a value, right? From your post, the function is on the right which is the value. The word "cure" is the key.
You are on the track here, but but using the round brackets it is called immediately. Just drop them. Also, you don't need to make the table twice.
afflictions = {
{name = 'paralysis', cure = eat_bloodroot, }
{name = 'stupidity', cure = eat_goldenseal, }
}
In this example you have a table "afflictions" which is a numerically keyed table, that you would have to linearly scan, and when you find a match, the sub-table will have a function which is the cure.
Unless you have a reason for the linear scan, it might be simpler to key on the affliction name, like this:
-- define functions
function eat_bloodroot ()
print "in eat_bloodroot"
end -- function eat_bloodroot
function eat_goldenseal()
print "in eat_goldenseal"
end -- function eat_goldenseal
-- table of afflictions
afflictions = {
paralysis = eat_bloodroot,
stupidity = eat_goldenseal,
}
-- test it
s = "stupidity" -- test
f = afflictions [s] -- look up affliction
if f then -- not-nil means we found it
f () -- so call function
end -- affliction found
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #2 on Sun 08 Apr 2007 09:10 PM (UTC) |
| Message
| yes, sorry, I ment value, not key. The linear scan would act as a prioritized queue, as per the post you made awhile back.
Is there any chance you could explain exactly why metatables are so important?
Thanks again | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #3 on Sun 08 Apr 2007 09:37 PM (UTC) |
| Message
| Ah yes, I knew there was a reason. The same basic idea holds, you scan the table, and once you have the function name you can call it. The nice thing about functions in Lua is you can assign them. eg.
f = function (s) print "in f" end
f1 = f -- assign function to f1
f1 () -- now call it
Quote:
Is there any chance you could explain exactly why metatables are so important?
You can certainly live without metatables, however they give you the capability to alter the behaviour of tables, to an extent.
A metatable is a secondary table which is "attached" to a main table with 'setmetatable (table, metatable)'. You can then put functions into the metatable to handle things like:
- Key not found (eg. return a default value)
- Attempt to add a new key (eg. fail, add somewhere else)
- String conversion (eg. print something nicer than 'table: 00CDB5A8', when you attempt to print a table value)
- Handle arithmetic and comparison. (eg. if a table represents a mathematical quantity, like a matrix, then you could "add" or "subtract" tables)
- Handle concatenation (eg. concatenate two tables)
- Specify weak keys / values
- Allow tables to be called, as if they were a function
The Programming In Lua books gives some examples, but if you can't think of a reason, don't worry. I don't use metatables much myself. Probably the "missing key" (__index) and "new key" (__newindex) operations are the ones I use the most. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #4 on Sun 08 Apr 2007 10:41 PM (UTC) |
| Message
| | Why might I need to assign a function to a different name? | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #5 on Sun 08 Apr 2007 11:24 PM (UTC) |
| Message
| Well, as in my example above:
f = afflictions [s] -- look up affliction
if f then -- not-nil means we found it
f () -- so call function
end -- affliction found
I am looking up the key in the table, the value is the function. So I assign it to f, check if not nil, and if not nil, call the function. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #6 on Tue 10 Apr 2007 06:39 PM (UTC) |
| Message
| Still having a touch of an issue...
function afflict.shiver (n,o,wc)
aff.shiver = true
Note ('calling queue')
queue ()
end
aff=
{
-- Drink affs (cold)
shiver=false,
frozen=false,
}
cures= {
{name='frozen', heal=drink.fire,},
{name='shiver', heal='drink.fire',},
}
function drink_fire ()
if bal.purg then
Send ("drink fire")
cure.drink = "fire"
bal.purg = .5
DoAfterSpecial (.5, 'reset.purg ()', 12)
end
end
-- Basically Send ('drink fire')
function queue ()
for _, v in ipairs (cures) do
if aff [v.name] then
Note (v.name)
if v.heal then
Note (v.heal)
v.heal ()
return
end
end
end
end
Now, the errors I receive..
Run-time error
World: Laeric on Lusternia (Ur'Guard)
Immediate execution
...rogram files/mushclient/scripts/lusternia/tables.lua:102: attempt to index global 'drink' (a nil value)
stack traceback:
...rogram files/mushclient/scripts/lusternia/tables.lua:102: in main chunk
[C]: in function 'dofile'
.../program files/mushclient/scripts/lusternia/init.lua:1: in main chunk
[C]: in function 'dofile'
[string "Script file"]:1: in main chunk
basically I use drink. as a prefix before all of my functions that involve drinking.. drink.health, drink.whatever..
if I change it to heal='drink.fire', i get..
Error number: 0
Event: Run-time error
Description: ...program files/mushclient/scripts/lusternia/queue.lua:8: attempt to call field 'heal' (a string value)
stack traceback:
...program files/mushclient/scripts/lusternia/queue.lua:8: in function 'queue'
.../program files/mushclient/scripts/lusternia/cold.lua:16: in function <.../program files/mushclient/scripts/lusternia/cold.lua:12>
Called by: Function/Sub: afflict.shiver called by trigger
Reason: processing trigger ""
Which I assume means I can't call a string as a function..
if I change it to heal=drink_fire, (and the appropriate function..)
I get this for output:
calling queue
queue
shiver
So what am I doing incorrectly? Heh is there anyway to maintain my healing function names as drink.(whatever potion to sip)? | | Top |
|
| Posted by
| David Haley
USA (3,881 posts) Bio
|
| Date
| Reply #7 on Tue 10 Apr 2007 07:17 PM (UTC) |
| Message
| You want to store the field as a function:
-- CREATE the drink table:
local drink = {}
-- FILL in the functions:
function drink.fire ()
if bal.purg then
Send ("drink fire")
cure.drink = "fire"
bal.purg = .5
DoAfterSpecial (.5, 'reset.purg ()', 12)
end
end
function drink.whatever()
Send ("drink whatever")
end
-- set up the cure table
-- NOTE the lack of quotes around the function names!
cures= {
{name='frozen', heal=drink.fire,},
{name='shiver', heal=drink.fire,},
}
Now, you can do something like:
cures[1].heal()
or iterate over them, calling v.heal() as you were. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #8 on Wed 11 Apr 2007 12:57 AM (UTC) |
| Message
| Sorry I didn't put in this line
drink= { }
should it be local? | | Top |
|
| Posted by
| David Haley
USA (3,881 posts) Bio
|
| Date
| Reply #9 on Wed 11 Apr 2007 01:37 AM (UTC) |
| Message
| | Doesn't have to be. I did it out of habit, because it's always better to not add global variables (global to the entire program as opposed to just the file in question) unless you have to. If you make a variable 'local' at the top-level of a file, then it is global to that entire file. (More technically speaking, it is local to the chunk, which in this case is the string containing the contents of the file.) |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #10 on Wed 11 Apr 2007 12:55 PM (UTC) |
| Message
| | still didn't work, does it matter that the different components are split up into different files? | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #11 on Wed 11 Apr 2007 01:08 PM (UTC) |
| Message
| What was the error message? "Didn't work" is pretty vague.
Different files doesn't matter, as long as you have the syntax right, the order of instructions right, the spelling right, etc. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #12 on Wed 11 Apr 2007 03:29 PM (UTC) |
| Message
| Very sorry, received a
Run-time error
World: Laeric on Lusternia (Ur'Guard)
Immediate execution
...ogram files/mushclient/scripts/lusternia/healing.lua:144: attempt to index global 'drink' (a nil value)
stack traceback:
...ogram files/mushclient/scripts/lusternia/healing.lua:144: in main chunk
[C]: in function 'dofile'
.../program files/mushclient/scripts/lusternia/init.lua:10: in main chunk
[C]: in function 'dofile'
[string "Script file"]:1: in main chunk
error, when I changed drink to local drink, I'm assuming because that made the table local to the file, as opposed to all files compiled.. | | Top |
|
| Posted by
| David Haley
USA (3,881 posts) Bio
|
| Date
| Reply #13 on Wed 11 Apr 2007 04:19 PM (UTC) |
| Message
| It shouldn't matter because the function pointer (drink.fire) is in the same file as the local table. However, I'm not sure how exactly you have split everything up, so it might be safer to make it non-local.
One thing I note that concerns me is that nearly every error message you have shown us is coming from a different source file. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | | Top |
|
| Posted by
| Gore
(207 posts) Bio
|
| Date
| Reply #14 on Wed 11 Apr 2007 04:33 PM (UTC) Amended on Wed 11 Apr 2007 04:35 PM (UTC) by Gore
|
| Message
| Yes, queue.lua will contain all of my different queue functions, for potion afflictions, eating/smoking afflictions, etc.
healing.lua contains all of the functions regarding actually healing, drinking potions, eating herbs, smoking, applying etc
Quote: if I change it to heal='drink.fire', i get..
Error number: 0
Event: Run-time error
Description: ...program files/mushclient/scripts/lusternia/queue.lua:8: attempt to call field 'heal' (a string value)
stack traceback:
...program files/mushclient/scripts/lusternia/queue.lua:8: in function 'queue'
.../program files/mushclient/scripts/lusternia/cold.lua:16: in function <.../program files/mushclient/scripts/lusternia/cold.lua:12>
Called by: Function/Sub: afflict.shiver called by trigger
Reason: processing trigger ""
I'm assuming the error is in the queue.lua file, with queue (), when it attempts to call heal, but the contents of heal is a string.
Quote: Now, the errors I receive..
Run-time error
World: Laeric on Lusternia (Ur'Guard)
Immediate execution
...rogram files/mushclient/scripts/lusternia/tables.lua:102: attempt to index global 'drink' (a nil value)
stack traceback:
...rogram files/mushclient/scripts/lusternia/tables.lua:102: in main chunk
[C]: in function 'dofile'
.../program files/mushclient/scripts/lusternia/init.lua:1: in main chunk
[C]: in function 'dofile'
[string "Script file"]:1: in main chunk
is from when I have it set as cure=drink.fire, it's saying that drink is a nil value, I think?
Edit: I'm going to write a smaller version of this in one file to try and see if I can make something that's exactly what I'm doing, but set up for test purposes instead..
Thanks for all your help
| | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
69,205 views.
This is page 1, subject is 2 pages long: 1 2
It is now over 60 days since the last post. This thread is closed.
Refresh page
top