[LUA] Krótsze odpowiedniki w lua - autorstwa Grimkka
Aloszka, tutorial napisałem już całkiem dawno, ale żeby trochę poruszyć dział to postanowiłem go wrzucić (biorąc pod uwagę fakt, że ostatni post tu był napisany 2 lata temu :o).
________________
Poradnik poniżej jest po prostu listą skryptów które mogą być zoptymalizowane po przez ich skrócenie. Nie będę tłumaczył działania każdego z kodów, bo zajęłoby to po prostu wieczność. Jeśli już wiesz czego szukasz to powinieneś wiedzieć jak to działa. Zaczynajmy.
Zamiast pisania tej instrukcji w ten sposób:
Kod PHP:
//zle
x = 7
if x < 10 then
x = 10
end
Można to zrobić w ten:
Kod PHP:
//dobrze
x = 7
x = math.max(x, 10)
Tak samo zresztą z tym:
Kod PHP:
//zle
x = 23
if x > 20 then
x = 20
end
Kod PHP:
//dobrze
x = 23
x = math.min(x, 20)
A jeżeli chciałbyś oba złączyć, to nie piszemy tego:
Kod PHP:
//zle
x = 23
if x < 10 then
x = 10
elseif x > 20 then
x = 20
end
Tylko to:
Kod PHP:
//dobrze
x = 23
x = math.min(math.max(x, 10), 20)
Lub:
Kod PHP:
//dobrze
x = 23
x = math.max(math.min(x, 20), 10)
Funkcja math.min zwraca nam najniższą wartość, zaś math.max najwyższą.
Następna optymalizacja może nastąpić w tym skrypcie:
Kod PHP:
//zle
if x == 10 then
y = 100
b = 50
xybz = x + y + b + 35
elseif x == 20 then
y = 100
b = 50
xybz = x + y + b + 110
else
y = 30
b = 50
xybz = x + y + b + 20
end
Może być on skrócony do:
Kod PHP:
//dobrze
y = 100
b = 50
if x == 10 then
z = 35
elseif x == 20 then
z = 110
else
y = 30
z = 20
end
xybz = x + y + b + z
Kolejnym błędnym kodem będzie to:
Kod PHP:
//zle
if x == 10 then
y = 100
b = 50
xybz = x + y + b + 35
elseif x == 20 then
y = 40
b = 78
xybz = x + y + b + 76
elseif x == 30 then
y = 80
b = 50
xybz = x + y + b + 45
elseif x == 40 then
y = 100
b = 666
xybz = x + y + b + 144
elseif x == 50 then
y = 33
b = 45
xybz = x + y + b + 12
Wersja poprawna:
Kod PHP:
//prawie dobrze
function numbers(x, y, b, z)
return (x + y + b + z)
end
if x == 10 then
xybz = numbers(x, 100, 50, 35)
elseif x == 20 then
xybz = numbers(x, 40, 78, 76)
elseif x == 30 then
xybz = numbers(x, 80, 50, 45)
elseif x == 40 then
xybz = numbers(x, 100, 666, 144)
elseif x == 50 then
xybz = numbers(x, 33, 45, 12)
else
xybz = numbers(x, 100, 100, 20)
end
Lub jeszcze krócej:
Kod PHP:
//dobrze
results = {
[10] = {100, 50, 35},
[20] = {40, 78, 76},
[30] = {80, 50, 45},
[40] = {100, 666, 144},
[50] = {33, 45, 12},
default = {100, 100, 20}
}
result = results[x] or results.default
xybz = x + result[1] + result[2] + result[3]
A zamiast tego:
Kod PHP:
//zle
doSummonCreature("Rat", pos)
doSummonCreature("Rat", pos)
doSummonCreature("Rat", pos)
doSummonCreature("Troll", pos)
doSummonCreature("Troll", pos)
doSummonCreature("Orc", pos)
Możemy po prostu dodać pętle. Skrypt wtedy będzie wyglądał następująco:
Kod PHP:
//dobrze
local summons = {["Rat"] = 3, ["Troll"] = 2, ["Orc"] = 1}
for k, v in pairs(summons) do
for i=1, v do
doSummonCreature(k, pos)
end
end
Tutaj kolejny za długi skrypt który będzie nam dawał addony:
Kod PHP:
//zle
sexAddons = {
{[136]=142, [147]=150, [155]=158, [252]=252},
{[128]=134, [143]=146, [151]=154, [251]=251}
}
local addons = sexAddons[getPlayerSex(cid)+1]
if (addons ~= nil) then
for k, v in pairs(addons) do
for i=k, v do
doPlayerAddOutfit(player, i, addonType[1])
end
end
end
A w tej sytuacji wystarczy zrobić tylko to!:
Kod PHP:
//dobrze
numbers = {
[10] = 30,
[55] = 65,
[80] = 140
}
for start, stop in pairs(numbers) do
for number=start, stop do
print(number)
end
end
Jednym z kolejnych błędów podczas pisania kodu jest dodawanie nil'a - a jest on po prostu zbędny. Można to zobaczyć na przykładzie poniżej:
Kod PHP:
//zle
function doSomething(x)
if x == nil then
x = 1
end
return x
end
Kod PHP:
//dobrze
function doSomething(x)
return x or 1
end
Co tu się stało? Solucja problemu jest bardzo prosta. Jeżeli x = nil, lub false to po prostu bierze następną wartość.
Jeszcze większe skrócenie:
Kod PHP:
//dobrze
x = 5
y = 10
z = x or y or 5
Tu zaś skrypt najpierw sprawdza czy x = nil. Jeżeli tak, to później sprawdza czy y = nil. Teraz gdy oba = nil, to skrypt po prostu zamienia z w 5.
Kolejny przykład który nigdy nie zwróci nil'a:
Kod PHP:
//dobrze bobrze
function sum(a, b)
return (a or 0) + (b or 0)
end
W praktyce to wygląda tak:
Kod PHP:
print(sum(5, 10))
print(sum(5, nil))
print(sum(nil, 10))
print(sum(5))
Powyższy skrypt zwróci nam to:
A jeśli chcesz wiadomość która wysyła error to zamiast tego:
Kod PHP:
//zle
if x == nil then
if y == nil then
print("Error, all values are nil!")
else
z = y
end
else
z = x
end
Wpisz to:
Kod PHP:
//prawie dobrze
z = x or y or print("Error, all values are nil")
Teraz, gdy x = nil, z zamieni się w y, a jeżeli y = nil to silnik wyśle wiadomość "Error, all values are nil", ale z zamieni się w nil. Co zatem zrobić aby wysłać wiadomość i nadać z wartość?
Spójrz:
Kod PHP:
//dobrze
z = x or y or print("Error, all values are nil") or 0
Dzięki dodaniu "or 0", silnik wyśle wiadomość i z = 0!
Tutaj mamy kolejny przykład używania "or":
Kod PHP:
//zle
function onSay(cid, words, param)
param = tonumber(param)
vocations = {"Sorcerer", "Druid", "Paladin", "Knight", "Master Sorcerer", "Elder Druid", "Royal Paladin", "Elite Knight"}
if vocations[param] ~= nil then
vocation = vocations[param]
else
vocation = "Unknown"
end
end
Poprawnie:
Kod PHP:
//dobrze
function onSay(cid, words, param)
param = tonumber(param)
vocations = {"Sorcerer", "Druid", "Paladin", "Knight", "Master Sorcerer", "Elder Druid", "Royal Paladin", "Elite Knight"}
vocation = vocations[param] or "Unknown"
end
Jeżeli chcesz sprawdzić czy kilka zmiennych razem = nil, robisz to w ten sposób:
Kod PHP:
//zle
if x and y and z then
pos = {x=x, y=y, z=z}
end
a przecież to samo można zrobić o tak:
Kod PHP:
//dobrze
(a and b) or (c and d) or e
"(a and b)" zwraca b jeśli nie jest nil'em.
Czyli to:
Kod PHP:
//dobrze
result = (a and b) or (c and d) or e
To to samo co to:
Kod PHP:
//zle
if a then
result = b
elseif c then
result = d
else
result = e
end
Gdy używasz tonumber zapewne piszesz skrypty w ten sposób:
Kod PHP:
function position(x, y, z, stackpos)
if ((x and y and z) and type(tonumber(x..y..z)) == 'number') then
pos = {x=x, y=y, z=z}
if (stackpos and type(stackpos) == 'number') then
pos.stackpos = stackpos
end
return pos
end
return false
end
Jak widać to:
Kod PHP:
//zle
type(tonumber(x) == 'number' and type(tonumber(y) == 'number' and type(tonumber(z) == 'number'
To po prostu inna wersja tego:
Kod PHP:
//dobrze
type(tonumber(x..y..z)) == 'number'
Jak to się stało? Przykład:
Kod PHP:
x = "134"
y = "abc"
z = "7"
print(tonumber(x))
print(tonumber(y))
print(tonumber(z))
print(tonumber(x..y..z))
Rezultatem tego skryptu będzie:
Dlaczego? Bo tonumber tylko akceptuje znaki numeryczne. Więc jeśli używasz tonumber do tekstu, nawet jeśli posiada on gdzieś numer to skrypt i tak zwróci nil.
Zamiast tego długiego skryptu:
Kod PHP:
//zle
if (x > z) then
r = x
else
r = z
end
Można napisać to:
Kod PHP:
//dobrze
r = (x > z and x) or z
Co to jest? Tak jak mówiłem, gdy wpisujesz coś typu "1 and 2 and 3" to zwróci nam ostatnią wartość, w tym wypadku 3. Dlatego też pisze "x > z", bo gdy warunek się spełni to skrypt doda też "and x", co zamienia ostatnią wartość w x przy okazji transformując r także w x. Ale gdy "x > z" wychodzi false, to skrypt przejdzie do "or z" co zmienia r w z.
Kolejny przykład:
Kod PHP:
//zle
if (type(x) == "number" and type(y) == "number") then
r = math.max(x, y)
else
r = 0
end
Kod PHP:
//dobrze
r = (type(x) == "number" and type(y) == "number" and math.max(x, y)) or 0
Lub trochę bardziej zaawansowanie:
Kod PHP:
//zle
if (type(x) == "number" and type(y) == "number") then
r = math.max(x, y)
elseif (type(x) == "number") then
r = x
elseif (type(y) == "number") then
r = y
else
r = 0
end
Można skrypt przetransformować w to:
Kod PHP:
//zle
r = (type(x) == "number" and type(y) == "number" and math.max(x, y)) or (type(x) == "number" and x) or (type(y) == "number" and y) or 0
Jak widać dałem tu przypis "//zle", a to dlatego, że kod jest przynajmniej dla mnie nieczytelny i nie polecam używania tej metody, chociaż sama wiedza nt. takiej techniki się Wam przyda.
Poradnik pisany z pomocą tutoriala z otland'u. Zabraniam jego kopiowania na inne strony bez mojej zgody, korzystam jeszcze z nicku 'Grimekk'.
Cześć.