crystal
A language for humans and computers

Install Learn Try Online

Latest release 1.4.1

22 April 2022 - More release notes


構文

Crystal の構文は Ruby の影響をつよく受けています。そのため自然に読めて、簡単に書けます。そして、 Ruby 開発の経験があれば習得は容易でしょう。

# A very basic HTTP server
require "http/server"

server = HTTP::Server.new 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(8080)

言語リファレンスで Crystal の学習をはじめましょう

型システム

Crystal は静的に型チェックされるプログラミング言語です。そのため、実行時にエラーを起こすのではなく、コンパイラが早期に型エラーを発見するでしょう。さらに、Crystal は型推論も備えています。ほとんどの場合、型注釈は必要ありません。

def shout(x)
  # Notice that both Int32 and String respond_to `to_s`
  x.to_s.upcase
end

foo = ENV["FOO"]? || 10

typeof(foo) # => (Int32 | String)
typeof(shout(foo)) # => String

Crystal の型システムについて、より詳しく知る

Null 参照チェック

Crystal ではすべての型は nil を許容しません。そして nil を許容する変数は、その型と nil とのユニオン型となります。要するに、コンパイラはコンパイル時に自動的に null 参照をチェックしてくれる、ということです。これは1億ドルの損失から免れる助けになるでしょう。

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
               ^~~~~~

マクロ

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 はファイバーと呼ばれる軽量スレッドを用いて、並列性を獲得しています。ファイバー同士は Go や Clojure のようなチャネルを用いて協調します。共有メモリやロックは用いません。

channel = Channel(Int32).new
total_lines = 0
files = Dir.glob("*.txt")

files.each do |f|
  spawn do
    lines = File.read_lines(f)
    channel.send lines.size
  end
end

files.size.times do
  total_lines += channel.receive
end

puts total_lines

Crystal の並列モデルについて、より詳しく知る

C バインディング

Crystal ではネイティブのライブラリを呼ぶため構文を持っており、低レベルのタスクの再実装は必要ありません。

# Fragment of the BigInt implementation that uses GMP
@[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 と呼ばれ、中央集権的なリポジトリを持たず Git で配布されます。shards コマンドではYAMLファイルで依存関係を指定できて、さらにそれらを取得してこれます。

name: my-project
version: 0.1
license: MIT

crystal: 1.4.1

dependencies:
  mysql:
    github: crystal-lang/crystal-mysql

Shards のリポジトリはこちら

Crystal のトップスポンサー

一覧はこちら

いくつかの CI はこちらで実行されています


コミュニティチャンネル

すべて表示