分享 【传教向】LiveScript,不仅仅是 JavaScript

saiga · 发布于 2014年08月21日 · 最后由 eryu 回复于 2014年11月04日 · 7010 次阅读
4375
本帖已被设为精华帖!

最近在充实一下贫瘠的博客好在面试时加点分,刚好撸完这篇顺道传教来了... 另外博客里面还有好几篇关于 LiveScript 的:)

如果你还不知道 LiveScript,可以看看这里: 从CoffeeScript转到LiveScript的10个理由

脱离 <- 回调嵌套

<- 这是直接引诱我从 CoffeeScript 转到 LiveScript 的符号,他可以扁平化嵌套回调

# CoffeeScript
$ ->
  $(document).on 'click', '#btn', (e) ->
    $.get '', (resp) ->
      console.log resp
# LiveScript
<-! $
e <- $ document .on \click \#btn
resp <- $ .get ''
resp |> console .log

上面这两段代码是等价的,但是 LiveScript 明显少了很多缩进

不过,如果中间夹杂着顺序逻辑,这或许会给你造成困扰...

# CoffeeScript
$ ->
  $(document).on 'click', '#btn1', (e) ->
  $(document).on 'click', '#btn2', (e) ->

这时候可以使用 do 来摆脱嵌套

<-! $
do
  e <- $ document .on \click \#btn1
do
  e <- $ document .on \click \#btn2

多才多能的 do

在 CoffeeScript 中,do 可以立即调用函数。而在 LiveScript...

调用函数

foo = ->
do foo # CoffeeScript 也有
foo! # LiveScript推荐的无参调用

参数包装

# CoffeeScript
foo = (int, obj) ->
foo 123,
  bar: 1

LiveScript 并不支持换行+缩进调用,但可以使用 do 关键字来实现真正的多行参数,这在用表达式作为参数时非常有用

foo = (int, obj) ->
foo do
  if true then 1 else 2
  bar: 1

代码块,相当于 (...)

fn = (arg1, arg2) ->
do
  e <- doAsync!
do 
  fn do
    do
      foo!
      bar!
    123

双向管道

管道是 LiveScript 非常炫的语法,管道前的结果将会作为管道后函数的参数被调用

[1 2 3] |> map (* 2) |> sum #=> 12

也支持反向,但只是代码反转,结果是一样的

sum <| map (* 2) <| [1 2 3]

有了正反向管道,就出现了双向管道了。LiveScript 在处理双向管道时会先计算右管道,再计算左管道

sum <| [1 2 3] |> map (* 2)

以上三段代码代码转译结果等价

占位符

LiveScript 的占位符提供了 部分应用函数 的特性

plus = (a, b) ->
  a + b
plus5 = plus 5, _
plus5 1 #=> 6

也可以应用到管道上,与上面不同的是,下面的代码不会生成 partialize$ 函数

1 |> plus 5, _

如果你熟悉 Scala,或许会像我一样写过这样的代码

new Date |> _.get-year! # 错误!

这是因为 LiveScript 的占位符只能用在参数位置,管道并不会推导成调用者本身

new Date |> -> it.get-year! # 正解

使用 let 改变上下文

立即执行函数(Immediate Functions) 在 JavaScript 到处可见,这是因为 JavaScript 搞笑的变量声明,如果在全局环境下声明会默认成为全局变量

在 CoffeeScript 和 LiveScript 会把每个 script 文件内的代码都编译在立即执行函数中,所以并不常见。但有时侯我们会想改变上下文

let this = {}
  @a = 1

请注意 this 赋值一定要在最前面

let this = window, $ = jQuery
  $.do-something!

神奇的括号

LiveScript 的括号很神奇,不同的位置有着不同的效果

当括号里是变量时,会转译成函数调用

(foo 1) #== lisp 方式的函数调用
(foo (bar (cf 1))) #== 同上

当括号里是 点+变量,转译成函数定义

