Correcting bad practices

I thought it would be a good idea for people to post bad practices that we see in lua a lot that make inefficient code
maybe someone will actually read this thread and use it to better their coding!

I’ll start:

declaring all of your variables at the beginning of a function, even though the function might return before that variable is used!
people should keep in mind that Lua’s memory management is rather slowww

EX.
[lua]
function RPName(name)
local len = string.len(name)
local low = string.lower(name)
if len > 20 then
return false --well now we don’t need low, their name’s too long
end
–low should be defined here, after we’ve made sure their name isn’t too long
– insert some check for allowed characters, using the variable ‘low’
end
[/lua]

  • snip - Forget it. I’m a dumb.

[lua]
hook.Add(“Think”, “EndOfTheWorld”, function()
print(“Oh god, what have I done?”)
end)
[/lua]

I don’t get it.

Depends on what you do.

I mean something like this

hook.Add(“Think”,“hurp”,function() while true do end end);
is pretty bad indeed.

Uhm, what?
No, if bad things happen you’re stupid and doing it wrong.

It’s a perfectly fine hook to use so long as you don’t create a bunch of tables or do a ton of looping every tick.

What are you even talking about. Think is necessary for a lot of things…

I think a bad practice is suggesting things when you have no idea what you’re talking about.

Anyway I have a terrible habbit of doing stuff like this:

[lua]
function nameIsValid( name )
if ( string.len(name) > 50 ) then
return false;
else
return true;
end
end
[/lua]

another thing, related to string handling, is unnecessary use of regex
Regex has a huge overhead, and it’s much more efficent to just access a string one character at a time

I.E. DarkRP’s Name check
[lua]
local allowed = {‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘0’,
‘q’, ‘w’, ‘e’, ‘r’, ‘t’, ‘y’, ‘u’, ‘i’, ‘o’, ‘p’,
‘a’, ‘s’, ‘d’, ‘f’, ‘g’, ‘h’, ‘j’, ‘k’, ‘l’,
‘z’, ‘x’, ‘c’, ‘v’, ‘b’, ‘n’, ‘m’, ’ ',
‘(’, ‘)’, ‘[’, ‘]’, ‘!’, ‘@’, ‘#’, ‘$’, ‘%’, ‘^’, ‘&’, ‘*’, ‘-’, ‘_’, ‘=’, ‘+’, ‘|’, ‘\’}

for k in string.gmatch(args, ".") do
	if not table.HasValue(allowed, string.lower(k)) then
		Notify(ply, 1, 4, string.format(LANGUAGE.unable, "RPname", k))
		return "" 
	end
end 

[/lua]
terrible unnecessary usage of Regexp
a more efficient way to achieve the same thing would be like so:

[lua]
local low = string.lower(args)
local allowed = {‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘0’,
‘q’, ‘w’, ‘e’, ‘r’, ‘t’, ‘y’, ‘u’, ‘i’, ‘o’, ‘p’,
‘a’, ‘s’, ‘d’, ‘f’, ‘g’, ‘h’, ‘j’, ‘k’, ‘l’,
‘z’, ‘x’, ‘c’, ‘v’, ‘b’, ‘n’, ‘m’, ’ ',
‘(’, ‘)’, ‘[’, ‘]’, ‘!’, ‘@’, ‘#’, ‘$’, ‘%’, ‘^’, ‘&’, '’, ‘-’, ‘_’, ‘=’, ‘+’, ‘|’, ‘\’}
for i=1, string.len(low) do
if not table.HasValue(allowed, low
) then
Notify(ply, 1, 4, string.format(LANGUAGE.unable, “RPname”, k))
return “”
end
end
[/lua]

Still uses table.HasValue and over uses string.sub due indexing the string.

The really most efficient way is probably hardcoding it like this.

[lua]
local low = string.lower(args);
local len = string.len(low);
local char;
for i=1, len do
char = string.byte(low, i);
if((char == 32) or //exclamation mark
(char == 33) or //whitespace
(char >= 35 and char <= 38) or//# - %
(char >= 40 and char <= 43) or //( - +
(char == 45) or //minus
(char >= 48 and char <= 57) or//0-9
(char == 61) or //equal
(char >= 91 and char <= 95) or //[ - _
(char >= 97 and char <= 122) or //a-b
(char == 124)) then //vertical line
Notify(ply, 1, 4, string.format(LANGUAGE.unable, “RPname”, k))
return “”
end
end
[/lua]

Also, Lua doesn’t use Regex.

It can.

yah, that method is better than mine, I didn’t even think of that, GG

@TGiFallen it’s not a POSIX implementation of regex, but lua pattern matching is the same idea and general syntax

Maybe not so much coding related but style. Mostly just for making code easier to read and trouble shoot.
[lua]
–More preference but i like to add a description/goal/thought process for what my function is supposed to do
function UsefulNameHere() --Use a name for your function that actually relates to what it does.
local DescriptiveVariableName = 0 --Same goes for variables. Also indent for better legibility.
–Maybe add a gap between all your variables that you just made and the rest of your code.
if DescriptiveVariableName > 0 then
return true --Indent again
end
end
[/lua]

With a module it can. With modules it can do anything.

The built in Lua string functions generally use lua patterns which somewhat resemble regex, but are a lot simpler, and lack some features of regex.

I recently broke out of the habbit of spacing my parenthesis. Not really a bad practice, but I can code much faster now that I don’t need to space every parenthesis or bracket.

PlayerCanHearPlayersVoice != PlayerCanHearPlayerVoice

I think you want the thread below this one.

[editline]4th October 2011[/editline]

Oh, nevermind, I see what you did there.

I always wonder if lua will check things twice if you put additional parentheses

[lua]
if (iTimeLeft < 0) then
– ^ is iTimeLeft smaller than 0?
– ^ does the stuff inside the parentheses evaluate to true?
EndRound()
end
[/lua]

I mean would removing the parentheses result in the same bytecode?

Do a runtime check, you’ll figure it out.

[editline]6th October 2011[/editline]

What the fuck.

[lua]
local t = SysTime();
for i = 1,100000000 do
if(true) then
end
end
print(SysTime() - t);

local t = SysTime();
for i = 1,100000000 do
if true then
end
end
print(SysTime() - t);
[/lua]

Evaluates to:

11.181411743164
10.893539428711

Seriously, what the fuck?

From what i understand, yes
I do believe when it is converted to C++ or whatever it automatically adds a ( after then if and a ) before the then.

@Wizard

Wow, thats amazing

I guess your cpu got hotter, which made it slower for the next shitton of stuff to evaluate.

11 seconds of nonstop cpu usage can make it go up about 7 or 8 degrees.