lua算术运算和关系运算metamethods

--[[
说明
1.以下使用的metamethod都是lua核心metamethod,使用的时候可以采用相应的操作符,如:__add可以解释成+。
2.metamethod需要放在metatable中使用

算术运算符对应的域:
__add(+), __sub(-), __mul(*), __div(/), __unm(-负), __pow(^幂)

关系运算符对应的域:
__eq(==), __lt(<), __le(<=)
无~=, >, >=, 可以通过上述关系运算符not操作来实现

其他:
字符串连接操作: __concat(..)
转化为字符串操作:__tostring,当使用函数print打印该变量时,首先利用该变量的__tostring函数进行字符串的转化
保护元表信息:__metatable
]]


Set = {}
Set.mt = {}

--[[
	算术运算
]]
function Set.new(t)
	local s = {}
	setmetatable(s, Set.mt)
	for _, item in ipairs(t) do
		s[item] = true
	end

	return s
end

-- 求集合并集
function Set.union(s1, s2)
	-- 两个集合的metatable必须相等,才能执行并集操作
	if getmetatable(s1) ~= Set.mt or
	getmetatable(s2) ~= Set.mt then
	    error("attempt to add a set with a non-set value", 2)
	end

	local res = Set.new({})
	for item in pairs(s1) do
		res[item] = true
	end

	for item in pairs(s2) do
		res[item] = true
	end

	return res
end

-- 求集合交集
function Set.intersection(s1, s2)
	if getmetatable(s1) ~= Set.mt or
	getmetatable(s2) ~= Set.mt then
		error("attempt to multify a set with a non-set value", 2)
	end

	local res = Set.new({})
	for item in pairs(s1) do
		res[item] = s2[item]
	end

	return res
end

-- 将集合转化为字符串
function Set.tostring(s)
	local res = "{"
	local sep = ""
	for item in pairs(s) do
		res = res .. sep .. item
		sep = ", "
	end

	return res .. "}"
end

-- 打印集合
function Set.print(s)
	print(Set.tostring(s))
end

Set.mt.__add = Set.union -- 设置+运算实现函数,集合并集
Set.mt.__mul = Set.intersection -- 设置*运算实现函数,集合交集
Set.mt.__tostring = Set.tostring

s1 = Set.new({1, 2, 3})
s2 = Set.new({3, 4, 5})
print(s1)
print(s2)
print(s1 + s2)
print(s1 * s2)

--[[
	关系运算
]]
-- 小于等于
Set.mt.__le = function(s1, s2)
	for item in pairs(s1) do
		-- s1有的,s2中没有,则s2不包含s1
		if not s2[item] then
			return false
		end
	end

	return true
end

-- 小于
Set.mt.__lt = function(s1, s2)
	--[[
	s1 <= s2,而且s1 ~= s2,
	当s1 <= s2且s2 <= s1时,表示s1 == s2,所以这里增加一个判断条件是not(s2 <= s1) ]]
	return s1 <= s2 and not(s2 <= s1)
end

-- 等于
Set.mt.__eq = function(s1, s2)
	return s1 <= s2 and s2 <= s1
end

s3 = Set.new({1, 2, 3})
s4 = Set.new({1, 2, 3, 4})
print(s3 < s4)
print(s3 == s4)
print(s3 <= s4)
print(s3 == (s3 * s4))

s5 = {2, 3, 4}
print(3 == "a")
print(3 == s3)  -- 相等比较,混合类型,则返回false,不会抛出异常
print(s5 == s3) -- 相等比较,相同类型,metadata不同,则返回false,不会抛出异常

--print(3 > s3)   -- 非相等比较,混合类型,则直接抛出异常
--print(s5 > s3)  -- 非相等比较,相同类型,metadata不同,则直接抛出异常

--[[
为元表设置属性__metatable,保护元表不会被读取,不会被修改
]]
Set.mt.__metatable = "none of your bussiness" 
s6 = Set.new({})
print(getmetatable(s)) -- 获得元表,会直接返回上面设置的__metatable属性的值
setmetatable(s6, {}) -- 修改s6的元表,将会抛出异常

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值