(.join '')

当括号里是操作符时,转译成函数定义

plus1 = (+ 1)
plus 1 #=> 2

绑定流

LiveScript 支持多层级流式调用,跟 jQuery 搭配时可以忘掉 ends() 了

$ \.content .parent!
  ..find \.sidebar
    ..append newContent
    ..addClass \highlight
  ..toggleClass \dark
  ..prepend newHeader

这段代码会被翻译为

var x$, y$;
x$ = $('.content').parent();
y$ = x$.find('.sidebar');
y$.append(newContent);
y$.addClass('highlight');
x$.toggleClass('dark');
x$.prepend(newHeader);

有时候,我们会需要流间的结果

$ \.content .parent!
  sidebar = ..find \.sidebar
    ..append newContent
    ..addClass \highlight
  ..toggleClass \dark
  ..prepend newHeader

sidebar

函数复合

函数复合可以将几个操作合并在一起,调用顺序与箭头方向一致

plus1 = (+ 1)
div2  = (/ 2)
div2-then-plus1 = plus1 << div2
plus1-then-div2 = plus1 >> div2

需要注意的是函数复合不能用在方法上!因此局限很大

多样的箭头

-> 定义函数

<- 定义回调函数

!-> 无返回值函数

<-! 无返回值回调函数

~> 绑定上下文的函数,等同于 CoffeeScript 的 fat arrow

--> 柯里化函数

~~> 绑定上下文的柯里化函数

除了箭头,LiveScript 也支持 function 关键字的函数声明

总结:

LiveScript 的语法糖非常非常的多,在 CoffeeScript 的语法基础上进一步向 FP 靠拢,并提供了 prelude.ls 标准库。

入门相比 CoffeeScript 要困难,不过如果你是FP的爱好者,不妨一试 :)

ps: 这里是我用 liveScript 写的 express4 的 demo: (https://github.com/aiasfina/express4-livescript-sample)

共收到 40 条回复
2973

首先谢谢分享!

无论是coffee还是Live,都是翻译成js嘛,所以选一个就好了,由于接触coffee更早,加上更像ruby,所以对live暂时表示不爱!等哪一天对coffee无法忍受了,再来试试。

7733

livescript挺好,可以coffeescript已经满足我的需求了

96

比Coffeescript更难看懂了。。。

90

LiveScript 语法多对于适应的人来说当然是超好了, 个人觉得语法太多记不住了. 另外团队里的话, 我第一反应就是我用 LiveScript 写代码会被喷不方便协作.

4375

#1楼 @small_fish__ 的确,coffee 和 livescript 走的方向不同。coffee 一开始用 ruby 写的编译器,后来才改用自举,所以跟rubyi很像。而livescript 更像是 haskell,f# 那类的纯fp了

#2楼 @yukihiro_matz Coffee 没那么炫啊,都不能在小伙伴前耍帅了

4375

#3楼 @hxtheone 有点向fp方向走了,不习惯fp的确难懂

#4楼 @jiyinyiyong 哈哈,在团队里我也不敢用。主要是自己的项目里折腾

7733

#5楼 @saiga 耍帅我才不用js,我用Elixir

2880

:thumbsup: 学了好多 haskell 的写法

709

这里还有一个: https://github.com/Microsoft/TypeScript

全原生JS支持, 同时, 加上自己的语法与限制.

TypeScript is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript.

说来说去就是个如何写JS的问题.

2973

#8楼 @luikore 简直帅到没朋友~~~ 比如这句:

1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?) |> Enum.sum
2880

#9楼 @suffering 就是讨厌像 js/typescript 这样繁琐的写法, 而且 typescript 没解决丑陋的回调的问题

96

用opalrb好了

7733

#10楼 @small_fish__

iex(4)> 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(fn(x) -> Integer.odd?(x) end) |> Enum.sum
7500000000
96

所以那个反斜杠是什么意思?

14272

我仿佛看到了erlang......囧

