You are not logged in.

Applications: [GameMaster: OPEN] | [Volunteer Testers: OPEN]


This forum will be permanently shut down on Friday 13.07.2018
Please copy or save all important information from old forum before they will be deactivated
We have moved to new board. https://forum.runesofmagic.gameforge.com/Come join us.

Peryl

Intermediate

  • "Peryl" started this thread

Posts: 313

Location: Elsewhere

  • Send private message

1

Thursday, February 2nd 2012, 12:40am

[repost] Avoiding Common Lua Errors

This is a repost since the original seems to have gone AWOL during the forum restructuring


I've been seeing a lot of the same errors cropping up in the DIYCE code that people have been posting and asking help about. These errors however are rather simple and, given a bit of knowledge, can easily be avoided. This is what I hope to show you. How to recognise and avoid making these simple mistakes. So here are a few rules you can use to help avoid problems in the first place, or if they do show up, you can find and correct them easily.


[SIZE=+2]Indentation Is Important[/SIZE]
Lua, as a programming language, pretty much ignores whitespace. Unfortunately, this means that it also allows you to make a complete mess of the code visually. This in turn can make it rather difficult to see where a problem might be, or to make modifications to existing code.


Here's an example of bad code indentation. Spot the error?

Source code

1
2
3
4
5
6
7
8
9
function BuggyFunc (
arg1,
arg2,
arg3
   ) local   avar1, avar2,
avar3 = GetActionInfo(1)
if avar3 == "interface/icons/sys_transfer.dds" then
DEFAULT_CHAT_FRAME:AddMessage("Looks like there's a portal button on the action button 1");
end end



Maybe you do see it, maybe you don't, or maybe you think it is something else. Let us re-write this with proper indentation:

Source code

1
2
3
4
5
6
7
8
function BuggyFunc(arg1, arg2, arg3)
    local avar1, avar2, avar3 = GetActionInfo(1)


    if avar3 == "interface/icons/sys_transfer.dds" then
        DEFAULT_CHAT_FRAME:AddMessage("Looks like there's a portal button on the action button 1");
    end
end



Now we can start to see where the problem might lie. The call to GetActionInfo() is returning its values into avar1, avar2, and avar3. Not just avar3 as is implied when looking at the code previously. Proper indentation allows us to avoid such problems. This of course doesn't mean that all problems magically go away, but why make life harder on yourself for no good reason? Use proper indentation.




[SIZE=+2]Avoid Unnecessary Parentheses[/SIZE]
A very common problem that pretty much everyone does, pro and amateur alike, is to use too many parentheses. This can easily lead to having mismatched parentheses and causing the code to fail. Now it should be mentioned that the opposite can also be true, and problems can occur when Lua decides to group operations in unexpected ways. This is why some parentheses are needed, just don't go overboard with them.


To do a quick check to see if you have a mismatch problem, start with a count of zero at the beginning of a line of code, and add one to this cound each time you open a parenthesis, and subtract one when you encounter a close parenthesis. If you reach the end of the line of code with a count of zero, you should be good. If at anytime while you are counting you end up with a negative number, you have an extra close parenthesis.


Though the above can help you identify if you have a mismatch problem, by not putting extraneous parentheses in the first, you place can avoid many problems. To help achieve this it is important to keep Lua's operator precedence in mind.


Here's a table of Lua's operator precedences (taken from http://www.lua.org/pil/3.5.html)

Quoted


Operator precedence in Lua follows the table below, from the higher to the lower priority:

Source code

1
2
3
4
5
6
7
8
^
not  - (unary)
*   /
+   -
..
<   >   <=  >=  ~=  ==
and
or

All binary operators are left associative, except for `^´ (exponentiation) and `..´ (concatenation), which are right associative. Therefore, the following expressions on the left are equivalent to those on the right:

Source code

1
2
3
4
5
a+i < b/2+1          <-->       (a+i) < ((b/2)+1)
5+x^2*8              <-->       5+((x^2)*8)
a < y and y <= z     <-->       (a < y) and (y <= z)
-x^2                 <-->       -(x^2)
x^y^z                <-->       x^(y^z)

When in doubt, always use explicit parentheses. It is easier than looking up in the manual and probably you will have the same doubt when you read the code again.





[SIZE=+2]Match the "end" Statements[/SIZE]
This sort of goes hand-in-hand with indentation, but I thought I'd also mention it seperately. The end statement in Lua is used to close out a block of code. Namely the following Lua statements all use end to terminate their code blocks.
  • if
  • do
  • for
  • while
  • function
Each of these statements expects to close out their respective code blocks with an end statement. So make sure that they have them. Proper indentation will help identify missing or extranous end statements.




[SIZE=+2]Get to Know Lua Error Messages[/SIZE]
When an error happens, and when you are creating Lua functions be it for DIYCE or something else you will encounter Lua errors, the Lua engine will spit a message at you. Do not ignore this message, Lua is trying to tell you that something is wrong. It might not know exactly what the problem is, but at least it is a beginning point.


The list of errors is a little too long for this little guide, but start getting to know what the errors mean, and what to do about them. Granted some can be a little cryptic, but even if you don't quite get what the Lua engine is trying to tell you, it will usually give you a line number so that you can go see where it is having trouble.


One of the most common errors that you are likely to see is the dreaded attempt to call global <insert some name here> (a nil value). What Lua is trying to tell you is that it doesn't know what the function is. As far as it is concerned that name doesn't exist. In Lua, when something doesn't exist, it is considered to have a value of nil. The likeliest candidate for this error is that there is a syntactical error in the definition of your function (this is assuming that you typed the name correctly when trying to run it of course).




[SIZE=+2]Posting Your Code[/SIZE]
So you've looked through your code, applied the above guidelines, and things are still not working. Now what?


By all means, post your code and mention what is going wrong. Mention as many details as you can. What you expect the code to do, what it is doing (if anything), any error messages that gets displayed etc. This will help others figure out what it is doing and what it is supposed to do.


When you do post your code, please place code tags around the posted Lua code. This will ensure that the code shows up with correct indentation, as well as having it show up in a fixed-width font (meaning column alignment is preserved across lines). This makes your posted code infinitely more readable.


To use the code tags, place your code between [noparse]

Source code

1
[/noparse] and [noparse]
[/noparse] BB-code tags.


Here's what I used for the example code shown in the identation section above:

Source code

1
2
3
4
5
6
7
8
9
10
[noparse]
[code]
function BuggyFunc(arg1, arg2, arg3)
    local avar1, avar2, avar3 = GetActionInfo(1)


    if avar3 == "interface/icons/sys_transfer.dds" then
        DEFAULT_CHAT_FRAME:AddMessage("Looks like there's a portal button on the action button 1");
    end
end

[/noparse]
[/code]


You might also be interested in some of the other BB-code tags. Go to this link: http://forum.us.runesofmagic.com/misc.php?do=bbcode or use the link in the "Posting Rules" box at the bottom of any thread and click the BB code name there.
2013... The year from hell....