Showing posts with label Lua. Show all posts
Showing posts with label Lua. Show all posts

Saturday, June 9, 2012

pairs가 아닌 ipairs를 써야 하는 경우

다음같이 key 이름이 주어지지 않은 array 에 대해 pairs 를 하면 엉뚱한 garbage 값이 enumerate 되곤 한다.
(실제 elements 수보다 하나 더 많이 enumerate 되곤 함)
 sprites_aniLoopBnF_breakable = {   
      {["filename"]="enemyFlyGreen", ["w"]=42, ["h"]=58, ["numFrames"]=3, ["durationTime"]=2400},  
      {["filename"]="enemyFlyBlue", ["w"]=42, ["h"]=58, ["numFrames"]=3, ["durationTime"]=2400},  
      {["filename"]="df", ["w"]=100, ["h"]=106, ["numFrames"]=3, ["durationTime"]=2400}  
 }  
   
 function loadData(displayType)  
      for k, v in ipairs(sprites_aniLoopBnF_breakable) do  
           print(count .. ")", v.filename, v.w, v.h)  
           ...  
      end  
 end  

Friday, June 8, 2012

Corona SDK Memory Leak Prevention 101

Corona SDK Memory Leak Prevention 101
What is Memory Management?
Memory management in Corona is simply managing the following five things:
  1. Display objects
  2. Global variables
  3. Runtime listeners
  4. Timers
  5. Transitions
다음 코드를 main.lua 맨 밑에 넣으면 됨
 local monitorMem = function()  
   
   collectgarbage()  
   print( "MemUsage: " .. collectgarbage("count") )  
   
   local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000  
   print( "TexMem:  " .. textMem )  
 end  
   
 Runtime:addEventListener( "enterFrame", monitorMem )  
키워드 : garbage collection, collectgarbage

Tuesday, May 22, 2012

다른 module의 함수를 부르는 예

iTestUtil.lua
 module(..., package.seeall)   
   
 hello = function()  
      print("hello!!!!")  
 end  

main.lua
 local TestUtil = require("iTestUtil")   
 TestUtil.hello() -- 느린 방법   
   
 local hello = TestUtil.hello -- 함수를 cache해서 빠르게 함   
 hello() -- 이제부터는 부를 때마다 빠르게 호출할 수 있음   

Sunday, May 20, 2012

Lua에서 module 사용하는 법

main.lua
 local testlib = require("testlib")  
 testlib.myPrint() -- 느린 방법  
    
 local myPrint = testlib.myPrint -- 함수를 cache해서 빠르게 함  
 myPrint() -- 이제부터는 부를 때마다 빠르게 호출할 수 있음  

testlib.lua
 module(..., package.seeall)  
   
 function myPrint()  
      print("Hi!")  
 end  

레퍼런스 : Modules and Packages
주의 : testlib.lua 저장시 with BOM 으로 저장하면 안된다 (line 1에서 에러가 남)
키워드 : error, separate, multiple, 별도 파일, 소스

Saturday, May 19, 2012

table의 assignment

그냥 assign 될때는 value가 카피되고
함수에 argument로 pass 될때는 call by reference 로 넘겨진다.
함수에서 return 되는 것도 당연히 포인터가 리턴됨.
 function printTable(table)  
      print("------------")  
      if(table == nil) then   
           print("this table is nil!")  
      else  
           for k, v in pairs(table) do  
                print(k, v)  
           end  
      end  
 end  
   
 function getAnotherRefOfTable(table)  
      local anotherTableRef = table  
      anotherTableRef["job"] = "Magician"  
      return anotherTableRef  
 end  
   
 local a = {name="Kiki", job="Witch"}  
 local b = a   -- Values are copied  
 printTable(a)  
 a = nil  
 printTable(a)  
 printTable(b)  
 local c = getAnotherRefOfTable(b)   -- Called by reference  
 printTable(c)  

Wednesday, May 16, 2012

String 예제

 y = 2012; m = 3; d = 1  
 s = string.format("%04d-%02d-%02d", y, m, d)  
 print(s)  
   
 s = string.format("%.4f", math.pi)  
 print(s)  
   
 s = "This is for you. I love you."  
 i = string.find(s, "you")  
 print(i)  
 i = string.find(s, "you", i+1)  
 print(i)  
   
 s = string.gsub(s, "you", "Jenny")  
 print(s)  
   
 s = "My girlfriend(Jenny) is lovely(cute(pretty))"  
 s = string.gsub(s, "%b()", "(---)")  
 print(s)  
레퍼런스 : Programming in Lua / Chapter 20. The String Library

