Register forum user name Search FAQ

Gammon Forum

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,201 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.