0

0

逗号运算符的一个令人信服的案例

WBOY

WBOY

发布时间:2024-09-07 15:36:13

|

421人浏览过

|

来源于dev.to

转载

逗号运算符的一个令人信服的案例

逗号运算符是类c语言(例如javascript和c++)中鲜为人知的运算符之一。本质上,它界定了一系列表达式并仅返回最后一个表达式的结果。

const a = 1;
const b = 2;
const c = 3;
const result = (a, b, c, 4, 5, 6, true);
console.log(result); // true
if (false, true) console.log('hello'); // hello

很自然地会问:什么时候将多个表达式塞进一行会有用?此外,即使它有用,为什么用逗号分隔的表达式序列(在单行)比分号分隔的语句序列(跨多行)更具可读性和可维护性?我们什么时候应该选择其中一种而不是另一种?

这些是我多年来一直努力回答的问题,但现在我想我终于有了答案。在本文中,我针对逗号运算符提出了一个令人信服的案例(坦率地说,也许是唯一的一个案例)。

一个激励人心的例子

我们先来说一下条件三元运算符。如下所示,如果条件为真,则评估值。否则,它评估另一个。这里强调关键字“评估”,因为分支仅在满足条件时执行。

const result = condition ? value : another;

在大多数情况下,它都是整洁漂亮的。然而,当我们需要在返回条件值之前在分支之间执行更复杂的逻辑时,它就会崩溃。此时,我们诉诸这种不幸的变态:

let result; // uninitialized! yikes!
if (condition) {
    // do some complex stuff in between...
    dosomething();
    // ...
    result = value; // actual assignment
} else {
    // do other complex stuff in between...
    doanotherthing();
    // ...
    result = another; // actual assignment
}
// hopefully we didn't forget to initialize `result`!

现在这个配方存在很多问题。

  1. 结果一开始是未初始化的。这本质上并不是邪恶的,但避免由于未定义而导致错误的一种简单且经过验证的方法是始终初始化变量。
  2. 结果的初始化实际上是在分支的底部——与其声明相分离。
  3. 在条件结束时,我们最好希望结果肯定已初始化。如果不是我们,我们最好希望我们的队友同样执行这一点。如果不是现在,我们最好希望未来的开发者也能坚持这一点!

如果我们坚持使用条件三元表达式,就有办法绕过这个限制。我们只需要将代码重构为函数即可。这绝对是说起来容易做起来难。这个噱头很快就过时了!

function computewrappedvalue() {
    // ...
    return value;
}

function computewrappedanother() {
    // ...
    return another;
}

// how cumbersome!
const result = condition ? computewrappedvalue() : computewrappedanother();

基于表达式的编程语言(例如 rust)有更优雅的解决方案。通过将 if 语句 重新分类为 if 表达式 ,可以对每个分支进行求值,从而返回稍后可以存储在变量中的值。

// a conditional ternary operator thus looks like this. each branch
// returns a value, which is captured by the `result` variable.
// we thus ensure that `result` is always initialized by construction.
let result = if condition { value } else { another };
// if we wanted to do something more complex, we use the same syntax.
let result = if condition {
    do_something();
    // in rust, the last expression without a semicolon is the value
    // that will be "returned" by the overall `if` expression.
    result
} else {
    do_another_thing();
    another
};

我们可以用类似 c 的语言来模拟这个吗?你可能早就预见到了我的发展方向,但是可以!

STORYD
STORYD

帮你写出让领导满意的精美文稿

下载

一个令人信服的案例

我们想要的是一种在返回三元分支内的值之前任意执行语句的方法。好吧,对我们来说幸运的是,这正是逗号运算符的用途。

// parenthesized for clarity.
const result = condition
    ? (dosomething(), value)       // evaluates to `value`
    : (doanotherthing(), another); // evaluates to `another`

这个公式的巧妙之处在于,分支表达式仅在必要时才进行计算。我们有效地模拟基于表达式的编程语言的行为。临时包装函数的时代已经一去不复返了!

但是可惜,我们只能用这种技术走这么远。你可以想象,对于一些足够大的 n,将 n 条语句塞进一行已经需要重构到它自己的函数中。就我个人而言,到 > 3 时我已经重新考虑了。就可读性而言,任何高于此值的结构都是可疑的。

// maybe we should reconsider here?
const result = condition
    ? (x++, thing = hello(), dosomething(), value)
    : (++y, thing = world(), doanotherthing(), another);
// Okay, stop. Definitely turn back now!
const result = condition
    ? (
        x++,
        thing = hello(),
        doSomething(),
        doMore(y),
        doEvenMore(thing),
        value,
    ) : (
        ++y,
        thing = world(),
        doAnotherThing(),
        doMore(y),
        doEvenMore(thing),
        another,
    );
// Unless, of course, you're fine with this. It kinda does
// look like a Rust `if` expression if you squint hard enough.

结论

总而言之,我们看到了逗号运算符的一个令人信服的案例:复杂的条件三元运算。当分支又短又甜时,逗号运算符会大放异彩,但在三个内联语句之后很快就会过时。到那时,重构代码可能会更好。

那么你应该使用逗号运算符吗?老实说......是的!可读的代码会考虑到下一个读者,因此只要逗号链不会太长,我就会接受甚至鼓励这种编码风格。如果我们考虑替代方案(即未初始化的变量和重构的微函数),逗号运算符毕竟没那么糟糕。

在实践中,我已经在自己的代码库中添加了这些看起来很有趣的逗号运算符。但公平地说,我很少需要多语句三元条件。但当我这样做时,我的腰带上就有了一个很酷的工具,可以简洁地表达我的意图。

为此,我对逗号运算符提出了令人信服的理由。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

401

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

619

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

354

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

259

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

606

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

530

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

645

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

603

2023.09.22

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

15

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Rust 教程
Rust 教程

共28课时 | 4.9万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.9万人学习

Go 教程
Go 教程

共32课时 | 4.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号