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