本文地址:https://www.cnblogs.com/oberon-zjt0806/p/13337577.html

本文参考了这篇文章

三元运算符

(如果您已经了解什么是三元运算符,请大胆第前往下一个章节)

我知道有一元运算符(逻辑非,位反转,负号),二元运算符(加减乘除等),这三元运算符是?

嗯,是的,很多编程语言是支持一种特定的三元运算符(Ternary Operator)的,不过我先不打算用代码的方式来解释这个运算符。我们先以代数的方式来介绍这种运算符。(如果您已经了解什么是三元运算符,请大胆第前往下一个章节)

从代数上来说,我们可以把一个N元运算符(算子)定义为一个N元函数的形式,那么我们假定这个三元运算符叫做\(\Xi_3\),那么实际上,这个三元算子可以被表述为这样一个函数:

\[\Xi_3 \left( o_1,o_2,o_3 \right) =
\begin{cases}
o_2 &,\mathop{\bf{1}} \left( o_1 \right)=1 \\
o_3 &,\mathop{\bf{1}} \left( o_1 \right)=0 \\
\end{cases}
\]

这里面的\(o_1\)到\(o_3\)就是三个运算元,\(\mathop{\bf{1}} (x)\)叫做逻辑幺函数,这个函数采取任意形式的\(o_1\),若\(o_1\)能被解释为\(F\)(逻辑0,逻辑矛盾式)则该函数都输出\(0\),否则总输出\(1\)。

换言之,上面的三元运算\(\Xi_3\)就表示了这样的含义:

若\(o_1\)不能被解释为逻辑0,则\(\Xi_3\)返回\(o_2\),否则\(\Xi_3\)返回\(o_3\)。

通过这样一种运算符可以进行一个很便利的条件选择,很多程序语言中也都提供了这样的运算符,考虑到我们写程序的代码是线性排版的(排在一行里),因此如果不使用函数而是使用运算符构成中缀表达式挤在运算元中间时,我们会发现:

op1 _ op2 _ op3

是的,与二元运算符不同,使用运算符区分三个运算元时需要至少两个字符,放在两个空挡处,因此很多程序语言提供给的是这个运算符?:,也就是:

op1 ? op2 : op3

用起来非常优雅简洁,可以让我们节省大量的代码行数,少些若干肥肥的if语句,尽管大量嵌套的话可读性会下降,不过尽量避免这一点就好。

Lua中的三元运算符

非常遗憾,翻遍整个Lua的参考文档,Lua并没有提供这个东西……

就在听过这个令人沮丧的消息后,我无意中看到了一个这样的解决方法,可以说骚断了我的腰……

(a and {b} or {c})[1]

这种方案使用了一个and和一个or运算符,号称完成了三元运算符的功能,起初我8太相信,但是看到Lua里关于逻辑运算的描述,我终于看懂了……

为什么会这样

Lua可以说是一个步伐六亲不认,不走寻常路的鬼才语言,虽然目前官网上一片死寂。

其中一个不寻常就是,Lua里只有nilfalse可以被解释为逻辑false,其余包括0[[]](空字符串)在内的所有内容全是true

而第二个不寻常的玩法就是,Lua的逻辑运算符andor并不一定返回truefalse,它的返回值满足某种吸收原则,这种吸收原则用一句话表示就是:

若表达式针对当前的逻辑运算符可短路求值,则进行左吸收,否则发生右吸收。

分解到这两个运算符身上就是:

  1. 对于and运算符,表达式a and b会在a解释为false时返回a(左吸收),否则返回b(右吸收)
  2. 对于or运算符,表达式a or b会在a解释为true时返回a(左吸收),否则返回b(右吸收)

这样一来我们回到这个情形:

op1 _1 op2 _2 op3

我们当然是希望op1被解释为true时得到op2,否则得到op3。那我们就具体考虑一下当op1被解释为true时应当怎样,要返回op2,则对于前部op1 _1 op2而言需要发生右吸收,对照上面的吸收规则,那么_1就应当是and。依然考虑op1true,第一次吸收后表达式变成了op2 _2 op3,此时我们希望左吸收,不过这里有个问题,op2被解释为truefalse又是两种情况,我们先考虑op2解释为true的情况,此时要完成左吸收,则个根据吸收规则,_2应当使用or运算符,于是整个表达式变成了op1 and op2 or op3,这个表达式可以解决绝大部分情况。

但是,就如前面所担忧的,这种做法并不能处理op1 and false or op3的情况,因为op1 and false部分会被恒定地置为false,而左falseor运算符无法进行左吸收(因为不能短路求值),这种情况下无论op1是多少都只能返回op3

既然如此,那么我们就需要对op2op3进行包装,Lua第三个不寻常的地方就是那个妖娆的tabletable简直就是个万金油数据结构,什么都能往里塞,而且无论装不装东西,table总能被解释为true,这就不会引发op1 and op2总返回false的情况,从而避免了or的右吸收,于是我们就考虑把op2op3用两个table分别包装起来。

