語法
語法源自於 Ruby,這使得我們能夠更自然的閱讀及撰寫 Crystal,且對於有經驗的 Ruby 開發者們在學習曲線上更有助益。
# 簡易 HTTP 伺服器
require "http/server"
server = HTTP::Server.new(8080) do |context|
context.response.content_type = "text/plain"
context.response.print "Hello world, got #{context.request.path}!"
end
puts "Listening on http://127.0.0.1:8080"
server.listen
編譯式
Crystal 是一個需要經過編譯的語言,這讓它可以以低成本的記憶體來執行飛快的程式。 並以 LLVM 為基石可以使 Crystal 在建置過程中進行最佳化。
網頁伺服器吞吐量比較
型別系統
Crystal 使用了靜態型別檢查,所有的型別錯誤都會在編譯時期被捕捉,而不是在執行時期才進行檢查。 另外,為了保持語言的純淨度,Crystal 還內建了型別推導的能力,在大部分的情況下,我們不需要自行宣告型別類型。
def shout(x)
# 注意不論是 Int32 或是 String 都擁有 `to_s` 的方法
x.to_s.upcase
end
foo = ENV["FOO"]? || 10
typeof(foo) # => (Int32 | String)
typeof(shout(foo)) # => String
空參照自動檢查
在 Crystal 裡的所有型別都是非空的,所有允許空值的變數都被宣告成預期型別與空值型別的集合型別。 因此,編譯器會在編譯時期自動地檢查空參照來避免著名的「The Billion Dollar Mistake 問題」。
if rand(2) > 0
my_string = "hello world"
end
puts my_string.upcase
執行結果如下:
$ crystal hello_world.cr
Error in hello_world.cr:5: undefined method 'upcase' for Nil (compile-time type is (String | Nil))
puts my_string.upcase
^~~~~~
巨集
針對 Metaprogramming,Crystal 亦內建了強大的巨集機制來實現模板機制以及在編譯時期檢閱 AST 與型別的功能,甚至於能夠在巨集中執行獨立的外部程式。
class Object
def has_instance_var?(name) : Bool
{{ @type.instance_vars.map &.name.stringify }}.includes? name
end
end
person = Person.new "John", 30
person.has_instance_var?("name") #=> true
person.has_instance_var?("birthday") #=> false
併發模型
Crystal 使用了一種稱為 Fiber 的綠色執行緒來實作併發模型。 如同 Go 或 Clojure,Fiber 能夠透過使用 Channel 來互相溝通而避免使用 SHM 與鎖。
channel = Channel(Int32).new
total_lines = 0
files = Dir.glob("*.txt")
files.each do |f|
spawn do
lines = File.read(f).lines.size
channel.send lines
end
end
files.size.times do
total_lines += channel.receive
end
puts total_lines
C 函式庫綁紮
Crystal 亦提供了簡單的語法來呼叫原生函式庫,如此一來我們便能減少在 Crystal 上重新實作的必要性。
# 以下為使用 GMP 來實作的 BigInt 的片段
@[Link("gmp")]
lib LibGMP
alias Int = LibC::Int
alias ULong = LibC::ULong
struct MPZ
_mp_alloc : Int32
_mp_size : Int32
_mp_d : ULong*
end
fun init_set_str = __gmpz_init_set_str(rop : MPZ*, str : UInt8*, base : Int) : Int
fun cmp = __gmpz_cmp(op1 : MPZ*, op2 : MPZ*) : Int
end
struct BigInt < Int
def initialize(str : String, base = 10)
err = LibGMP.init_set_str(out @mpz, str, base)
raise ArgumentError.new("invalid BigInt: #{str}") if err == -1
end
def <=>(other : BigInt)
LibGMP.cmp(mpz, other)
end
end
相依性
我們稱 Crystal 函式庫為 Shards,不同於常見的套件管理機制,Shards 避免了中心化管理而是透過 Git 來派送。 透過內建的指令我們可以輕易地透過編輯 YAML 格式的設定檔來描述套件之間的相依並從各自的倉庫抓取套件。
name: my-project
version: 0.1
license: MIT
crystal: 0.21.0
dependencies:
mysql:
github: crystal-lang/crystal-mysql
version: ~> 0.3.1
以下資訊若未即時更新請至
原文網站Articles from our blog
Release Notes
Crystal 0.20.0 released! | 22 Nov 2016 | |
Crystal 0.18.0 released! | 14 Jun 2016 | |
Crystal 0.17.0 released! | 17 May 2016 | |
Crystal 0.16.0 released! | 05 May 2016 | |
Crystal 0.15.0 released! | 02 Apr 2016 | |
Crystal 0.14.1 released! | 21 Mar 2016 | |
Crystal 0.13.0 released! | 07 Mar 2016 | |
Crystal 0.12.0 released! | 16 Feb 2016 | |
Crystal 0.11.0 released! | 23 Jan 2016 | |
Crystal 0.10.0 released! | 23 Dec 2015 |