Slide 1

Slide 1 text

ReScript JSの世界に厳密な型を

Slide 2

Slide 2 text

•㈱バリューソース •神崎 善司 •twitter:@zenzengood •RDRA:https://www.rdra.jp/ •著作 •モデルベース要件定義テクニック •RDRA2.0ハンドブック •開発したツール(ReScript) •LLMで要件定義を行う:RDRAZeroOne •要件定義支援 :RDRAGraph •仕事 •RDRA導入支援 •要件定義支援 •既存システムの可視化支援 •好きな事 •システムの可視化 •モデリング •表形式でのモデリング LLMの活用したプログラミング RDRAZeroOne RDRAGraph

Slide 3

Slide 3 text

ReScript 基本的な特徴 ● Ocaml由来の関数型言語 ○ 基本的にimmutable(不変)だがmutableも可能 ○ 高階関数、カリー化など基本的な関数型言語の特徴を備える ○ React用のライブラリもある ● 構文 ○ JavaScriptに比べて構文が簡潔 ○ 強力な構文 ⇒ Variant/record/Pattern Matching ○ 使いやすいライブラリ(JSとほぼ同じように使える) ○ 抽象プログラミング可能:Module Functor ● トランスパイル ○ 型の整合性を厳密にチェック:option型によるnull安全性 ○ トランスパイルが非常に高速 ○ 効率的な実行 ■ JSの処理に変換(ReScript用のライブラリ不使用) ■ 出力されるJSもReadableで効率的なJSに変換

Slide 4

Slide 4 text

基本構文 JavaScript ReScript no types type point = {x: int, mutable y: int} {x: 30, y: 20} Same point.x Same point.y = 30; Same {...point, x: 30} Same Object/Record JavaScript ReScript [1, 2, 3] Same myArray[1] = 10 Same [1, "Bob", true] (1, "Bob", true) Array 型があるのでタプル JavaScript ReScript for (let i = 0; i <= 10; i++) {...} for i in 0 to 10 {...} for (let i = 10; i >= 0; i--) {...} for i in 10 downto 0 {...} while (true) {...} while true {...} Loop JavaScript ReScript if (a) {b} else {c} if a {b} else {c} * a ? b : c Same switch pattern matching! If-else 式なので返される型は 同じでないといけない 基本的な構文はJSとほぼ同じ

Slide 5

Slide 5 text

Variant type myResponse = | Yes | No | PrettyMuch let areYouCrushingIt = Yes type account = | None | Instagram(string) | Facebook(string, int) let myAccount = Facebook("Josh", 26) let friendAccount = Instagram("Jenny") type user = | Number(int) | Id({name: string, password: string}) let me = Id({name: "Joe", password: "123"}) 複雑な構造を簡潔に記述

Slide 6

Slide 6 text

Pattern Matching let message = switch person1 { | Teacher({name: "Mary" | "Joe"}) => `Hey, still ~?` | Teacher({name}) => `Hello ${name}.` | Student({name, reportCard: {passing: true, gpa}}) => `${name}, ${Float.toString(gpa)}~` | Student({ reportCard: {gpa: 0.0}, status: Vacations(daysLeft) | Sabbatical(daysLeft)}) => `~${Int.toString(daysLeft)} ~` | Student({status: Sick}) => `How are you feeling?` | Student({name}) => `Good luck next semester ${name}!` } let students = ["Jane", "Harvey", "Patrick"] switch students { | [] => Console.log("There are no students") | [student1] => Console.log("There's ~: " ++ student1) | manyStudents =>Console.log2("The students ~: ", manyStudents) } 複雑なパターン Arrayのパターン 0件 1件 多数

Slide 7

Slide 7 text

トランスパイル open Array let funA = () => [1, 2, 3] let b = funA() -> map(x => x * 2) let c = b -> filter(x => x < 2) function funA() { return [1, 2,3]; } var b = [1,2,3].map(function (x) { return (x << 1); }); var c = b.filter(function (x) { return x < 2; }); ReScript Javascript type account = | None | Instagram(string) | Facebook(string, int) let myAccount = Facebook("Josh", 26) let friendAccount = Instagram("Jenny") ReScript Javascript var myAccount = { TAG: "Facebook", _0: "Josh", _1: 26 }; var friendAccount = { TAG: "Instagram", _0: "Jenny" }; JSのArray処理 関数定義 JSの関数 タグ付けされた オブジェクト

Slide 8

Slide 8 text

トランスパイル1 var categoryId = 2; var isBig = true; var myAnimal = "Cat"; type animal = Dog | Cat | Bird let isBig = true let myAnimal = Cat let categoryId = switch (isBig, myAnimal) { | (true, Dog) => 1 | (true, Cat) => 2 | (true, Bird) => 3 | (false, Dog | Cat) => 4 | (false, Bird) => 5 } ReScript Javascript トランスパイル 時に最適化

Slide 9

Slide 9 text

トランスパイル2 ReScript Javascript function categoryId2(isBig, myAnimal) { if (isBig) { switch (myAnimal) { case "Dog" : return 1; case "Cat" : return 2; case "Bird" : return 3; } } else { switch (myAnimal) { case "Dog" : case "Cat" : return 4; case "Bird" : return 5; } } } let categoryId2 = (isBig, myAnimal) => switch (isBig, myAnimal) { | (true, Dog) => 1 | (true, Cat) => 2 | (true, Bird) => 3 | (false, Dog | Cat) => 4 | (false, Bird) => 5 } 関数化 JSの関数に変換

Slide 10

Slide 10 text

Javascriptとの連携 @send external cyNodeField : (cyNodesT,string) => string = "data" @send external cyEdgeField : (cyEdgesT,string) => string = "data" ele.data( name ) Get a particular data field for the element. name The name of the field to get. let msg1 = %raw(" (a) => a.content ") let msg2:string => string = %raw(“ (a) => a ++ “AA” ") ReScript Cytoscape Node(アイコン)とEdge(線)で タイプが異なるので2つ定義 CytoscapeのAPI JSの関数をそのまま記述 引数の型も帰り値の型も不定 型を記述 JSの処理を生で記述

Slide 11

Slide 11 text

まとめ ● JSと同じ構文でより簡潔 ● 厳密な型チェックと純粋ではない使いやすい関数型言語 ● JSに最適化された高速なトランスパイル