a and {b} or {c}

然而我们希望返回的结果是表里的元素,而非这张表,因此我们取下元素:

(a and {b} or {c})[1] --Lua里下标从1开始

大功告成!

后记

……

……

我还能说什么呢??太马叉虫了!!!

Lua骚操作——三元条件运算符的更多相关文章

  1. 论减少代码中return语句的骚操作

    一.写作背景 最近组内在推行checkstyle代码规范的检测,关于checkstyle的介绍可以参考:https://checkstyle.sourceforge.io, 在按照checkstyle ...

  2. Typescript骚操作,在TS里面直接插入HTML

    Typescript骚操作,在TS里面直接插入HTML,还有语法提示 先给大家看一个图 因为我不喜欢用很重的框架,主要是并非专业UI,但是偶尔会用到,还是觉得直接element组装受不了,想想能在ts ...

  3. 闪电侠 Netty 小册里的骚操作

    前言 即使这是一本小册,但基于"不提笔不读书"的理念,仍然有必要总结一下.此小册对于那些"硬杠 Netty 源码 却不曾在千万级生产环境上使用实操"的用户非常有 ...

  4. awk骚操作

    一.awk自加 [root@168web3 ~]# head /data/logs/cloud_monitor_rds_cpu.log |awk '{sum+=$NF}END{print sum}' ...

  5. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  6. UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)

    题目链接:http://uoj.ac/problem/117 题目大意: 解题思路:先判断度数: 若G为有向图,欧拉回路的点的出度等于入度. 若G为无向图,欧拉回路的点的度数位偶数. 然后判断连通性, ...

  7. lua和C++交互的lua栈操作——以LuaTinker为例

    一. -- C++类注册函数(LuaTinker) 的lua栈操作: -- lua栈内容(执行到pop语句) 栈地址 <--执行语句 space_name[name] = t1 -- (2b8) ...

  8. 关于map 及 map 骚操作

    关于map这个东西   很冷门..................   但是,这个博客带你稍微了解一下map:   map用法:一般当作一个下表无穷大的数组   关于它的骚操作:map的鬼畜用法,可以 ...

  9. 通过HTTP的HEADER完成各种骚操作

    作为一名专业的切图工程师,我从来不care网页的header,最多关心Status Code是不是200.但是HEADER真的很重要啊,客户端从服务器端获取内容,首先就是通过HEADER进行各种沟通! ...

随机推荐

  1. JMETER学习宝典

    1. 简介 Apache JMeter是100%纯java桌面应用程序,被设计用来测试客户端/服务器结构的软件(例如web应用程序).它可以用来测试包括基于静态和动态资源程序的性能,例如静态文件,Ja ...

  2. JAVA SOCKET 通信总结 BIO、NIO、AIO ( NIO 2) 的区别和总结

    1 同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 自己上街买衣服,自己亲自干这件事,别的事干不了.2 异步 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已 ...

  3. TestNG离线安装步骤

    1.下载testNG 离线安装包[eclipse-testng离线包],并解压.资源可以在下载:http://download.csdn.net/detail/u012100968/9623613: ...

  4. 动力节点 mysql 郭鑫 34道经典的面试题三

    1.第十五题 15.列出受雇日期早于其直接上级的所有员工编号.姓名.部门名称 思路一:第一步将emp a看成员工表,将emp b 看成领导表,员工表的mgr字段应该等于领导表的主键字段 mysql&g ...

  5. python 2 与python 3区别汇总

    python 2 与python 3区别汇总 一.核心类差异1. Python3 对 Unicode 字符的原生支持.Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类 ...

  6. P2114 [NOI2014]起床困难综合症【二进制运算+优化】

    起床困难综合症[二进制运算+优化] 题目描述 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作斗争.通过 ...

  7. 手摸手带你理解Vue的Watch原理

    前言 watch 是由用户定义的数据监听,当监听的属性发生改变就会触发回调,这项配置在业务中是很常用.在面试时,也是必问知识点,一般会用作和 computed 进行比较. 那么本文就来带大家从源码理解 ...

  8. 栈的顺序存储和链式存储c语言实现

    一. 栈 栈的定义:栈是只允许在一端进行插入或删除操作的线性表. 1.栈的顺序存储 栈顶指针:S.top,初始设为-1 栈顶元素:S.data[S.top] 进栈操作:栈不满时,栈顶指针先加1,再到栈 ...

  9. Zuul请求超时

    最近在弄springcloud的时候发现在发送短信的时候zuul总是报错,错误信息如下 com.netflix.zuul.exception.ZuulException: at org.springf ...

  10. 一个很酷炫也挺实用的JS库leader-line

    简单粗暴,直入主题,看看效果再说. 是不是这效果挺棒?这样的效果在做系统时,可以有很多的应用,可以让枯燥的页面生动起来. 具体效果,大家可以上这个搜索网站Mag[i]上面看,切身体会一下. 这是一个开 ...