Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Computation Expressions for Haxe

626 visualizaciones

Publicado el

NGK2018Bの発表資料です

Publicado en: Tecnología
  • Sé el primero en comentar

Computation Expressions for Haxe

  1. 1. Computation Expressions for Haxe terurou 2018-12-22
  2. 2. プロフィール(個人/会社) • terurou • デンキヤギ(株) 代表取締役 兼 チーフアーキテクト • 代表作:デンキヤギ就業規則 *1 • 会社見学に来ると、寿司か焼肉をご馳走します。 • ✉terurou@denkiyagi.jp or @terurou まで 1*1 https://github.com/DenkiYagi/EmployeeHandbook
  3. 3. Haxeとは 2
  4. 4. Haxeとは • クロスプラットフォームなプログラミング言語 • JavaScript, Flash, C++, C#, Lua, PHP, Java, Python, HL, Neko • HTML5, Android, iOS, Desktop, Adobe AIR, … • コンパイルが速い • JSターゲットの場合、TypeScriptの7.0倍、Dart2の14.4倍速い *1 • 静的型、代数的データ型(GADT)、マクロ(AST変換) • Haxe 4.0で“関数のアロー構文”がついに実装 3*1 https://github.com/damoebius/HaxeBench
  5. 5. Haxeの使われどころ • ゲーム開発(これがメイン) • Dead Cells(The Game Award 2018 Best Action Game受賞), Northgard, Evoland(Haxe作者が創業した会社が制作) など • 国内でもHaxeゲーム開発の事例あり • Webシステム開発 • Backlog *1, Nepula *2 (私が把握しているもの、他にもあるはず) • 弊社開発案件 (3プロジェクト、長期継続中) • その他にも、ググってるとHaxeを使ってそうなものが見つかる 4 *1 https://www.wantedly.com/companies/nulab/post_articles/127346 *2 https://nepula.net/nepula
  6. 6. Computation Expressions に至るまでの軌跡 5
  7. 7. Computation Expressions(コンピュテーション式)とは 制御フローを簡潔に記述する専用構文と、 専用構文を実行できる形に変換するマクロ もしくは F#におけるMonad, Monad Transformer 6
  8. 8. F# コンピュテーション式の解説 • 入門(何ができるのかレベル) • mzpさん:F#プログラマのためのMaybeモナド入門 *1 • 詳細情報 • MSDN F# Computation Expressions *2 (英語版で読むべき) • bleis-tiftさん:詳説コンピュテーション式 *3 7 *1 http://d.hatena.ne.jp/mzp/20110205/monad *2 https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions *3 http://bleis-tift.hatenablog.com/entry/computation-expression
  9. 9. コンピュテーション式、完全に理解した みなさんがコンピュテーション式を 完全に理解できたので、本題へ 8
  10. 10. デンキヤギの最近の仕事 • JavaScriptは生成するもの、人間が書くものではない • 静的型付きな言語でかつ代数的データ型を使いたい • Node.js • Serverless(Azure Functions, AWS Lambda), Koa.js • 小難しいWebフロントエンド開発 • SPA, PWA, ServiceWorker, WebAudio, WebAssembly, … • Adobe AIR(Haxe/Flash) → HTML5(Haxe/JS+OpenFL)へ移植 • Vue.js : 副作用を扱いたい(扱わざるを得ない)事が多い 9
  11. 11. モチベーション 非同期処理というか、 Node.jsとコールバック地獄が しんどい 10
  12. 12. 深いネスト、エラーチェックも必要 ファイルの「アクセス権チェック」「読み込み」だけでつらい 11 const fs = require('fs'); const path = 'hoge.txt'; fs.access(path, fs.constants.R_OK, err => { if (err == null) { fs.readFile(path, {encoding:'utf-8'}, (err, data) => { if (err == null) { console.log(data); } else { console.error(err); } }); } else { console.error(err); } }); Node.js コールバックの分だけ ネストが深くなる
  13. 13. Node.jsには util.promisify() と async/await がある • util.promisify() • Nodebackスタイル関数をPromiseを返す関数に変換できる • Nodebackとは「第一引数でエラーを受けるコールバック」 • aync/await • Promiseを使ったコードを手続き型的にフラットに書ける 12
  14. 14. util.promisify() + async/awaitを使ったJSコードに書き換え ネストがなくなり、手続き型っぽいコードに 13 const fs = require('fs'); const util = require('util'); const access = util.promisify(fs.access); const readFile = util.promisify(fs.readFile); const path = 'hoge.txt'; (async () => { await access(path, fs.constants.R_OK); return await readFile(path, {encoding:'utf-8'}); })().then( data => console.log(data), err => console.error(err) ); Node.js 関数を変換 async/await
  15. 15. でも、Haxeからutil.promisify() + async/awaitを使うのはつらい • async/awaitはHaxeにはない構文なので、どうする? • util.promisify()にHaxeでうまく型定義がつけられず、 型情報がすべて消し飛んでしまう大きな問題 14 extern class Util { function promisify(fn: Function) : Rest<Dynamic> -> Promise<Dynamic>; } 引数は単に関数でさえあればいい コールバック関数という型制約はできない promisify()で変換後の関数 ・ 引数:型・長さの制約なし ・ 戻り値:型不明の値を返すPromise Haxe
  16. 16. [2018-02-20] Haxe用のpromisify()っぽいものを作成 マクロでコールバック関数をAST解析+型推論して変換 15https://twitter.com/terurou/status/965882934870786048
  17. 17. [2018-03-06] HaxeからJS Nativeのasync/awaitを使えるようにした マクロ+インラインJSでasync/awaitに変換 16https://twitter.com/terurou/status/970871928255729664
  18. 18. こういう感じで書けるようになった 17 import js.node.Fs; using hxgnd.PromiseTools; class Main { static function main() { (function () { var path = "hoge.txt"; Fs.access.callAsPromise(path, Fs.constants.R_OK) .await(); var data = Fs.readFile .callAsPromise(path, {encoding:"utf-8"}) .await(); }).asyncCall().then( function (data) trace(data), function (err) trace(err) ); } } Haxe
  19. 19. しばらく使ってみたが、微妙… • async/awaitの実装が無理やりなので、実装ミスしがち • asyncを付け忘れても、Haxe上はコンパイルが通ってしまう • メソッドにはasyncがつけられない • Haxeの構文には手が出ないので、対応が難しい • メソッドの直下にasync functionを書けば済むので許容範囲内 • fn.callAsPromise(…).await() というコードが横に長い 18
  20. 20. [2018-09-17] マクロでHaxe Nativeのasync/await専用構文を作った そもそも、JS Nativeのasync/awaitも構文糖衣という事に 気が付いて、専用構文をマクロでAST変換 19https://twitter.com/terurou/status/1041685595884380161
  21. 21. JS Nativeのasync/awaitにだいぶ近くなった 20 import js.node.Fs; import hxgnd.Promise; using hxgnd.FunctionTools; class Main { static function main() { Promise.compute({ var path = "hoge.txt"; @await Fs.access.callAsPromise(path, Fs.constants.R_OK); var data = @await Fs.readFile .callAsPromise(path, {encoding:"utf-8"}); data; }).then( function (data) trace(data), function (err) trace(err) ); } } Haxe Promise.compute()の中で @awaitが使えるようになった
  22. 22. 人間の欲望は果てしない • この時点で限定的なコンピュテーション式を実装して、 その上にasync/awaitを表現していた • 蛇足だが、JS以外のターゲットでも動作するようになった • フルセットのコンピュテーション式も実装可能では? • 実装すると、専用構文内で if, for, while が使えるようになる 21
  23. 23. [2018-11-23] yieldを除くコンピュテーション式を実装 専用構文をF#のコンピュテーション式風に統一した 22 https://twitter.com/terurou/status/1065790767040360448 https://twitter.com/terurou/status/1065792144516964352
  24. 24. [2018-12-04] コールバック関数専用のコンピュテーション式 最小限のコードで、util.promisify()+async/await相当を 型安全に書けるようにした 23https://twitter.com/terurou/status/1069966913848135681
  25. 25. Node.jsより簡潔に記述できて、型安全!!入力補完も動く! 24 import js.node.Fs; import hxgnd.NodebackFlow; class Main { static function main() { NodebackFlow.compute({ var path = "hoge.txt"; @do Fs.access(path, Fs.constants.R_OK); @var data = Fs.readFile(path, {encoding:"utf-8"}); return data; }).then( function (data) trace(data), function (err) trace(err) ); } } Haxe
  26. 26. まとめ 25
  27. 27. 今後の課題 実装はGitHubで公開 *1 したけど、 ドキュメントを書くのがしんどい 26*1 https://github.com/DenkiYagi/hxgnd
  28. 28. まとめと所感 • Node.jsでのコールバック地獄のこと考えているだけで 1年が溶けたが、型安全かつ簡潔に書けるようになった • Node.jsとかTypeScriptでは到達できない領域なので満足 • コンピュテーション式を考えた人は、すごく頭がいい • 発表時間が足りないので内部実装の解説は割愛した • もしニーズがあれば話すんで呼んでください • ドキュメントはいつか書きます・・・ 27

×