Sweet.js 宏很简单,它们乍一看很神秘。
F# 语言中的正向管道,中缀运算符|>
将右侧的函数应用于左侧表达式的结果。
新语法应如下所示(|>
宏):
var seven = 7;
var outcome = 3 |> plus(seven) |> divideBy(2); // outcome must be 5
管道宏必须将参数附加到函数,以便扩展后的函数看起来像这样plus(seven, 3)
:
问题中的 sweet.js 宏适用于最简单的情况。
主要部分在这个片段return #{ /** macro expansion template */ }
中。它包含在编译时执行的 JavaScript(sweet.js),返回的文本是宏扩展的代码。编译结果:
var outcome$633 = plus.length <= [seven].length + 1 ? plus(seven, 5) : plus.bind(null, seven, 5);
js 中函数的length
是其预期位置参数的数量。
允许使用对象中包含的函数的复杂宏(点表示法):
macro (|>) {
case infix { $val | _ $fn(.)... ( $args(,)... ) } => {
return #{
($fn(.)....length <= [$args(,)...].length + 1 ? $fn(.)...( $args(,)..., $val) : $fn(.)....bind(null, $args(,)..., $val))
}
}
case infix { $val | _ $fn($args ...) } => {
return #{
($fn.length <= [$args ...].length + 1 ? $fn($args ..., $val) : $fn.bind(null, $args ..., $val))
}
}
case infix { $val | _ $fn(.)... } => {
return #{
($fn(.)....length <= 1 ? $fn(.)...($val) : $fn(.)....bind(null, $val))
}
}
}
()
如果管道中的函数不接受参数,则此宏的一个限制/要求是省略括号。
行var outcome = 5 |> plus(seven) |> obj.subObj.func;
扩展为 js 中的这个嵌套三元运算符表达式:
var outcome$640 = obj.subObj.func.length <= 1 ? obj.subObj.func(plus.length <= [seven].length + 1 ? plus(seven, 5) : plus.bind(null, seven, 5)) : obj.subObj.func.bind(null, plus.length <= [seven].length + 1 ? plus(seven, 5) : plus.bind(null, seven, 5));