crystal
飛快如 C,靈巧似 Ruby

立即安裝 入門文件 線上試玩

語法

語法源自於 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

編譯式

Crystal 是一個需要經過編譯的語言,這讓它可以以低成本的記憶體來執行飛快的程式。 並以 LLVM 為基石可以使 Crystal 在建置過程中進行最佳化。

網頁伺服器吞吐量比較

資料來源: costajobs/app-servers
> 學習如何使用 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 型別系統的資訊

空參照自動檢查

在 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

> 更多有關 Crystal 中併發模型的說明

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

> 瞭解如何與 C 函式庫互動

相依性

我們稱 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

> 參閱 Shards 的 GitHub 頁面以瞭解更多

以下資訊若未即時更新請至

原文網站

Articles from our blog

authors/mdavid.jpg María Inti David 23 Mar 2017

Announcing Crystal CodeCamp SF2017

chat_bubble_outline


authors/spalladino.jpg Santiago Palladino 24 Feb 2017

State of Crystal at 0.21

What did we do since new year?

chat_bubble_outline


authors/lschutz.jpg Leonard Schütz 06 Jan 2017

The Charly programming language

Guest blog post by Leonard Schütz

chat_bubble_outline


More articles

社群資源

更多……