5508

#1楼 @small_fish__ 同意,对live script表示无爱, 学好一种再说

2973

#13楼 @yukihiro_matz 对的,我只是表示,很有意思,代码清晰度也很高~有点喜欢商elixir了。

values = [good: 1, good: 2, bad: 3, good: 4]
for {:good, n} <- values, do: n * n

[1,4,16]
3406

#13楼 @yukihiro_matz 中间用Stream呀,Lazy Enumerables 😄

iex(4)> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(&Integer.odd?/1) |> Enum.sum
7500000000
4375

#14楼 @iwege 反斜杠 类似 symbol 的东西,翻译出来还是字符串。 字符串中间没有空格都可以用反斜杠

4375

#16楼 @jun1st 其实 coffee 和 live 兼容挺高的,很多语法相同。会live再玩coffee那是毫无问题的,反过来嘛....

7733

#18楼 @KoALa 👏 赞 一开始也是Stream,为了统一又改成Enum了。

973

好geek啊

177

#5楼 @saiga 如果按照这种说法,live是按照FP写法写的,也许他无法被一般开发人员接受,真正愿意用FP写前段Code有多少个?

2575

喜欢 CoffeeScript 就几个原因:

  1. 和 JavaScript 贴的最近,仅仅是改进了一些 JavaScript 的繁琐的地方,加了少许新特性。LiveScript, TypeScript 和 Dart 都引入了太多东西了。
  2. 不需要 jshint 之类的检查工具去辅助 JavaScript 检查错误。

长期来看我还是支持 JavaScript。这些编译成 JavaScript 的语言都面临一个问题,就是跟 ES6 的语法冲突。 有些语法像 ->, xxx for in, for ... of ..., class 在 ES6 里面也有,但 CoffeeScript 自己也定义了一套。LiveScript 的 let 在 ES6 里面也有。那写这些代码的时候,编译器是应该尊重 ES6 的语法,还是用自己的理解编译成 ES5 呢?尤其是某些语法在 ES6 和在 CoffeeScript 中的理解不一样的时候。

一个关于 CoffeeScript 和 ES6 的讨论可以见 Discourse 论坛的这篇讨论 。这也是为什么 Discourse 用 JavaScript 全部替代 CoffeeScript 的原因。当然他们这样做还有一个原因:对于开源软件来说受众更广泛的 JavaScript 能吸引更多的 contributors。不过那就不在语言讨论范围之内了。

4375

#23楼 @gene_wu 别说前端,后端也不多...

4375

#24楼 @darkbaby123 Live 是建立在 coffee 之上再加入了 FP,并且修正了 coffee 那些不如人意的地方,比如 ~= 约等,var 声明,:= 赋值穿透等等 至于 ES6,先不说得等到何年何月,那一大堆新特性就能弄倒一批常用的类库,这些转译语言肯定也不能幸免的

729

LiveScript太炫不易掌握,也没有足够多的Best Practise支持开发

10316

ES6 不是说要年底发布了嘛,到时在观望形势。

14574

还不错

198

没人来传教一下clojurescript么?

5173

#30楼 @heyuan google那货太那啥了。。。

681

哪个更接近人类语言?

96

这样搞真的好嘛。。。

34楼 已删除
96

只能说不习惯

1968

只能说不习惯

134

只能说不习惯

96

我最后又从CoffeeScript 换回Javascript了

90

早上看了土豆上唐凤的一个演讲, 里面提到了 LiveScript 不到十分钟的样子吧 她个人对 LiveScript 是盛赞的, 而且在 2006 年预言所有编程语言都会编译到 JavaScript. http://weibo.com/1914643755/Blti3aNYD 演讲开头把各种编程语言吐槽了个遍, 有兴趣的戳链接看一下..

4375

#39楼 @jiyinyiyong 感谢分享,正在看 😄

15352

最近有没有做兼职或者跳槽的打算呀

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册