table.insert(), table.remove()

    local a = {"Ariel", "Barbie", "Clara"}   
     
    table.insert(a, 3, "Zelda")   
    print("-----------------")   
       for k, v in pairs(a) do   
       print(k, v)   
    end   
       
    table.remove(a, 2)   
    print("-----------------")   
    for k, v in pairs(a) do   
       print(k, v)   
    end   
     
    table.remove(a, 1)   
    print("-----------------")   
    for k, v in pairs(a) do   
       print(k, v)   
    end   

__index, __newindex Metamethod

 MyArr = {}  
   
 MyArr.Meta = {}   
 MyArr.Meta.__tostring = function(a)  
      result = ""  
      for k, v in pairs(a.arr) do  
           result = result .. "[" .. k .. "]" .. " " .. v .. "\t"  
      end  
      return result  
 end  
 MyArr.Meta.__index = function(a, key)  
      return (a.arr[key])  
 end  
 MyArr.Meta.__newindex = function(a, key, value)  
      a.arr[key] = value  
 end  
 function MyArr.new(a)  
      local instance = {}  
      instance.arr = {}  
      for k, v in pairs(a) do  
           instance.arr[k] = v  
      end  
        
      function instance:printMe()   
           print("----------------------")  
           for k, v in pairs(self.arr) do  
                print(k, v)  
           end  
      end  
        
      setmetatable(instance, MyArr.Meta)  
      return instance  
 end  
   
 do  
      local a = MyArr.new{"Mimi", "Ki", "Jacky"}  
      a[5] = "Tom"  
      print(tostring(a))  
      a:printMe()  
 end  
Programming in Lua / Chapter 13. Metatables and Metamethods / 레퍼런스 : 13.4.1 – The __index Metamethod

array의 멤버에 nil이 assign되는 경우

array의 멤버에 nil이 assign되는 경우, 아무것도 안해주는 것과 동일하다. 예를 들어 다음과 같이 해주면
 local x = {[10] = "A", [20] = "B", [30] = nil, [40] = false}  
 for k, v in pairs(x) do  
      print(k, v)  
 end  
결과 :
 40     false  
 10     A  
 20     B  
[30]에는 아무것도 존재하지 않음을 알 수 있다.

Metatable 을 이용해 만든 집합연산

다음은 Chapter 13. Metatables and Metamethods / 13.1 – Arithmetic Metamethods 에 나온 Set 클래스를 다시 써 본 것.
 -- Metatable -------------------------------  
 SetMeta = {}  
   
 SetMeta.__tostring = function(a)  
      result = ""  
      for k in pairs(a) do  
           if(type(k) == "number") then -- 이것을 체크 안하면 함수까지 나열함  
                result = result .. k .. " "  
           end  
      end  
      return result  
 end  
   
 SetMeta.__add = function(a, b)   
      local result = Set.new{}  
      for k, v in pairs(a) do  
           if(v == true) then result[k] = true end  
      end  
      for k, v in pairs(b) do  
           if(v == true) then result[k] = true end  
      end  
      return result  
 end  
   
 SetMeta.__mul = function(a, b)   
      local result = Set.new{}  
   
      for k, v in pairs(a) do  
           if(type(k) == "number") then  
                if(v == true) then  
                     result[k] = b[k] -- nil 이 assign 되는 경우, 아무것도 안해주는 것과 동일.  
                end  
           end  
      end  
   
      return result  
 end  
   
 -- Set Class -------------------------------  
 Set = {}    
 function Set.new (a)  
      local instance = {}  
      for k, v in ipairs(a) do instance[v] = true end  
        
      function instance:printMe()  
           for k, v in pairs(self) do   
                if(type(k) == "number") then  
                     print(k, v)   
                end  
           end  
      end  
   
      setmetatable(instance, SetMeta)  
      return instance  
 end  
   
 -- Main -------------------------------  
 do  
      local a = Set.new{10, 20, 30}  
      local b = Set.new{20, 30, 40}  
      local c = a + b  
      local d = a * b  
      print("--------")  
      print(tostring(c))  
      print(tostring(d))  
      print("--------")  
      c:printMe()  
      print("--------")  
      d:printMe()  
 end  
키워드 : 집합 연산, union, intersection

Tuesday, May 15, 2012

Metatables and Metamethods

