是否值得惯用编程?一个 ES6 例子

Is it worth idiomatic programming? An ES6 example

编程就是决定如何实现任何一段代码。根据这些决定,代码将或多或少具有可读性、高效性、复杂性等。一个常见的决定也是或多或少地符合习惯,即使用特定的语句或您的编程语言或范例。

作为概念证明,我在 Javascript 中开发了两个代码片段来分析性能。目标是生成 tagA|tagB|tagC 形式的字符串,其中 tagX 的数量是随机的,后缀 ABC 是随机整数。而且,tagX不能重复

第一个实现更为地道,而第二个则更为传统。接下来是每一个的代码片段:

惯用语:

performance.mark('A');

let tags = new Set(Array.from({length: tagCount}, () => Math.floor(Math.random() * 10)));
tags = Array.from(tags).map(x => `tag${x}`).join('|');

performance.mark('B');

传统

performance.mark('C');

let tagset = new Set();
let tagstr = "";

for (let tag=0; tag<tagCount; tag++) {
    tagset.add(Math.floor(Math.random() * 10));
}

tagset.forEach((tag) => {
    tagstr += 'tag' + tag + '|'
});

tagstr = tagstr.slice(0, -1);

performance.mark('D');

为了衡量性能,我使用了 Performance Timing API

结果有点令人惊讶,至少对我来说是这样。请注意传统方法比另一种方法效率高得多。

Idiomatic: 0.436535
Traditional: 0.048177

我重复了几次实验,结果都差不多

地道的方式看起来很酷而且更短,但效率较低且难以阅读。

你怎么看?是否值得使用惯用编程而不是传统编程?是否有一个普遍的答案,或者它在很大程度上取决于每个案例?

代码的可读性和复杂性如何?

已编辑tagX不能重复。

已编辑:仅供参考,我已将完整代码上传至Github:https://github.com/aecostas/benchmark-js-looping

Idiomatic way looks pretty cool and shorter, but it is less efficient and hard to read.

如果熟悉该语言的人觉得难以阅读,则它不是“地道的”。 (你可能会按照这个词的一个定义——“使用许多惯用语”——但这并不是人们提到惯用代码时的意思,尽管 Array.from({length}, fn) 确实是一个 idiom¹ 用于根据 JavaScript 中的函数填充数组。更确切地说,它是按照语言用户期望的方式编写的代码。)您可以通过命名一些东西来更接近它:

const tagNumbers = Array.from(
    {length: tagCount},
    () => Math.floor(Math.random() * 10),
);

const uniqueTagNumbers = Array.from(new Set(tagNumbers));

const tagString =
    uniqueTagNumbers
        .map(n => 'tag' + n)
        .join('|');

并利用实践中存在的效用函数类型:

import generate from '…';
import unique from '…';

const getRandomTag = () =>
    Math.random() * 10 | 0;

const tags =
    generate(tagCount, getRandomTag);

const tagString =
    unique(tags)
        .map(n => 'tag' + n)
        .join('|');

尽管如此,您只能使用玩具示例。

至于性能:并非所有内容都必须进行微优化。你这里的两个例子有相同的渐近时间和 space 复杂度,这对很多情况来说已经足够了。你用 JavaScript 写作是因为它的语言特性可以让你以性能为代价更好地表达自己²,毕竟。当涉及到优化时,您可能希望编写更准确的基准(这在 Node 中非常困难!)——例如尝试重新排序这些测量结果。

¹ 在某种意义上,作为一种语言用户知道的表达方式,表达方式本身并没有清楚地传达这一点。
² 或者因为其他人或其他一些人认为,现在你被困在他们的代码上,或者可能是出于某种原因而不是表现力本身,或者前面提到的人在同一个boat³, …
³ 哦嘿一个成语