Home > other >  Defining logical operator implies in lua
Defining logical operator implies in lua

Time:03-09

print("i", "j", "i & j")
for i = 0,1 do
   for j=0,1 do
   print(i, j, i & j)
   end
end

The above code works fine in Lua. It gives the following output.

i   j   i & j
0   0   0
0   1   0
1   0   0
1   1   1

I want to define another operator implies. It is conditional logical operator. The result p implies q is false only when p is true and q is false.

print("i", "j", "i implies j")
for i = 0,1 do
   for j=0,1 do
   print(i, j, i implies j)
   end
end

I want the above code to work. It should output the following.

i   j   i implies j
    0   0   1
    0   1   1
    1   0   0
    1   1   1

So far I have succeeded in defining implies function but that doesn't seem to be of great use. Of course I can write implies(i,j) but I want operator similar to & or | that I can use. So basic question is to replicate definition of logical operator & or | from lua. Here is the code for implies function (not operator).

function implies(a,b)
   if a then
        return b
    else
        return True
  end
end

CodePudding user response:

OOP-style calls

This gets rather hacky if it must truly be infix. What about simply using metatables for OOP-ish object:method(params) syntax?

Assuming implies is defined as

local function _implies(a, b)
    if a ~= 0 then return b end
    return 1
end

this would be implemented as

debug.setmetatable(0, {__index = {
    implies = _implies
}})

and used as

i:implies(j)

if you want you a simpler dot syntax instead, consider using currying:

debug.setmetatable(0, {__index = {
    implies = function(a) return function(b) return _implies(a, b) end end
}})

used as

i.implies(j)

A more "infix-ish" notation might be achieved by using the __call metamethod, and passing a function name:

debug.setmetatable(0, {__index = {
    implies = function(a) return function(b) return _implies(a, b) end end
}, __call = function(self, index) return self[index] end})
(i)("implies")(j)

If implies = "implies", this can even be shortened to (i)(implies)(j).

Hacky, "truly" infix notation

If infix notation is of utmost importance, yet you can't use the available metamethods as they are limited and rather unreadable, you can use even more currying and workarounds to use other metamethods to create operators that seemingly turn your function (at least syntactically) into an infix operator using a "proxy" metatable instead of the function. You can use whatever operators you like; just make sure they suit your needs in terms of associativity and precedency:

local implies_right_hand_mt = {
    __mul = function(self, b)
        return _implies(self.a, b)
    end
}
local implies_left_hand = setmetatable({}, {
    __mul = function(a)
        return setmetatable({a = a}, implies_right_hand_mt)
    end
})
implies = implies_left_hand

The syntax would then be i *implies* j or "i *implies* j" in your example (using the multiplication operator). You could however use all other operators (except the comparison operators) as well, including other arithmetic operators, as implies is not a number but rather a table and may thus override number metamethods.

Side note

Consider using booleans instead of numbers. You'd get two advantages:

  1. Most metamethods aren't used by booleans (especially all arithmetic & bitwise metamethods);
  2. The logic operators not, and and or work; you don't have to use bitwise operators (although those work fine as well).

CodePudding user response:

There are two metamethods available for "number" datatype: __call and __index.

debug.setmetatable(0, {__call = function(a, b) return a~1|b end})
-- Now you can use "(i)(j)" for "i implies j"

print("i", "j", "(i)(j)")
for i = 0,1 do
   for j = 0,1 do
      print(i, j, (i)(j))
   end
end

CodePudding user response:

Lua has no provision for user-defined operators.

CustomOperators

But if i and j were boolean, you could use:

i and j or true

It doesn't work with 0 and 1, because for LUA they are both true!

  • Related