Metatable이란 Metamethod라는 함수들을 담고 있는 테이블을 말한다. Metatable이 table에 붙으면 그 테이블의 행동양식이 바뀐다. 예를 들어 보통의 테이블은 + 로 더하는 operation을 할 수 없지만, + 연산의 정의를 갖고 있는 메타테이블을 추가해줌으로써 + 연산을 가능하게 할 수 있다. 다음의 __add나 __tostring이 metamethod 인데 __add 라는 이름은 + operator 를 사용할 수 있는 특별한 키워드이고, __tostring 은 tostring(obj)의 형태로 쓸 수 있게 하는 특별한 키워드이다. 그러한 키워드들은 Metatable Events 에 정리되어 있다.
 CharacterMeta = {}  
 CharacterMeta.__add = function(a, b)  
      return Character.new(a.name .. " " .. b.name, a.HP + b.HP)  
 end  
 CharacterMeta.__tostring = function(a)  
      return (a.name .. "\t" .. a.HP)  
 end  
   
 Character = {}  
 Character.new = function(name, HP)  
      local instance = {}  
      instance.name = name  
      instance.HP = HP  
      setmetatable(instance, CharacterMeta)  
      return instance  
 end  
   
 do  
      local heroine = Character.new("Marilyn", 10)  
      local hero = Character.new("Manson", 20)  
      print(tostring(heroine))  
      print(tostring(hero))  
        
      local hybrid = heroine + hero  
      print(tostring(hybrid))  
 end  

Metatables and Metamethods in Lua

Metatables and Metamethods
Metamethods Tutorial ... __add 등
키워드 : getmetatable, setmetatable

Monday, May 14, 2012

개별 instance에 특화된 member function 넣기

 Character = {}  
 Character.new = function(name, HP)  
      local instance = {}  
      instance.name = name  
      instance.HP = HP  
        
      function instance:decreaseHP(delta)  
           self.HP = self.HP - delta  
      end  
        
      function instance:printMe()  
           print(self.name, self.HP)  
      end  
             
      return instance  
 end  
   
 local hero = Character.new("Luke", 10)  
 local vader = Character.new("Vader", 20)  
 local soldier = Character.new("Soldier", 5)  
 hero:printMe()  
 vader:printMe()  
 soldier:printMe()  
   
 function vader:talk()  
      print("I am your father")  
 end  
   
 function soldier:printMe()  
      print(self.name, self.HP, "March!")  
 end  
   
 hero:decreaseHP(1)  
 vader:decreaseHP(2)  
 soldier:decreaseHP(4)  
 vader:talk()  
 hero:printMe()  
 vader:printMe()  
 soldier:printMe()  
Lua에서는 이처럼 특정 오브젝트만이 가지는 함수를 넣을 수도 있고,
같은 클래스라도 오브젝트 별로 다른 함수를 넣어줄 수도 있다.
(애초에 language 안에 클래스라는 개념이 없기 때문에 가능한 일)

Lua에서 클래스 정의하는 법 (3) Closure 방식

다음은 lua-users.org/wiki 의 Object Orientation Closure Approach 에 나오는 스타일을 따라한 것. (2) Table 방식과의 performance 비교도 되어 있음. 결론은, 성능상으로는 둘 다 비슷하므로 코딩 스타일에 따라 선택하는 게 좋다는 것.
 Hero = {}  
 Hero.new = function(name, HP)  
      local instance = {}  
      local maxHP = 100  
      local name_ = name or "anonymous"  
      local HP_ = HP or maxHP  
   
      instance.setHP = function(hp)  
           HP_ = hp  
      end  
        
      instance.printMe = function()  
           print("Hero : " .. name_ , "HP=" .. HP_)  
      end  
   
      return instance  
 end  
   
 hero1 = Hero.new(nil, nil)  
 hero2 = Hero.new("Mika", 80)  
 hero1.printMe()  
 hero2.printMe()  
   
 hero2.setHP(70)  
 hero1.printMe()  
 hero2.printMe()  
키워드 : OOP

Lua에서 클래스 정의하는 법 (2) Table 방식

다음은 lua-users.org/wiki 의 Object Orientation Closure Approach 에 나오는 스타일을 따라 정의한 것. 대체로 이 방법이 쓰임
 Hero = {}  
 Hero.new = function(name, HP)  
      local instance = {}  
      local maxHP = 100  
      instance.name = name or "anonymous"  
      instance.HP = HP or maxHP  
   
      instance.setHP = function(self, hp)  
           self.HP = hp  
      end  
   
      instance.printMe = function(self)  
           print("Hero : " .. self.name , "HP=" .. self.HP)  
      end  
   
      return instance  
 end  
   
 hero1 = Hero.new(nil, nil)  
 hero2 = Hero.new("Mika", 80)  
 hero1:printMe()  
 hero2:printMe()  
   
 hero2:setHP(70)  
 hero1:printMe()  
 hero2:printMe()  
   
 hero1:setHP(90)  
 hero1:printMe()  
 hero2:printMe()  
