Reklama
Pokazuje wyniki od 1 do 3 z 3

Temat: [LUA] Krótsze odpowiedniki w lua - autorstwa Grimkka

  1. #1
    Avatar Grimekk
    Data rejestracji
    2011
    Posty
    2,692
    Siła reputacji
    14

    Domyślny [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:
    Kod:
    15
    5
    10
    5
    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:
    Kod:
    134
    nil
    7
    nil
    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ść.
    Ostatnio zmieniony przez Grimekk : 12-01-2014, 03:28

  2. #2

    Data rejestracji
    2014
    Posty
    23
    Siła reputacji
    0

    Domyślny

    Kurde; dzięki :) Myślałem; że dobrze piszę; a tu zonk... :)

  3. Reklama
  4. #3
    Avatar zakius
    Data rejestracji
    2008
    Położenie
    The Internets
    Wiek
    33
    Posty
    11,075
    Siła reputacji
    24

    Domyślny

    O właśnie o tym mówiłem, ten poradnik tylko używa funkcji OTSowych, równie dobrze mogłyby to być foo() bar(), i imo merytorycznie bardziej pasuje do sio>programowanie

    A do samego poradnika: kod jest niepoprawny jeśli nie wykonuje zamierzonego zadania, ewentualnie jeśli wykonuje je wykorzystując zdecydowanie zbyt wiele zasobów



    przy okazji: LuaJIT interpretuje trochę inaczej niż robi to oryginalna biblioteka
    ostatnio jak testowałem
    Kod:
    local config = 
    {
        time = 60, -- seconds
        teleportId = 5023,
        bosses = 
    	{ -- Monster Name,  Teleport Position, aid, optional brothers name
    		["Ushuriel"] = {  pos={ x=1383, y=615, z=11}, aid=1001},
    		["Zugurosh"] = {  pos={ x=1415, y=614, z=11}, aid=1002},
    		["Madareth"] = {  pos={ x=1398, y=655, z=11}, aid=1003},
    		["Annihilon"] = {  pos={ x=1473, y=615, z=11}, aid=1005},
            ["Hellgorak"] = {  pos={ x=1478, y=657, z=11}, aid=1006},
    		["Golgordan"] = {	pos={ x=1433, y=655, z=11}, aid=1004, brother = "Latrivan"},
            ["Latrivan"] = {	pos={ x=1433, y=655, z=11}, aid=1004, brother = "Golgordan"}
    	}
    }
    local function changeBack(position)
    	doItemSetAttribute(getTileItemById(t.pos, config.teleportId).uid, "aid", 3000)
    end
    function onKill(cid, target, lastHit)
        if(local t = config.bosses[getCreatureName(target)]) then
    		if t.brother then if(isMonster(getCreatureByName(t.brother))) then return true end end
    	    doItemSetAttribute(getTileItemById(t.pos, config.teleportId).uid, "aid", t.aid)
            doCreatureSay(cid, "Go into the teleport in "..config.timeToRemove.." seconds, else it will disappear.", 19)
    		addEvent(changeBack, config.time * 1000, t.pos)
    	end
    	return true
    end
    nie działało w LuaJIT

    Kod:
    if(local t = config.bosses[getCreatureName(target)]) then
    trzeba było rozpisać na sprawdzenie, czy istnieje w tablicy pole o indeksie getCreatureName(target) i dopiero po tym można było działać, i analogicznie chyba dalej, dawno to było :D
    Ostatnio zmieniony przez zakius : 13-01-2014, 21:06
    Problem z komputerem? Instrukcja diagnostyczna
    Cytuj Vegeta napisał Pokaż post
    Cytat został ukryty, ponieważ ignorujesz tego użytkownika. Pokaż cytat.
    Baby maja wymagania jak windows vista, takze nigdy nie wiesz.
    Cytuj Dzzej napisał Pokaż post
    Cytat został ukryty, ponieważ ignorujesz tego użytkownika. Pokaż cytat.
    Moje posty to esencja głupoty.
    "Don't worry, I'm just a pervert"

Reklama

Informacje o temacie

Użytkownicy przeglądający temat

Aktualnie 1 użytkowników przegląda ten temat. (0 użytkowników i 1 gości)

Podobne tematy

  1. Odpowiedniki Allegro, discogs itd
    Przez Dawox w dziale O wszystkim i o niczym
    Odpowiedzi: 13
    Ostatni post: 16-05-2019, 14:48
  2. Czy isnieją odpowiedniki AirPodsów? Do androida.
    Przez Piotruś w dziale Sprzęt i oprogramowanie
    Odpowiedzi: 1
    Ostatni post: 14-06-2018, 17:59
  3. Wiersze, autorstwa wlasnego
    Przez Loo King w dziale Artyści
    Odpowiedzi: 29
    Ostatni post: 03-10-2013, 00:59
  4. [Lua] Od zera do skryptera, czyli LUA: PODSTAWY i Actions*
    Przez Grim90 w dziale Artykuły developerskie
    Odpowiedzi: 7
    Ostatni post: 02-08-2009, 01:05

Zakładki

Zakładki

Zasady postowania

  • Nie możesz pisać nowych tematów
  • Nie możesz pisać postów
  • Nie możesz używać załączników
  • Nie możesz edytować swoich postów
  •