ECMAScript语法提案 智能管道运算符(smart pipelines)
发布于 7 年前 作者 dislido 4287 次浏览 来自 分享

这是一个充满了函数式编程,艺术感和逼格的语法(合理利用可以有效劝退初学者和其他语言想转js的同学,减少js程序员竞争激烈程度。。。) 详情请看proposal-smart-pipelines

核心提案

中缀管道运算符... |> ...#词法 babel 7已经支持了中缀|>运算符(不过是另一个pipelines提案),#目前暂未被实现

|>运算符用来让层层嵌套的函数调用变得易读和易写

Math.sqrt(Math.sqrt(81)); // 3

81 |> Math.sqrt |> Math.sqrt; // 3

function div2(num) { return num / 2; }
// 像这样的调用不用管道运算符写起来会(十(分(难(受))));
1024
|> div2
|> div2
|> div2
|> div2
|> div2; // 32

通过以下例子可以很容易理解#这个符号的作用。

2 |> # + 2; // 4
'hello' |> # + ' world'; // 'hello world'

// 可以写在各种各样的语句中 
new Promise(resolve => resolve(123))
|> await #
|> new Foo(#)
|> bar(#)
|> baz(1, #, 2)
// |> yield #
|> # || throw new Error()
|> [#, # + 1, # + 2]
|> ({ arr: # }) // 像箭头函数返回对象时一样,这里也要用括号
|> #.arr
|> [...#]
|> (# => #.concat([1])); // 这里也必须使用括号

// console.log(
//   Math.max(
//     -(input - 3) * 2,
//     0
//   )
// );
input
|> # - 3
|> -#
|> # * 2
|> Math.max(#, 0)
|> console.log;

// # 是不可修改的
input |> (# = 1); // Error

通过|>#两个符号,我们可以轻易地将嵌套多层函数调用拍平

出于代码可读性的原因,以下用法是被禁止的

// 高阶函数使用管道语法容易在阅读代码时混淆含义
input |> object.method(); // Error
// object.method()(input);
// object.method(input);
// 此时应使用#符号
input |> object.method()(#); // ok

// 声明函数和类,在管道中,即使像下例一样简单的函数声明也会变得很难还原出原意
value
|> processing
|> function (x = #) { return x; }; // Error
// 原意如下:
// function (x = processing(value)) {
//   return x;
// }

// for/while/catch/with语句块同理
input
|> process
|> (x, y) => {
  for (const element of #)
    …
}
// (x, y) => {
//   for (const element of process(input))
//     …
// }

额外特性提案

以上是smart pipelines语法的核心提案部分,在此基础上还有一些额外的特性提案

Additional Feature BC (支持对象的构造器)

// '123'
// |> new Number(#);
'123'
|> new Number;

Additional Feature BA (支持异步函数)

async function foo(arg) { return arg; }

// 123
// |> await foo(#);
123
|> await foo;

Additional Feature BP (支持代码块)

它的表现类似于另一个提案 do-expression(事实上已经能够完全取代该语法了)。该代码块的最后一个表达式的值为代码块的值

123
|> {
  console.log(#); // 123
  # + 1;
}
|> #; // 124

Additional Feature PF (管道函数+>

邪能语法之一,让你能够在管道外的其他地方用上#

// [1, 2, 3].map(i => i * 2)
// [1, 2, 3].map(i => i |> # * 2)
[1, 2, 3].map(+> # * 2); // [2, 4, 6]

// 异步管道函数
const asyncPipelineFunction = async +>
|> await foo
|> bar;

Additional Feature TS (支持try-catch)

// let _1;
// try {
//   _1 = 1 / f(value);
// }
// catch (error) {
//   _1 = processError(error);
// }
// g (_1, 1);
value
|> f
|> {
  try |> 1 / #;
  catch |> processError;
}
|> g;

Additional Feature NP (多参数管道)

邪能语法之二…

function add(...args) { return args.reduce((a, b) => a + b, 0); }

(1, 2)
|> add(#, 4, ##); // 7

// ...会得到最后一个被使用的参数之后的所有参数
(1, 2, 4, 8)
|> add(##, ...); // 14

// 支持解构
(1, ...[2, 4, 8])
|> add(##, ...); // 14
3 回复

很久之前用过一个这样的插件,当时好像是 ~> 。这样可以让 compose 更优雅,但是第一眼看去,犹如鬼画符。

还有一些提案,也是劝退初学者的 (滑稽)

来自酷炫的 CNodeMD

作为一名初学者,我选择放弃 From Noder

回到顶部