보충 :
사실 Hero = {} 하고 나서 Hero.new() 를 정의하는 것은 constructor 를 Hero.new 같은 형식으로 쓸 수 있게 하기 위한 것 뿐이다. 사실 Hero = {} 를 정의하지 않고 HeroNew() 라는 이름으로 function 정의를 해버려도 된다.

local instance = {} 로 안하고
instance = {} 로 해버리면
instance 가 global 이 되어 버려서 hero1 과 hero2 가 항상 똑같은 global object 를 가리키게 된다.
local 선언을 절대 잊어서는 안된다.

instance.setHP = function(self, hp) 는
function instance.setHP(self, hp) 또는
function instance:setHP(hp) 로 써줄 수 있다.
실전에서는 "보다 간결한 방식이 있을 때는 그 방식을 채택한다"는 원칙을 갖고 코딩하는 것이 좋을 것이다.

키워드 : OOP

Lua에서 클래스 정의하는 법 (1)

다음은 Programming in Lua 의 Chapter 16. Object-Oriented Programming 에 나오는 스타일을 따라 정의한 것. 설명을 위해 책에 등장하긴 했지만 실전에선 잘 안쓰이는 방식.
 Hero = {  
      name = "anonymous",  
      HP = 100,  
 }  
   
 Hero.init = function(self, name, hp)  
      self.name = name  
      self.HP = hp  
 end  
   
 Hero.printMe = function(self)  
      print("Hero : " .. self.name , "HP=" .. self.HP)  
 end  
   
 hero1 = {init = Hero.init, printMe = Hero.printMe}  
 hero1:init("Jack", 70)  
 hero1:printMe() -- Hero : Jack     HP=70  
   
 hero2 = {init = Hero.init, printMe = Hero.printMe}  
 hero2:init("Mimi", 50)  
 hero2:printMe() -- Hero : Mimi     HP=50  
   
 hero1:printMe() -- Hero : Jack     HP=70  
키워드 : OOP

OOP in Lua

가장 알기 쉬운 설명 링크 :
[1] Object Orientation Closure Approach
[2] Lua OOP (Litt's Lua Laboratory)
[3] Programming in Lua - Chapter 16. Object-Oriented Programming
[3]은 [1], [2]를 다 이해한 후에 보는 것이 알기 쉬움

보충 :
[2] 에서 좀 잘못된 부분이 있는데
 Point.new = function(x, y)       
      -- #PRIVATE VARIABLES  
      local self = {}    -- Object to return  
      x = x or 0      -- Default if nil  
      y = y or 0      -- Default if nil  
와 같은 코드가 있는데 이렇게 하면 x와 y는 global variable이 되어 버린다.
local x, local y 로 해주어야 함.

미러 :
Lua로 Object Oriented Programming 하기 - class 정의하기/Lua OOP.html
Lua로 Object Oriented Programming 하기 - class 정의하기/lua-users wiki - Object Orientation Closure Approach.html

참고자료 모음 :
Object Orientation Closure Approach
Object Orientation Tutorial - Representation of classes in Lua
Object Oriented Programming in Lua
Inheritance Tutorial
Metamethods Tutorial
Inspired Lua - Object Classes

인용 : Lua wasn't built with OOP in mind, it was built with atomic computer programming features such as closures, iterators, tables, metatables, tail recursion.
출처 : Discussion: Many Ways to Do OOP
키워드 : Object Oriented, class definition

Sunday, May 13, 2012

Nested function

 function printReverse(str)  
      function reverseString(s)  
           return string.reverse(s)  
      end  
      print(reverseString(str))  
 end  
   
 printReverse("ANONYMOUS")  

Variable Arguments

 function printAll(...)  
      for i=1, #arg do  
           print(i, arg[i])  
      end  
 end  
   
 printAll("Megadeth", "Metallica", "Slayer", "Anthrax")  

Looping

 local a = {Mustaine = "Megadeth", Hetfield = "Metallica", King = "Slayer", Yngwie = "Rising Force"}  
   
 print ("--next--------------------------------------")  
 do   
      local k, v  
      k, v = next(a, nil)  
      while k do  
           print(k, v)  
           k, v = next(a, k)  
      end  
 end  
 print ("--pairs--------------------------------------")  
 do  
      for i, v in pairs(a) do  
           print(i, v)  
      end  
 end