Beautiful Syntax, Faster Than Go編程
它和 Mirah, JRuby, Groovy 等等的區別是: 它不須要 JVM 這個平臺, 沒有字節碼和解釋器. 很容易在速度上超過這些 JVM 語言.bootstrap
一樣是編譯成 LLVM IR 再到機器碼, 和 Ruby Motion 的區別是: Ruby Motion 依賴 ObjC 運行時, 而 Crystal 不依賴安全
除了編譯外, 和 Elixir 的區別還有: 它的語法和 Ruby 很類似, 因此 Crystal 編譯器能夠直接用 Crystal 和 Ruby 的交集寫, 而後用 Ruby 執行編譯本身, 就輕鬆完成了 bootstrap. 它的語法對熟悉 Ruby 的人更有親和力, 因此 Matz 率先捐了 $500.app
因此你看, 雖然如今還在 Alpha 階段, 仍是頗有存在乎義的.線程
Crystal 還有一些不同凡響的特性:code
面向對象類型推導對象
在一些靜態類型系統上結合 FP 和麪向對象的嘗試中, 例如 Scala 中, 推導僅侷限於方法內部. 而 Crystal 沒有這個限制, 它會盡可能修改類型定義以知足使用須要文檔
舉個栗子:get
class Person getter name def initialize @name end end daisy = Person.new "Daisy Johnson" chappie = Person.new 22 puts daisy.inspect puts chappie.inspect
使用 hierarchy 命令查看類圖編譯器
$ crystal hierarchy person.cr ... +- class Person (24 bytes) | @name : (String | Int32) (16 bytes) ...
能夠看到 Person 的 name 屬性的類型自動變成了 String | Int32
if 表達式類型推導
和 Ruby 同樣, Crystal 的 if 語句有返回值, 是表達式. 但 if 表達式在不少靜態語言中的使用卻不那麼便利, 一個巨大問題就是編譯器不能根據條件去作推斷, 例如:
val a = if (args.length > 0) { "string" } else { 42 } // a 的類型是 Any
if (a.isInstanceOf[String]) {
println(a.length) // 編譯錯誤, Any.length 沒定義, 得手動強轉
}
而 Crystal 的類型推斷會考慮條件中的 is_a? 和 responds_to? 信息, 減小了繁瑣的強制轉換:
a = ARGV.size > 0 ? "string" : 42 if a.is_a? String # 這裏 a 的類型是 String puts a.size else # 這裏 a 的類型是 Int32 puts a / 2 end
Nil 的處理
在靜態類型語言中, 有的編譯器默認容許 nil/null, 那麼就會拋出 NPE (NullPointerException), 有的編譯器會在類型上禁止一些 nil/null 的存在, 並鼓勵用 Maybe/Option 去裝箱/拆箱. 前一種方法很容易出錯, 後一種方法使用繁瑣 (尤爲在不支持 do notation 的語言中). 而 Crystal 結合數據流分析, 對 nil 值的處理更加簡單優雅. 文檔裏的例子以下:
a = some_condition ? nil : 3 # a is Int32 or Nil if a # Since the only way to get here is if a is truthy, # a can't be nil. So here a is Int32. a.abs end
不過爲了線程安全, 非局部變量不推薦這麼作
if @a @a.abs # 若是編譯器分析出 @a 能夠賦值 nil, 就會出編譯錯誤 end
上面的代碼能夠加鎖, 或者改寫成局部變量判斷的方式
if a = @a a.abs # 別的線程就改不了局部變量啦 end
和 Ruby 同樣, 因爲 Nil 上能夠定義方法, 全部值都天然變成 Maybe Monad 了, 上面的代碼也能夠改爲用 try 去處理
@a.try do |a| a.abs end
在 responds_to 的情形, 會出現這類代碼 pattern
if (a = @a).responds_to? :size a.size end
不那麼靜態
從上面能夠看到, 和通常的靜態語言相比, Crystal 的一個局部變量的類型並非固定的
a = 32 # 如今 a 的類型是 Int32 a.abs a = "foo" # 如今 a 的類型是 String a.length
在 while 循環中, 編譯器會作更復雜的事情, 儘可能不讓類型成爲阻礙編程的限制, 如下例子出自 Crystal 博客:
a = 1 while some_condition a # here a is Int32 or String or Bool if some_other_condition a = "hello" # we next, so in the next iteration a can be String next end a = false # here a is Bool end a # here a is Int32 or String or Bool
來自知乎
http://www.zhihu.com/question/33311554--- (未完待續)