Lua骚操作——三元条件运算符
本文地址:https://www.cnblogs.com/oberon-zjt0806/p/13337577.html
本文参考了这篇文章
三元运算符
(如果您已经了解什么是三元运算符,请大胆第前往下一个章节)
我知道有一元运算符(逻辑非,位反转,负号),二元运算符(加减乘除等),这三元运算符是?
嗯,是的,很多编程语言是支持一种特定的三元运算符(Ternary Operator)的,不过我先不打算用代码的方式来解释这个运算符。我们先以代数的方式来介绍这种运算符。(如果您已经了解什么是三元运算符,请大胆第前往下一个章节)
从代数上来说,我们可以把一个N元运算符(算子)定义为一个N元函数的形式,那么我们假定这个三元运算符叫做\(\Xi_3\),那么实际上,这个三元算子可以被表述为这样一个函数:
\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里只有nil
和false
可以被解释为逻辑false
,其余包括0
和[[]]
(空字符串)在内的所有内容全是true
。
而第二个不寻常的玩法就是,Lua的逻辑运算符and
和or
并不一定返回true
或false
,它的返回值满足某种吸收原则,这种吸收原则用一句话表示就是:
若表达式针对当前的逻辑运算符可短路求值,则进行左吸收,否则发生右吸收。
分解到这两个运算符身上就是:
- 对于
and
运算符,表达式a and b
会在a
解释为false
时返回a
(左吸收),否则返回b
(右吸收) - 对于
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
。依然考虑op1
为true
,第一次吸收后表达式变成了op2 _2 op3
,此时我们希望左吸收,不过这里有个问题,op2被解释为true
或false
又是两种情况,我们先考虑op2
解释为true
的情况,此时要完成左吸收,则个根据吸收规则,_2
应当使用or
运算符,于是整个表达式变成了op1 and op2 or op3
,这个表达式可以解决绝大部分情况。
但是,就如前面所担忧的,这种做法并不能处理op1 and false or op3
的情况,因为op1 and false
部分会被恒定地置为false
,而左false
对or
运算符无法进行左吸收(因为不能短路求值),这种情况下无论op1
是多少都只能返回op3
。
既然如此,那么我们就需要对op2
和op3
进行包装,Lua第三个不寻常的地方就是那个妖娆的table
,table
简直就是个万金油数据结构,什么都能往里塞,而且无论装不装东西,table
总能被解释为true,这就不会引发op1 and op2
总返回false
的情况,从而避免了or
的右吸收,于是我们就考虑把op2
和op3
用两个table
分别包装起来。
a and {b} or {c}
然而我们希望返回的结果是表里的元素,而非这张表,因此我们取下元素:
(a and {b} or {c})[1] --Lua里下标从1开始
大功告成!
后记
……
……
我还能说什么呢??太马叉虫了!!!
Lua骚操作——三元条件运算符的更多相关文章
- 论减少代码中return语句的骚操作
一.写作背景 最近组内在推行checkstyle代码规范的检测,关于checkstyle的介绍可以参考:https://checkstyle.sourceforge.io, 在按照checkstyle ...
- Typescript骚操作,在TS里面直接插入HTML
Typescript骚操作,在TS里面直接插入HTML,还有语法提示 先给大家看一个图 因为我不喜欢用很重的框架,主要是并非专业UI,但是偶尔会用到,还是觉得直接element组装受不了,想想能在ts ...
- 闪电侠 Netty 小册里的骚操作
前言 即使这是一本小册,但基于"不提笔不读书"的理念,仍然有必要总结一下.此小册对于那些"硬杠 Netty 源码 却不曾在千万级生产环境上使用实操"的用户非常有 ...
- awk骚操作
一.awk自加 [root@168web3 ~]# head /data/logs/cloud_monitor_rds_cpu.log |awk '{sum+=$NF}END{print sum}' ...
- 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)
0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...
- UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)
题目链接:http://uoj.ac/problem/117 题目大意: 解题思路:先判断度数: 若G为有向图,欧拉回路的点的出度等于入度. 若G为无向图,欧拉回路的点的度数位偶数. 然后判断连通性, ...
- lua和C++交互的lua栈操作——以LuaTinker为例
一. -- C++类注册函数(LuaTinker) 的lua栈操作: -- lua栈内容(执行到pop语句) 栈地址 <--执行语句 space_name[name] = t1 -- (2b8) ...
- 关于map 及 map 骚操作
关于map这个东西 很冷门.................. 但是,这个博客带你稍微了解一下map: map用法:一般当作一个下表无穷大的数组 关于它的骚操作:map的鬼畜用法,可以 ...
- 通过HTTP的HEADER完成各种骚操作
作为一名专业的切图工程师,我从来不care网页的header,最多关心Status Code是不是200.但是HEADER真的很重要啊,客户端从服务器端获取内容,首先就是通过HEADER进行各种沟通! ...
随机推荐
- 深入理解 EF Core:EF Core 写入数据时发生了什么?
阅读本文大概需要 14 分钟. 原文:https://bit.ly/2C67m1C 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能 ...
- 基于flask的城市空气质量分析系统
1.1 系统功能 在对主要需求进行分析后,确定系统由以下几个模块组成. 1) 用户信息管理: 该部分主要完成系统管理员的增加.删除.编辑和访问控制权限等操作. 2) 数据管理: 该部分主要完成后台存 ...
- Linux文件目录和访问权限
前言 本文知识点是曾经学习过程中收录整理的,方便学习使用,并非在下撰写. 一>Lniux目录结构 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录.所有的东西都是从这里开始. ...
- Linux系统结构详解(转)
Linux系统一般有4个主要部分: 内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统.部分层次结构如图1-1所 ...
- 关于MySQL事务和存储引擎常见FAQ
1.什么是事务? 事务就是「一组原子性的SQL查询」,或者说一个独立的工作单元.如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询.如果其中有任何一条语句因为崩溃或其他原因无法 ...
- Alink漫谈(八) : 二分类评估 AUC、K-S、PRC、Precision、Recall、LiftChart 如何实现
Alink漫谈(八) : 二分类评估 AUC.K-S.PRC.Precision.Recall.LiftChart 如何实现 目录 Alink漫谈(八) : 二分类评估 AUC.K-S.PRC.Pre ...
- 入门大数据---Hbase协处理器详解
一.简述 Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立"二级索引",难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hbase 中,统计数 ...
- 面试官:你精通多少种语言的 Hello World?
Hello World,是程序员入门编程语言的第一课.不论是C.C++还是Java ,我们写的第一个程序就是它了,还记得小编在大一C语言课上,花了一整节课时间才把它打印到控制台上.万事开头难啊,相信看 ...
- vue 生命周期钩子 路由钩子 动画钩子 执行顺序
进入首页的钩子们 1 路由钩子 路由跳转前beforeEach 2 路由钩子 home组件内部:守卫执行前beforeRouteEnter 3.路由钩子 路由跳转后afterEach 4 生命周期 h ...
- 近期Java高级开发岗面试总结
原文出处:公众号:编程大道 作者:walking 近期Java高级开发岗面试总结 哈喽大家好,我是walking,这是我的公众号:编程大道. 很久没和大家见面了,文章更新的速度略有延后.这个公众号断断 ...