很早就知道lua的and与or的巧妙用法:

local str = num==1 and "one" or "not one"

这句话可以简洁的表达如下意思:

local str = ""
if num==1 then
	str = "one"
else
	str = "not one"
end

类似与c++的:?运算符,一直用着没啥问题,可是前不久遇到了一个很奇怪的bug,查到最后,锁定在这个用法上,举例:

function get_item(config_id, star_lv, server_id)
	for _,item in pairs(items) do
    	if item.config_id==config_id and item.star_lv==star_lv and (server_id and item.server_id==server_id or true) then
        	return item
        end
    end
end

我是想:根据config_id, star_lv和server_id来查找物品,其中server_id可以不填(即为nil),若不填,则忽略。
逻辑上是对的,可是运行时候有bug,原因就是:server_id and item.server_id==server_id or true这一句。
原来,lua的and和or返回的值是:使它可以确定其最终值的值

简单测试一下即可看出规律:

print(false and nil)    -- false
print(nil and true)     -- nil
print(123 and nil)      -- nil
print(123 and 456)      -- 456
print(false or nil)     -- nil
print(nil or 123)       -- 123
print(123 or nil)       -- 123
print(123 or 456)       -- 123

为了验证返回的是值(而不是bool值),我用nil来代替false,用123,456来代替true。
而a = b and c or d这种写法,等同于a = (b and c) or d,也就是根据b and c来决定是否返回d。
结果就很明显了,b and c有2种情况:

  1. b:true -> c
  2. b:false -> b

然后再和d做逻辑或运算:x or d,而x or d在:

  1. x:true -> x
  2. x:false -> d

分析到这里,可以得出,对于:a = b and c or d来说,若:

  1. b:true ->
    1. c:true -> a = c
    2. c:false -> a = d
  2. b:false -> a = d

坑已经暴露出来了,a = b and c or d 不等与 C++的a = b ? c : d
只有在c为true的时候,才可以这么用
ps. 只有false和nil才是false,其他都为true