Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

静的型付け言語 Crystal

2,327 views

Published on

from Tokyo Crystal Meetup #2 (2015-10-23)

Published in: Technology
  • Be the first to comment

静的型付け言語 Crystal

  1. 1. 静的型付け言語 Crystal Crystal The Programming Language with Static Typing Hirofumi Wakasugi (@5t111111)
  2. 2. Crystalは静的型付けの プログラミング言語です。
  3. 3. 静的型付け • 変数などの型はコンパイル時に決定されている • 型チェックによって事前にバグを捕捉しやすい • 変数などの型は実際の実行時の値になる • 柔軟で再利用性の高いプログラムを書きやすい 動的型付け
  4. 4. 動的型付けのRubyと 静的型付けのCrystal どっちが優れてるかとか そういう話はしません!
  5. 5. Crystalが 静的型付け言語として どのように働くか 淡々と見ていきます。
  6. 6. 変数の定義 a = 3 b = "we are like crystal, we break easy" c = [1, 2, 3] • 変数 a の型は Int32 • 変数 b の型は String • 変数 c の型は Array(Int32) 変数は初めて値が代入されたときに宣言される
  7. 7. 変数の定義 • 変数 a の型は Int32 • 変数 b の型は String • 変数 c の型は Array(Int32) 変数は初めて値が代入されたときに宣言される a = 3 b = "we are like crystal, we break easy" c = [1, 2, 3] 型推論
 Type Inference

  8. 8. 変数への再代入 これはどうなる? エラーになってしまうの? すでに宣言されて型が決まっている変数に代入する a = "we are like crystal, it is not easy" a = 100
  9. 9. 変数への再代入 別の型を変数に代入してもエラーにはならない 変数の型は代入される式 (値) によって型推論される すでに宣言されて型が決まっている変数に代入する a = "we are like crystal, it is not easy" # ここで変数 a は String a = 100 # ここで変数 a は Int32
  10. 10. Arrayの型 これはどうなる? いけそうじゃない? Int32のArrayにString型の要素を追加する a = [1, 2, 3] a << "we are like crystal"
  11. 11. Arrayの型 Int32のArrayにString型の要素を追加する a = [1, 2, 3] a << "we are like crystal" no overload matches 'Array(Int32)#<<' with types String Overloads are: - Array(Int32)#<<(value : Int32) a << "we are like crystal" ^~ これは コンパイルエラー Error
  12. 12. 空のArray 型を指定せずに空のArrayを宣言することはできない a = [] # Syntax Error a = [] of Int32 # OK! ということは、 異なる型の要素を含むArrayは 作れない?
  13. 13. Union型 ArrayはGeneric型であり、(Union型を含む) 要素 の型を指定できる
 Hashなど、他のコンテナ (コレクション) 型も同様 型の組み合わせを表現するUnion型 a = [1, 2, 3, "we are like crystal"] #=> Array(String | Int32) a = [] of String | Int32 #=> Array(String | Int32)
  14. 14. Generic型 (後で説明しますしません)
  15. 15. メソッド呼び出し これはどうなる? エラーになってしまうの? ある型 (クラス) に存在しないメソッドを呼び出した場合 a = 3 a.size
  16. 16. メソッド呼び出し ある型 (クラス) に存在しないメソッドを呼び出した場合 a = 3 a.size undefined method 'size' for Int32 a.size ^~~~ これは コンパイルエラー Error
  17. 17. メソッド引数 def put_size(x) puts x.size end put_size("crystal") put_size(5) undefined method 'size' for Int32 puts x.size ^~~~ Error 引数で渡されたオブジェクトにメソッドがない
  18. 18. 型制約 def put_size(x : String) puts x.size end put_size(5) no overload matches 'put_size' with types Int32 Overloads are: - put_size(x : String) put_size(5) ^~~~~~~~ Error 引数に型アノテーションを指定し型を制約する
  19. 19. 型制約があると安心だね!
 引数はどんどん型制約しよう!
  20. 20. Re: メソッド引数 def put_size(x) puts x.size end put_size("crystal") put_size([1, 2, 3]) 引数で渡されたオブジェクトにメソッドがある えっ?
  21. 21. Re: メソッド引数 def put_size(x) puts x.size end put_size("crystal") put_size([1, 2, 3]) 引数で渡されたオブジェクトにメソッドがある 7 3 Result エラーなく正常終了する
  22. 22. Re: def put_size(x) puts x.size end put_size("crystal") put_size([1, 2, 3]) 引数で渡されたオブジェクトにメソッドが 7 3 Result エラーなく正常終了する 明確に型制約がされてい なければ、ある型が呼び 出されるメソッドに応答 するとき、コンパイラの 型チェックは通る。
  23. 23. ダックタイピング的な型システム 型そのものやその継承関係に依存しない、 柔軟性を持った静的型付けになっている シグネイチャが特に重要であるという点で、
 Structural Subtyping (構造的部分型付け) と言ってもよいかも
  24. 24. Re: Re: メソッド引数 def put_size(x) puts x.size end put_size("crystal") put_size(5) undefined method 'size' for Int32 puts x.size ^~~~ Error 型制約をしなくてもコンパイル時にエラーが捕捉される 不必要な型制約は 柔軟性を欠く
  25. 25. インスタンス変数 インスタンス変数も代入される値から型推論される class Person getter name def initialize(@name) end end barney = Person.new "Barney" barney.name #=> "Barney" barney.name.size #=> 6
  26. 26. barney = Person.new "Barney" barney.name.size one = Person.new 1 Re: インスタンス変数 インスタンス変数に異なる型を与えて初期化 なんかおかしいとこある?
  27. 27. barney = Person.new "Barney" barney.name.size one = Person.new 1 Re: インスタンス変数 インスタンス変数に異なる型を与えて初期化 undefined method 'size' for Int32 (compile-time type is (String | Int32)) barney.name.size #=> 4 ^~~~ これは コンパイルエラー Error
  28. 28. if var.is_a?(…) is_a? で型をチェックし制限する if a.is_a?(String) # ここでは a が # String で「ある」ことが保証される else # ここでは a が # String では「ない」ことが保証される end コンパイル時リフレクションによる型の保証
  29. 29. if var.responds_to?(…) responds_to? で応答をチェックし制限する if a.responds_to?(:size) # ここでは a が # size に応答「する」ことが保証される else # ここでは a が # size に応答「しない」ことが保証される end コンパイル時リフレクションによるメソッド応答の保証
  30. 30. Re: Re: インスタンス変数 is_a? や responds_to? で制限する if (name = barney.name).is_a?(String) name.size #=> 4 end if (name = barney.name).responds_to?(:size) name.size #=> 4 end インスタンス変数の場合は、上記のように一度変数に代入する必要がある
  31. 31. as as で型を制限することもできる name = barney.name as String name.size #=> 4 • asは実行時にチェックを行う • 対象がStringでなかった場合には例外が発生 • asはキャストではない (別の型への変換はしない)
  32. 32. nil-able ある型がNil型を持つ可能性 a = [] of String? a.class #=> Array(String?) a << "crystal" #=> ["crystal"] a << nil #=> ["crystal", nil] • String?は型がNil型を持つことを意味する • (String ¦ Nil) というUnion型と同様
  33. 33. nil-able インスタンス変数 initializeで初期化されないインスタンス変数 class Person getter name property address def initialize(@name) end end barney = Person.new "Barney" barney.address = "Manchester" barney.address.size
  34. 34. nil-able インスタンス変数 initializeで初期化されないインスタンス変数 barney = Person.new "Barney" barney.address = "Manchester" barney.address.size undefined method 'size' for Nil (compile-time type is String?) barney.address.size ^~~~ Error これは コンパイルエラー initializeで初期化されないインスタンス変数はNil型を持つ
  35. 35. Re: nil-able インスタンス変数 インスタンス変数をinitializeの外側で初期化する class Person getter name property address @address = "nowhere" def initialize(@name) end end barney = Person.new "Barney" barney.address = "Manchester" barney.address.size #=> 10
  36. 36. インスタンス変数の型指定 インスタンス変数を型アノテーションで指定する class Person … @address :: String … end • @addressにString以外の型を代入するとエラー • 型のデフォルト値は存在しないので初期化は必要
  37. 37. まとめ • Crystal Ruby • 中でも静的型付けによる違いは非常に大きい それでも、 We love Ruby's efficiency for writing code. というのがCrystalの出発点の1つであるように、 Rubyの柔軟性や生産性、気持ちいい書き味を維持して 静的型付けにしようとする工夫が随所に見られる。
  38. 38. 話せなかった話題たち • Generic型 (Generics) • 例外処理内での型推論の働き • クロージャ内での変数の型 • マクロにおける型情報へのアクセス • typeof、Object#tryなどのメソッド • etc. etc.
  39. 39. http://ja.crystal-lang.org/docs/ 今日話せなかった内容もドキュメントに記載があります
  40. 40. ドキュメントをいつもup-to-dateにするために 翻訳を手伝ってくれる方を募集しています GitHub https://github.com/crystal-jp/ja.crystal-lang.org Gitter https://gitter.im/crystal-jp/ja.crystal-lang.org もしくは @5t111111 まで直接お知らせください! Slack http://crystal.pine.moe/
  41. 41. 本スライド中のサンプルコード およびその出力内容は すべて Crystal 0.9.0 で確認しています ご静聴ありがとうございました。

×