crystal.tokyo #7 で Concurrency について話しました
2018/07/18 に crystal.tokyo #7 を開催しました。
前回の「Crystal勉強会」から名称を変えて「crystal.tokyo」としました。 crystal-jp.slack.com でご意見を募ったところ、「crystal.tokyo」が一番票を得たので変更しました。「登壇者&聴衆」という勉強会スタイルに縛られずに、もっといろんな形で交流できたら良いなと思っています。
毎回のごとく、開始前からお酒を開放。
なんか飯が届くの遅れてるらしく、始まるのも遅れて、じゃあ何してるかというとひたすらビール飲んでるというw #crystaljp
— 組長☆馬 (@Goryudyuma) 2018年7月18日
ピザ寿司が届くと同時に、LTを開始しました。
Concurrency
最初は自分でした。Concurrencyについて話しました。
CrystalのConcurrency!しょっぱなからディープトークっすわ! #crystaljp
— 今城 (@imajou) 2018年7月18日
.。oO(Crystalはsingle threadなので…) #crystaljp
— ふわっふわさっちゃん♬♪♡ (@ne_sachirou) 2018年7月18日
Great talk about concurrency with #crystallang by the great @at_grandpa #crystaljp https://t.co/NuxTOgLgIR
— Carlos Donderis (@CaDs) 2018年7月18日
図を用いて説明しようとしたのですが、図解がかなり難しかったので諦めました。発表後に「Goにあるような『メッセージのバッファ数』を指定することはできるか」という質問がありました。「CrystalのChannelでも指定できます」とお答えしましたが、改めてここでコードを紹介します。下記のConcurrencyに関する公式ドキュメントの「Buffered channels」で説明されています。
本家のコードを引用します。
# A buffered channel of capacity 2 channel = Channel(Int32).new(2) spawn do puts "Before send 1" channel.send(1) puts "Before send 2" channel.send(2) puts "Before send 3" channel.send(3) puts "After send" end 3.times do |i| puts channel.receive end
出力は以下です。
Before send 1 Before send 2 Before send 3 1 2 After send 3
Channel(Int32).new(2)
の部分でinitializeの引数としてメッセージのバッファ数を指定しています。するとこのChannelは以下のような特徴を持ちます。
- sendを呼び出したときは、メッセージがバッファ数に達するまで蓄積する
- メッセージ数がバッファ数に達していない場合、sendを呼んでもFiberの切り替えは行われない
- 蓄積されたメッセージはインスタンス変数
@queue
に格納されている
- receiveを呼び出したときは、蓄積されたメッセージを順に返す
- 複数回receiveを呼び出したら、
@queue
から順にshiftされてメッセージが返ってくる - メッセージが蓄積されていない場合はFiberの切り替えが行われる
- 複数回receiveを呼び出したら、
この挙動に注意して処理を追うと、上記の出力結果になることがわかると思います。
Crystal in Operation
次は @arcage さんです。地方からのご参加でした。タイトルは 「Crystal in Operation」。
サーバー管理業務でCrystalを使ってる話! #crystaljp
— 今城 (@imajou) 2018年7月18日
ファイル操作の有用な情報ばっかりだ。 #crystaljp
— at_grandpa (@at_grandpa) 2018年7月18日
Crystalでパトライト回すのいい! 今の現場でまわしたい。
— n.siena (@n_siena) 2018年7月18日
(^^;
#crystaljp
日々のネットワーク周りの業務で使うツールをCrystalで書かれているお話でした。システム周りの情報を取得するClassの紹介だったり、ファイル操作に便利なClass、プロセス周りの情報を取得するClassなど、自分は知らなかった有用な情報が盛りだくさんでした。逆にCrystalに足りない部分も言及されています。結論はぜひ資料を御覧ください。
Crystalのインスタンス変数の型推論について
最後は @make_now_just さんです。インスタンス変数の型推論のお話でした。
「Crystalの型推論は3つある」 #crystaljp
— at_grandpa (@at_grandpa) 2018年7月18日
型推論!気になってた話題! #crystaljp
— 組長☆馬 (@Goryudyuma) 2018年7月18日
ライブコーディングだ!! #crystaljp
— 組長☆馬 (@Goryudyuma) 2018年7月18日
rubyの場合はnilが返るがcrystalの場合はコンパイルされない、という話や、「Crystalのインスタンス変数の型推論の内容はエラー文に書いてある」ということなど、型推論に関することを発表されていました。発表のあとは、 @make_now_just さんのPRの話に移ったり、ライブコーディングで「このケースではどういった型推論になるのか」というのを会場全員で考えて確認する、という流れが生まれました。こういうの、良いイベントだなぁと思った瞬間です。
話題になったのが、次の例では @arg
の型はなんでしょう?というものです。
class Hoge getter arg def initialize(@arg : Int32) end def initialize(@arg : String) end end hoge = Hoge.new("string") puts typeof(hoge.arg) # => ここは何が表示される?
正解は (Int32 | String)
です。ここは会場でもある程度予想はできていました。では、次はどうでしょうか。
class Hoge getter arg : Int32 # ここで型を定義する def initialize(@arg) # ここで型は定義しない end def initialize(@arg : String) end end hoge = Hoge.new("string") puts typeof(hoge.arg) # => ここは何が表示される?
正解はコンパイルエラーです。
$ crystal hoge.cr Error in hoge.cr:11: instantiating 'Hoge:Class#new(String)' hoge = Hoge.new("string") ^~~ in hoge.cr:7: instance variable '@arg' of Hoge must be Int32, not String def initialize(@arg : String) ^~~~
このコンパイルエラーは Hoge.new("string")
の部分で起きています。しかしこの場合、 def initialize(@arg : String)
のメソッド定義の部分でエラーになっても良いのでは?という意見が出ていました。確かになるほどと考えさせられる内容でした。
こういった形で、会場が一体となって意見交換できるのはとても良いなと思いました。
そのまま懇親会へ
個々の会話ベースの懇親会もいろいろ話すことができて良いのですが、今回は「Crystalの話題にフォーカスし、個々人の困っている点や疑問を会場で共有しよう」ということにチャレンジしました。形式としては、
- わいわい周りの人と話しても良い
- ピザ寿司食べていても良い
- なにか疑問に思ったことがあったら、プチLTのように前に出て、会場に疑問を投げかける
- 会場の人は興味があれば一緒に考えて意見を交換する
という形です。何かを強制することはありません。登壇者の話を必ず聞く必要もないですし、必ず誰かが登壇しなければいけないということもありません。疑問や困りごとがあったらみんなに聞こう!というスタンスです。
どうなるかわからなかったのですが、結果的に会場から以下の話が出てきました。
- デバッグってどうしていますか
- WAFを使っているCrystalコードのレビュー
- Webサーバーのテストってどうしていますか
- 別の勉強会で話したLTをここでもします!
それぞれいい感じに意見交換できてよかったです。また、ネタが尽きたとしても自然とわいわいと会話発生し、良い雰囲気だなと思いました。
まとめ
まだまだ発展途上で至らない点も多かったので、今後もどんどん改善していきたいです。
今回も楽しかったー!とはいえ、まだまだファシリテート不足でグダグダ感があって申し訳なさが大きい。でもなんとか参加者の方に良い体験をしていただきたいんだよなぁ。
— at_grandpa (@at_grandpa) 2018年7月18日
皆さんも温かくて、いろいろお手伝いしていただき、ありがとうございました! #crystaljp
帰宅った。 #crystaljp は発展途上感が楽しかった。言語仕様の見てないところも早めに押さえようっと。
— n.siena (@n_siena) 2018年7月18日
せっかくの寿司ピザスポンサーのご厚意だったけど、暑さでそれどころではなく ><;
Crystalの普及ももちろんですが、「ハードルは低く、満足度は高く」を目指して、イベント開催のPDCAを回していけたらと思います。