2011-12-22 3 views
5

이것은 놀라운 커뮤니티의 첫 번째 질문입니다.루아 : __lt metamethod 설정이 작동하지 않습니다.

요즘 나는 스스로 Lua 모듈을 작성하고 있습니다. 여기 문제

mt = {} 

bf = {} 

------------ 
-- bf.new -- 
------------ 
function bf.new(A) 

    local out = A 
    setmetatable(out,mt) 
    return out 

end 

----------------- 
-- bf.tostring -- 
----------------- 
function bf.tostring(A) 

    local typeA = type(A) 
    local out = "" 
    if typeA=="number" or typeA=="boolean" then 
     print(tostring(A)) 
    elseif typeA=="table" then 
     local col = "" 
     local m  = #A 
     local typeA1 = type(A[1]) 
     for i=1,m do 
      if typeA1=="table" then 
       n = #A[1] 
       for j=1,n do 
        out = out.." "..tostring(A[i][j]) 
        if j==n then 
         out = out.."\n" 
        end 
       end 
      elseif (typeA1=="number" or typeA1=="boolean") then 
       row = row.." "..tostring(A[i][j]) 
      end 
     end 
    end 
    return out 
end 

----------------------------- 
-- bf.compare(A,logical,B) -- 
----------------------------- 
function bf.compare(A,logical,B) 

    if (logical~="<" and 
     logical~=">" and 
     logical~="<=" and 
     logical~=">=" and 
     logical~="==" and 
     logical~="~=") then 
     error("second input input must be a logical operator written into a string") 
    end 
    local out = {} 
    local ind = {} 
    local count = 0 
    if type(B)=="number" then 
     if type(A[1])=="table" then 
      for i=1,#A do 
       out[i] = {} 
       for j=1,#A[1] do 
        loadstring("cond ="..A[i][j]..logical..B)() 
        if cond then 
         out[i][j] = true 
         count  = count+1 
         ind[count] = (i-1)*#A[1]+j 
        else 
         out[i][j] = false 
        end 
       end 
      end 
     elseif type(A[1])=="number" then 
      for j=1,#A do 
       loadstring("cond ="..A[j]..logical..B)() 
       if cond then 
        out[j]  = true 
        count  = count+1 
        ind[count] = j 
       else 
        out[j]  = false 
       end 
      end 
     end 
    else 
     if (type(A[1])=="table" and type(B[1])=="table") then 
      if (#A==#B and #A[1]==#B[1]) then 
       for i=1,#A do 
        out[i] = {} 
        for j=1,#A[1] do 
         loadstring("cond ="..A[i][j]..logical..B[i][j])() 
         if cond then 
          out[i][j] = true 
          count  = count+1 
          ind[count] = (i-1)*#A[1]+j 
         else 
          out[i][j] = false 
         end 
        end 
       end 
      else 
       error("The comparison can be done between ".. 
         "two matrix with same dimension ".. 
         "or between a matrix with a scalar value") 
      end 
     elseif (type(A[1])=="number" and type(B[1])=="number") then 
      if (#A==#B) then 
       for j=1,#A do 
        loadstring("cond ="..A[j]..logical..B[j])() 
        if cond then 
         out[j] = true 
         count  = count+1 
         ind[count] = j 
        else 
         out[j] = false 
        end 
       end 
      else 
       error("Comparison between ".. 
         "two vector with different dimension") 
      end 
     else 
      error("The comparison can be done between ".. 
        "two matrix with same dimension ".. 
        "or between a matrix with a scalar value") 
     end 
    end 
    return setmetatable(out,mt)--,ind 

end 

------------------------ 
-- metamethod setting -- 
------------------------ 
mt.__tostring = bf.tostring 
mt.__lt  = function(A,B) return bf.compare(A,"<",B) end 

-------------------------- 
-- use of my metamethod -- 
-------------------------- 
A = bf.new{{1,2,3,4},{5,6,7,8},{9,10,11,12}} 
B = bf.new{{3,6,1,8},{1,3,87,20},{11,2,5,7}} 
C1 = bf.compare(A,"<",B) 
C2 = A<B 
print("What I want") 
print(C1) 
print("What I get") 
print(C2) 

이 작은 스크립트를 실행하는 경우, 당신은 내가 함수 bf.compare를 사용할 때 직접 내가 필요가 있음을 알 수와 코드의 최소 부분입니다. 메타 메서드를 통해 bf.compare를 사용하면 true라는 "스칼라"값만 가져옵니다.

의견이 있으십니까? __lt metamethod위한

What I want 
true true false true 
false false true true 
true false false false 

What I get 
true 
>Exit code: 0 
+0

출력을 표시하지 않기 때문에 전혀 볼 수 없습니다. – Puppy

+1

+1 실제로 작업 코드를 제공합니다. – jpjacobs

답변

4

Lua manual 미국이 의사 코드 :

편집

IT는 출력

function lt_event (op1, op2) 
     if type(op1) == "number" and type(op2) == "number" then 
     return op1 < op2 -- numeric comparison 
     elseif type(op1) == "string" and type(op2) == "string" then 
     return op1 < op2 -- lexicographic comparison 
     else 
     local h = getbinhandler(op1, op2, "__lt") 
     if h then 
      return not not h(op1, op2) 
     else 
      error(···) 
     end 
     end 
    end 

메타 메소드,이 선이 있다면 return not not h(op1, op2)은 핸들러에 의해 반환 된 singel (첫 번째) 값만 반환합니다., not은 단항 연산자입니다. 두 번째 효과로 처리기 출력을 스칼라로 변환합니다 (not {} == falsenot false == true).

주의 할 점 : 루아 테이블은 항상 참조로 전달됩니다. 테이블을 다른 변수에 할당하면 포인터가 복사됩니다. 따라서 다음과 같이하면 :

function myFun(A) 
    local out=A 
    out[1]='bar' 
    return out 
end 
A={'foo',1,2,3} 
B=myFun(A) 
print(table.concat(B,', ')) -- OK 
print(table.concat(A,', ')) -- A also changed, because: 
print(A,B) -- they are the same table! 
2

모든 비교 메타 결과는 자동으로 부울로 변환됩니다.

관련 문제