Currying operations in lua

80 views Asked by At

This question has some reference to the question Defining logical operator implies in lua. The following code works fine.

local function _implies(a, b)
      if a == 1 and b == 0 then return 0 
        else return 1 end
    end
    
    local my_right = {
        __mul = function(self, b)
            return _implies(self.a, b)
        end
      }
      
      local _mt =  {
        __mul = function(a)
            return setmetatable({a=a}, my_right)
        end
    }
    
    local my_left={}
    setmetatable(my_left,_mt)
    imp = my_left
    local names={}
    
    
    for i = 0,1 do
       for j=0,1 do
         names.i=i;names.j=j
       print(i, j, names.i *imp* names.j)
      
       end
    end

The following code is similar to above code. It is for logical and. The question I want to ask is : Are both and_left and and_right are required in this case as well? Were they required because implies is not commutative? In other words, can the code be made somewhat efficient for defining logand?

    local function _and(a, b)
          if a == 1 and b == 1 then return 1 
            else return 0 end
    end
    
    local right_and = {
        __mul = function(self, b)
            return _and(self.a, b)
        end
      }
      
      local and_mt =  {
        __mul = function(a)
            return setmetatable({a=a}, right_and)
        end
    }
    
    local and_left={}
    setmetatable(and_left,and_mt)
   log_and = and_left
    local names={}
    
    
    for i = 0,1 do
       for j=0,1 do
 names.i=i;names.j=j
       print(i, j, names.i *log_and* names.j)
      
       end
end

Note: I know bitwise operator & is there but for some reasons, I don't want to use it.

1

There are 1 answers

0
Egor Skriptunoff On BEST ANSWER

Are both and_left and and_right are required

They were introduced because there are two semantically different multiplications involved.

But the code can be optimized.
The version below does not create a new table on every multiplication.
It also uses only one metatable instead of two.

do
   local function _implies(a, b)
      if a == 1 and b == 0 then
         return 0
      else
         return 1
      end
   end

   local temp, imp = {}, {}
   local _mt =  {
      __mul = function(a, b)
         if b == imp then
            temp[1] = a
            return temp
         elseif a == temp then
            return _implies(temp[1], b)
         end
      end
   }
   setmetatable(temp, _mt)
   setmetatable(imp, _mt)
   _G.imp = imp
end

local names={}
for i = 0, 1 do
   for j = 0, 1 do
      names.i=i
      names.j=j
      print(i, j, names.i *imp* names.j)
   end
end