A Toy Robot...A Toy Robot and a Functional Pattern...
Transcript of A Toy Robot...A Toy Robot and a Functional Pattern...
![Page 1: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/1.jpg)
A Toy Robot and a Functional Pattern関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。
A Functional Programming-inspired pattern to separate instructions and interpretations.
![Page 2: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/2.jpg)
Rob Howard@damncabbagehttp://robhoward.id.au
Ambiata PureScript HaskellJavaScriptAustralia
![Page 3: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/3.jpg)
プレゼンに関して‣ プレゼンテーションは英語で行われます。 ‣ 各セクションの後に概要が表示されます。
‣ 翻訳はあまり良くないかもしれません。😰
![Page 4: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/4.jpg)
![Page 5: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/5.jpg)
...
![Page 6: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/6.jpg)
PLACE 1,1,NORTH LEFT MOVE RIGHT MOVE RIGHT RIGHT RIGHT LEFT REPORT
>
2,2 South
![Page 7: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/7.jpg)
PLACE 1,1,NORTH LEFT MOVE RIGHT MOVE RIGHT RIGHT RIGHT LEFT REPORT
>
2,2 South
![Page 8: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/8.jpg)
PLACE 1,1,NORTH LEFT MOVE RIGHT MOVE RIGHT RIGHT RIGHT LEFT REPORT >
2,2 South
![Page 9: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/9.jpg)
2,2,SOUTH
cat instructions.txtPLACE 1,1,NORTH LEFT MOVE RIGHT MOVE RIGHT RIGHT RIGHT LEFT REPORT
$
cat instructions.txt | node robot.js
$
![Page 10: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/10.jpg)
「トイ・ロボット」に関して‣ 「トイ・ロボット・シミュレーター」というコード演習は面接試験としてオーストラリアのルビー言語コミュニティでよく使われています。
‣ プログラムは幾つかのコマンドを読み込みます。(例えばロボットを《テーブルに置く》や《向きを変える》、又は《前に進む》など)
‣ それに基づいてロボットを行動させ、最終的なロボットの位置を確認します。
‣ これは通常、単純なコンソールアプリケーションです。
![Page 11: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/11.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break;
![Page 12: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/12.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break;
![Page 13: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/13.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break;
![Page 14: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/14.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break;
![Page 15: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/15.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break;
![Page 16: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/16.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break;
![Page 17: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/17.jpg)
) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } const x = parseInt(matches[1],10); const y = parseInt(matches[2],10); dir && x >= 0 && x < width && y >= 0 && y < height && (robot = {x, y, dir}); } else if (line === "LEFT") { robot && (robot.dir =
![Page 18: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/18.jpg)
&& (robot = {x, y, dir}); } else if (line === "LEFT") { robot && (robot.dir = (robot.dir === 0 ? 3 : robot.dir - 1)); } else if (line === "RIGHT") { robot && (robot.dir = ( robot.dir + 1) % 4); } else if (line === "MOVE") { if (robot) { let newX = robot.x; let newY = robot.y; switch (robot.dir) { case 0: newY = robot.y + 1; break; case 1: newX = robot.x - 1; break;
![Page 19: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/19.jpg)
let newY = robot.y; switch (robot.dir) { case 0: newY = robot.y + 1; break; case 1: newX = robot.x - 1; break; case 2: newY = robot.y - 1; break; case 3: newX = robot.x + 1; break; } newX >= 0 && newX < width && newY >= 0 && newY < height && ( robot.x = newX, robot.y = newY ); } } else if (line === "REPORT") {
![Page 20: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/20.jpg)
); } } else if (line === "REPORT") { const dirStr = x => { switch(x) { case 0: return "NORTH"; case 1: return "EAST"; case 2: return "SOUTH"; case 3: return "WEST"; } } robot && console.log(robot.x, robot.y, dirStr(robot.dir)); } });
![Page 21: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/21.jpg)
case 3: return "WEST"; } } robot && console.log(robot.x, robot.y, dirStr(robot.dir)); } }); }
runRobot( 5, 5 "PLACE 1,1,EAST\nMOVE\nMOVE\nLEFT\nMOVE\nRIGHT\nRIGHT\nREPORT", ); // "0 2 SOUTH" (0,2 South)
![Page 22: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/22.jpg)
String
![Page 23: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/23.jpg)
String → [Things Happen]
![Page 24: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/24.jpg)
function runRobot(width, height, input) { // ... }
const w = 3, h = 3; // width and height it("tests runRobot is correct", function() {
});
![Page 25: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/25.jpg)
function runRobot(width, height, input) { // ... }
const w = 3, h = 3; it("tests runRobot is correct", function() { expect( runRobot(w, h, "PLACE 1,1,EAST\nREPORT") ).toBe(
); });
![Page 26: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/26.jpg)
function runRobot(width, height, input) { // ... }
const w = 3, h = 3; it("tests runRobot is correct", function() { expect( runRobot(w, h, "PLACE 1,1,EAST\nREPORT") ).toBe( // ...? ); });
何
![Page 27: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/27.jpg)
function runRobot(width, height, input) { // ... }
const w = 3, h = 3; it("tests runRobot is correct", function() { expect( runRobot(w, h, "PLACE 1,1,EAST\nREPORT") ).toBe( undefined // ); });
素晴らしい事だな
![Page 28: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/28.jpg)
function runRobot(width, height, input) { // ... }
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, "PLACE 1,1,EAST\nREPORT"); expect(console.log).toHaveBeenCalledWith( "1,1,EAST" ); });
![Page 29: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/29.jpg)
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, [ "PLACE 1,1,EAST", "REPORT", ].join("\n") ); expect(console.log).toHaveBeenCalledWith( "1,1,EAST" ); });
![Page 30: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/30.jpg)
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, [ "PLACE 1,1,EAST", "LEFT", "FORWARD", "REPORT", ].join("\n") ); expect(console.log).toHaveBeenCalledWith( "1,2,NORTH" ); });
![Page 31: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/31.jpg)
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, [ "PLACE 1,1,EAST", "FORWARD", "RIGHT", "REPORT", ].join("\n") ); expect(console.log).toHaveBeenCalledWith( "0,1,SOUTH" ); });
![Page 32: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/32.jpg)
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, [ "PLACE 1,1,EAST", "REPORT", ].join("\n") ); expect(console.log).toHaveBeenCalledWith( "0,1,SOUTH" ); });
"裏庭には二羽庭には二羽鶏がいる",
![Page 33: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/33.jpg)
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, [ "PLACE 1,1,EAST", "LEFT ", "REPORT", // "LEFT " ignored; has spaces ].join("\n") ); expect(console.log).toHaveBeenCalledWith( "1,1,EAST" ); });
![Page 34: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/34.jpg)
const w = 3, h = 3; it("tests runRobot is correct", function() { spyOn(console, "log"); runRobot(w, h, [ "PLACE 9,9,EAST", // Out of bounds, "REPORT", // so PLACE is ignored. ].join("\n") ); expect(console.log).toNotHaveBeenCalled();
});
![Page 35: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/35.jpg)
「トイ・ロボット」の例に関して‣ 「トイ・ロボット」の例があります。例は「runRobot」と呼ばれる関数あります。この関数はストリングを受け入れ、それを使って多くのアクションを実行します。
‣ この関数はあまりにも多くのことを行うので、テストするのは難しいです。 ストリングを解析し、ロボットの動きを計算し、ロボットの位置を報告するためのテストが必要です。
‣ 現在、すべてを一度にテストする必要があります。
![Page 36: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/36.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } const x = parseInt(matches[1],10); const y = parseInt(matches[2],10); dir && x >= 0 && x < width && y >= 0 && y < height && (robot = {x, y, dir}); } else if (line === "LEFT") { robot && (robot.dir = (robot.dir === 0 ? 3 : robot.dir - 1)); } else if (line === "RIGHT") {
![Page 37: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/37.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } // ... } else if (line === "LEFT") { // ... } else if (line === "RIGHT") { // ... } else if (line === "MOVE") { // ... } else if (line === "REPORT") { // ... } }); }
![Page 38: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/38.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } // ... } else if (line === "LEFT") { // ... } else if (line === "RIGHT") { // ... } else if (line === "MOVE") { // ... } else if (line === "REPORT") { // ... } }); }
![Page 39: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/39.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } // ... } else if (line === "LEFT") { // ... } else if (line === "RIGHT") { // ... } else if (line === "MOVE") { // ... } else if (line === "REPORT") { // ... } }); }
![Page 40: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/40.jpg)
String → [Things Happen]
手戻り
![Page 41: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/41.jpg)
String →
![Page 42: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/42.jpg)
String → Commands
![Page 43: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/43.jpg)
String → Commands
Commands →
![Page 44: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/44.jpg)
String → Commands
Commands → [Things Happen]
![Page 45: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/45.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } // ... } else if (line === "LEFT") { // ... } else if (line === "RIGHT") { // ... } else if (line === "MOVE") { // ... } else if (line === "REPORT") { // ... } }); }
![Page 46: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/46.jpg)
function runRobot(width, height, input) { let robot; input.split("\n").forEach((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH|SOUTH| EAST|WEST)/), matches ) { let dir; switch (matches[3]) { case "NORTH": dir = 0; break; case "EAST": dir = 1; break; case "SOUTH": dir = 2; break; case "WEST": dir = 3; break; } // ... } else if (line === "LEFT") { // ... } else if (line === "RIGHT") { // ... } else if (line === "MOVE") { // ... } else if (line === "REPORT") { // ... } }); }
手戻り
![Page 47: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/47.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
function runRobot(width, height, input) { let commands = stringToCommands(input); executeCommands(commands); }
function executeCommands(w, h, commands) { // ... }
![Page 48: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/48.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
function runRobot(width, height, input) { let commands = stringToCommands(input); executeCommands(commands); }
function executeCommands(w, h, commands) { // ... }
![Page 49: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/49.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
function runRobot(width, height, input) { let commands = stringToCommands(input); executeCommands(commands); }
function executeCommands(w, h, commands) { let robot; commands.forEach((command) => { switch (command.type) { case "PLACE": // ... case "LEFT": // ... case "RIGHT": // ... case "MOVE": // ... case "REPORT": // ... } }); }
![Page 50: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/50.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
function runRobot(width, height, input) { let commands = stringToCommands(input); executeCommands(commands); }
function executeCommands(w, h, commands) { let robot; commands.forEach((command) => { switch (command.type) { dir && cmd.x >= 0 && cmd.x < width && cmd.y >= 0 && cmd.y < height && (robot = { x: cmd.x, y: cmd.y, dir: cmd }); case "LEFT": // ... case "RIGHT": // ... case "MOVE": // ... case "REPORT": // ... } }); }
![Page 51: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/51.jpg)
function runRobot(width, height, input) { let commands = stringToCommands(input); executeCommands(commands); }
function executeCommands(w, h, commands) { let robot; commands.forEach((command) => { switch (command.type) { case "PLACE": dir && cmd.x >= 0 && cmd.x
<h
& & cmd.y
> = 0
& &
cmd.y <
h ei gḫ
t
&& (r ŏ
҉b
ǒt҉ =
{
x , y
, diř}
) ;
c as e " L
E F T "
:
/ /
. .
. .
҉
.
c
a
҉
s
e
" R
I
G
H
T
"
:
҉
҉
҉ /
/ . .
.
҉ c
ą
s
e
"
TONY V Ê " :
/ THE/
.
. ҉ .
c
a s e
"
THE P
Ǫ NY Ř
T
"
:
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
![Page 52: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/52.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
![Page 53: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/53.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
![Page 54: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/54.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
![Page 55: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/55.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
![Page 56: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/56.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
![Page 57: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/57.jpg)
function stringToCommands(i: string): Commands { return i.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
type Commands = Array<Command>
type Command = { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
type Direction = "NORTH" | "EAST" | "SOUTH" | "WEST"
![Page 58: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/58.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
![Page 59: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/59.jpg)
3つの関数に関して‣ 「runRobot」関数は、stringToCommands、
executeCommands、runRobotの3つの関数に分割できます。
‣ 最初はストリングを受け取り、いくつかのコマンドを返します( "Command")。 各コマンドはオブジェクトであり、アクションを表します。
‣ 2番目の関数はこれらのコマンドを受け取り、いくつかのアクションを実行します。
‣ 3番目の関数は2番目の関数を使用します。
![Page 60: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/60.jpg)
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
![Page 61: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/61.jpg)
it("tests stringToCommands", function() { expect( stringtoCommands([ "PLACE 1,1,EAST", "REPORT", ].join("\n") ).toEqual([ { type: "PLACE", x:1, y:1, dir: "EAST" }, { type: "REPORT" }, ])
});
![Page 62: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/62.jpg)
it("tests stringToCommands", function() { expect( stringtoCommands([ "PLACE 9,9,EAST", "REPORT", ].join("\n") ).toEqual([ { type: "PLACE", x:9, y:9, dir: "EAST" }, { type: "REPORT" }, ])
});
![Page 63: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/63.jpg)
it("tests stringToCommands", function() { expect( stringtoCommands([ "LEFT", "REPORT", ].join("\n") ).toEqual([ { type: "LEFT" }, { type: "REPORT" }, ])
});
![Page 64: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/64.jpg)
it("tests stringToCommands", function() { expect( stringtoCommands([ " ", "REPORT", ].join("\n") ).toEqual([ // ... ignoring that first "command" { type: "REPORT" }, ])
});
裏庭には二羽庭には二羽鶏がいる
![Page 65: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/65.jpg)
it("tests executeCommands", function() {
// ...
});
![Page 66: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/66.jpg)
分離に関して‣ stringToCommandsは小さく、定義された入力と出力を持っているので、テストする方が簡単です。
‣ executeCommandsは、チェックする戻り値がないため、まだテストするのが難しいです。 しかし、もはや文字列入力を解析しないので、入力の順列を少なくしてテストを実行できます。
![Page 67: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/67.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
console.log( "2,2,EAST" )
⚡1. Left2. Right3. ...
"..."
[ {type: "PLACE", x:1, y:2, dir:"EAST"}, {type: "LEFT"}, {type: "RIGHT"}, ...]
![Page 68: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/68.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
⚡1. Left2. Right3. ...
"..."console.log( "2,2,EAST" )
[ {type: "PLACE", x:1, y:2, dir:"EAST"}, {type: "LEFT"}, {type: "RIGHT"}, ...]
Instructions 命令
![Page 69: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/69.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
⚡1. Left2. Right3. ...
"..."
Instructions 命令
Interpreter 解釈
console.log( "2,2,EAST" )
[ {type: "PLACE", x:1, y:2, dir:"EAST"}, {type: "LEFT"}, {type: "RIGHT"}, ...]
![Page 70: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/70.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
⚡1. Left2. Right3. ...
"..."console.log( "2,2,EAST" )
[ {type: "PLACE", x:1, y:2, dir:"EAST"}, {type: "LEFT"}, {type: "RIGHT"}, ...]
stringToCommands
![Page 71: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/71.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
⚡1. Left2. Right3. ...
"..."console.log( "2,2,EAST" )
[ {type: "PLACE", x:1, y:2, dir:"EAST"}, {type: "LEFT"}, {type: "RIGHT"}, ...]
stringToCommands executeCommands
![Page 72: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/72.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
⚡1. Left2. Right3. ...
"..."console.log( "2,2,EAST" )
[ {type: "PLACE", x:1, y:2, dir:"EAST"}, {type: "LEFT"}, {type: "RIGHT"}, ...]
![Page 73: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/73.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
robot() .move(instructions) .withConnection(serial) .asFutureChain() .toPromise()
⚡
+ console.log(…) console.log(…)console.log(…)
it('moves around',()=>{ let r = robot(); let instructions = [ ... ];});
const instructions = [ place(1,2,east), left, right, ...];
[...]
[{"t":"PLACE", "x":1,"y":2, "f":"EAST"}, {"t":"LEFT"}, {"t":"RIGHT"}, ...]
"{…}"
1. Left2. Right3. ...
"..."
![Page 74: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/74.jpg)
分離に関して‣ 命令と解釈を分けているので、もっと多くのことができます。
‣ 複数の方法で指示を出すことができます。 ‣ これらの命令については、複数の解釈が可能です。
![Page 75: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/75.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
function stringToCommands(input) { return input.split("\n").map((line) => { let matches; if ( matches = line.match( /PLACE ([\d]+),([\d]+),(NORTH| SOUTH|EAST|WEST)/), matches ) { switch (matches[3]) { /* ... */ } const x = parseInt(matches[1], 10); // ... return { type: "PLACE", x, y, dir }
} else if (line === "LEFT") { return { type: "LEFT" } } else if (line === "RIGHT") { return { type: "RIGHT" } } else if (line === "MOVE") { return { type: "MOVE" } } else if (line === "REPORT") { return { type: "REPORT" } } }).filter(x => x === undefined); }
![Page 76: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/76.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
function return input.split( matches = line.match( SOUTH|EAST|WEST)/ ) const // ... return { type: "PLACE", x, y, dir }
return { type: "LEFT" } return { type: "RIGHT" } return { type: "MOVE return { type: "REPORT" } } }
Remember these?
![Page 77: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/77.jpg)
We've made alittle language.
(限られた言語)
![Page 78: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/78.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
![Page 79: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/79.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
Words単語
![Page 80: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/80.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, // 1,2,3,… y: number, // 1,2,3,… dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
Words単語
![Page 81: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/81.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
Sentences文
![Page 82: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/82.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
Sentences文
![Page 83: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/83.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
Sentences文
![Page 84: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/84.jpg)
Commands are a list of... Command objects
Command is one of... { type: "PLACE", x: number, y: number, dir: Direction } | { type: "LEFT" } | { type: "RIGHT" } | { type: "MOVE" } | { type: "REPORT" }
Direction is one of... "NORTH" | "EAST" | "SOUTH" | "WEST"
Document書面
![Page 85: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/85.jpg)
例えば
![Page 86: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/86.jpg)
Place the robot at 1 across (from the right),1 upwards (from the bottom), and have it face North. Turn left. Go forward one space. Turn right. Go forward one space. Turn right. Turn right. Report the robot's position.
![Page 87: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/87.jpg)
[ { type: "PLACE", x: 1, y: 1, dir: "NORTH" },
{ type: "LEFT" }, { type: "FORWARD" }, { type: "RIGHT" }, { type: "FORWARD" }, { type: "RIGHT" }, { type: "RIGHT" }, { type: "REPORT" }, ]
![Page 88: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/88.jpg)
DSL(Domain-Specific Language)
ドメイン固有言語
![Page 89: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/89.jpg)
DSL(Domain-Specific Language)
言語内ドメイン固有言語
INTERNAL
![Page 90: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/90.jpg)
限られた言語に関して‣ 指示は限られた言語で表現することができます。
![Page 91: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/91.jpg)
This idea also shows up in...
![Page 92: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/92.jpg)
Validation
![Page 93: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/93.jpg)
Validate.js
![Page 94: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/94.jpg)
const constraints = { username: { presence: true, exclusion: { within: ["bert"], message: "'%{value}' is not allowed", } }, password: { presence: true, length: { minimum: 6, message: "must be at least 6 characters", } }, };
![Page 95: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/95.jpg)
const constraints = { username: { ... }, password: { ... }, };
![Page 96: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/96.jpg)
const constraints = { username: { ... }, password: { ... }, };
validate( { username: "rob", password: "acceptable" }, constraints ); // undefined (no errors)
validate( { username: "rob", password: "short" }, constraints ); // {"password": ["Password must be at least 6 characters"]}
![Page 97: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/97.jpg)
validate()⚡
+ console.log(…) console.log(…)console.log(…)
const constraints = { username: { ... } password: ... ...];
[...]
1. User 2. Pass 3. ...
User Input 入力
+
![Page 98: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/98.jpg)
io-ts
![Page 99: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/99.jpg)
const Person = t.interface({ name: t.string, age: t.number })
t.validate( JSON.parse('{"name":"Giulio Canti","age":43}'), Person ); // => Right({name: "Giulio Canti", age: 43})
![Page 100: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/100.jpg)
検証に関して‣ フォーム検証ライブラリでは、このパターンもよく使用されます。
‣ 検証ルールは指示です。
![Page 101: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/101.jpg)
Redux-Saga
![Page 102: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/102.jpg)
function* fetchUserFromServer(action) { const user = yield call( Api.fetchUser, action.payload.userId ); yield put({ type: "USER_FETCH_SUCCEEDED", user: user }); }
![Page 103: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/103.jpg)
function* fetchUserFromServer(action) { const user = yield call( Api.fetchUser, action.payload.userId ); yield put({ type: "USER_FETCH_SUCCEEDED", user: user }); }
![Page 104: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/104.jpg)
function* fetchUserFromServer(action) { const user = yield {..., CALL:{..., action:{ fn: Api.fetchUser, args: [ action.payload.userId ], }}}; yield put({ type: "USER_FETCH_SUCCEEDED", user: user }); }
![Page 105: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/105.jpg)
function* fetchUserFromServer(action) { const user = yield {..., CALL:{..., action:{ fn: Api.fetchUser, args: [ action.payload.userId ], }}}; yield put({ type: "USER_FETCH_SUCCEEDED", user: user }); }
![Page 106: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/106.jpg)
function* fetchUserFromServer(action) { const user = yield {..., CALL:{..., action:{ fn: Api.fetchUser, args: [ action.payload.userId ], }}}; yield put({ type: "USER_FETCH_SUCCEEDED", user: user }); }
![Page 107: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/107.jpg)
function* fetchUserFromServer(action) { const user = yield {..., CALL:{..., action:{ fn: Api.fetchUser, args: [ action.payload.userId ] }}}; yield {..., PUT: {..., action:{ type: "USER_FETCH_SUCCEEDED", user: user }}}; }
![Page 108: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/108.jpg)
function* fetchUserFromServer(action) { const user = yield {..., CALL:{..., action:{ fn: Api.fetchUser, args: [ action.payload.userId ] }}}; yield {..., PUT: {..., action:{ type: "USER_FETCH_SUCCEEDED", user: user }}}; }
![Page 109: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/109.jpg)
Where's the Interpreter?
![Page 110: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/110.jpg)
Redux Middleware⚡it('sagas',()=>{ let saga = ...();});
Saga Definition
{...}
1. CALL 2. PUT3. ...
![Page 111: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/111.jpg)
Tests
![Page 112: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/112.jpg)
const action = { payload: { userId: 123 }} }; const gen = fetchUserFromServer(action);
assert.deepEqual( gen.next().value, call(Api.FetchUser, action.payload.userId) );
assert.deepEqual( gen.next().value, put({ type: "USER_FETCH_SUCCEEDED", user: makeFakeUser(action.payload.userId), }) );
![Page 113: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/113.jpg)
Redux-Saga's Redux Middleware
![Page 114: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/114.jpg)
// ...
// declarative effects : is.array(effect) ? runParallelEffect(effect, effectId, currCb) : (data = isEffect.take(effect)) ? runTakeEffect(data, currCb) : (data = isEffect.put(effect)) ? runPutEffect(data, currCb) : (data = isEffect.all(effect)) ? runAllEffect(data, effectId, currCb) : (data = isEffect.race(effect)) ? runRaceEffect(data, effectId, currCb) : (data = isEffect.call(effect)) ? runCallEffect(data, effectId, currCb) : (data = isEffect.cps(effect)) ? runCPSEffect(data, currCb) : (data = isEffect.fork(effect)) ? runForkEffect(data, effectId, currCb) : (data = isEffect.join(effect)) ? runJoinEffect(data, currCb) : (data = isEffect.cancel(effect)) ? runCancelEffect(data, currCb) : (data = isEffect.select(effect)) ? runSelectEffect(data, currCb)
// ... // See:// https://github.com/redux-saga/redux-saga/blob/master/src/internal/proc.js
![Page 115: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/115.jpg)
switch(effect.type) { case "take": return runTakeEffect(...); case "put": return runPutEffect(...); case "all": return runAllEffect(...); case "race": return runRaceEffect(...); case "call": return runCallEffect(...); case "cps": return runCPSEffect(...); case "fork": return runForkEffect(...); case "join": return runJoinEffect(...); case "cancel": return runCancelEffect(...); case "select": return runSelectEffect(...); }
![Page 116: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/116.jpg)
switch(effect.type) { case "take": return runTakeEffect(...); case "put": return runPutEffect(...); case "all": return runAllEffect(...); case "race": return runRaceEffect(...); case "call": return runCallEffect(...); case "cps": return runCPSEffect(...); case "fork": return runForkEffect(...); case "join": return runJoinEffect(...); case "cancel": return runCancelEffect(...); case "select": return runSelectEffect(...); }
![Page 117: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/117.jpg)
switch(effect.type) { case "take": return runTakeEffect(...); case "put": return runPutEffect(...); case "all": return runAllEffect(...); case "race": return runRaceEffect(...); case "call": return runCallEffect(...); case "cps": return runCPSEffect(...); case "fork": return runForkEffect(...); case "join": return runJoinEffect(...); case "cancel": return runCancelEffect(...); case "select": return runSelectEffect(...); }
![Page 118: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/118.jpg)
Redux-Sagaに関して‣ 「Saga」関数は命令です。 ‣ インタプリタはアプリケーションのテストであり、
Redux-Sagaミドルウェアです。
![Page 119: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/119.jpg)
What's so "Functional" about all this?
![Page 120: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/120.jpg)
That "Pure Functions"
Thing.
![Page 121: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/121.jpg)
function addOne(x) { return x + 1; }
var r = addOne(5); // r is 6
出力が入力によって完全に決定される場合、 関数は「pure」です。
![Page 122: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/122.jpg)
function addOne(x) { return x + 1; }
var r = addOne(1) + addOne(3); // r is 6
出力が入力によって完全に決定される場合、 関数は「pure」です。
![Page 123: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/123.jpg)
function addOne(x) { console.log("Hi!"); return x + 1; } var r = addOne(5); // Logged: "Hi!" // r is 6実行を観察できる場合、関数は「impure」です。
![Page 124: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/124.jpg)
function addOne(x) { console.log("Hi!"); return x + 1; } var r = addOne(1) + addOne(3); // Logged: "Hi!Hi!" // r is 6実行を観察できる場合、関数は「impure」です。
![Page 125: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/125.jpg)
function addOne(x) { console.log("Hi!"); return x + 1; } var r = addOne(1) + addOne(3); // Logged: "Hi!Hi!" // r is 6実行を観察できる場合、関数は「impure」です。
![Page 126: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/126.jpg)
Pure things:
![Page 127: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/127.jpg)
stringToCommands()
![Page 128: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/128.jpg)
t.interface()
![Page 129: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/129.jpg)
fetchUserFromServer()
![Page 130: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/130.jpg)
Representing impure actions as instructions to be later interpreted
can make them pure.impureなアクションを、
後に解釈される指示として表現することで、それらをpureにすることができます。
![Page 131: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/131.jpg)
Representing impure actions as instructions to be later interpreted
can make them pure.impureなアクションを、
後に解釈される指示として表現することで、それらをpureにすることができます。
![Page 132: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/132.jpg)
A Quick Confession
![Page 133: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/133.jpg)
It's also known as the "Interpeter Pattern"
(from "Design Patterns")これはGoFの
「Interpreter パターン」とも呼ばれます。
![Page 134: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/134.jpg)
It just shows up in the "FP" community a lot.このような考え方は、Functional Programming
のコミュニティで人気があります。
![Page 135: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/135.jpg)
It just shows up in the "FP" community a lot.このような考え方は、Functional Programming
のコミュニティで人気があります。 (たとえば、Free Monadsや HaskellのIO型)
(Free Monads in Haskell and Scala, and Haskell's entire way of doing side-effects
with its IO Type.)
![Page 136: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/136.jpg)
Back to the Robot
![Page 137: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/137.jpg)
MARVIN
Raspberry Pi + Motor Hat
![Page 138: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/138.jpg)
![Page 139: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/139.jpg)
const j5 = require("johnny-five"); const rp = require("raspi-io"); const hat = j5.Motor.SHIELD_CONFIGS.ADAFRUIT_V2; const board = new j5.Board({io: rp()});
![Page 140: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/140.jpg)
const j5 = require("johnny-five"); const rp = require("raspi-io"); const hat = j5.Motor.SHIELD_CONFIGS.ADAFRUIT_V2; const board = new j5.Board({io: rp()});
board.on("ready", function() { const motors = { left: new j5.Motor(hat.M1), right: new h5.Motor(hat.M2), };
// ... });
![Page 141: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/141.jpg)
const j5 = require("johnny-five"); const rp = require("raspi-io"); const hat = j5.Motor.SHIELD_CONFIGS.ADAFRUIT_V2; const board = new j5.Board({io: rp()});
board.on("ready", function() { const motors = { left: ..., right: ... };
// ... });
![Page 142: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/142.jpg)
const j5 = require("johnny-five"); const rp = require("raspi-io"); const hat = j5.Motor.SHIELD_CONFIGS.ADAFRUIT_V2; const board = new j5.Board({io: rp()}); const Marvin = require("./marvin"); board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors);
// ... });
![Page 143: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/143.jpg)
const j5 = require("johnny-five"); const rp = require("raspi-io"); const hat = j5.Motor.SHIELD_CONFIGS.ADAFRUIT_V2; const board = new j5.Board({io: rp()}); const Marvin = require("./marvin"); board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors);
// ... });
![Page 144: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/144.jpg)
const logic = require("./logic");
function Marvin(motors) { ... }
const motorSpeed = 100; // 0 - 250 const turnTime = 700; // milliseconds const forwardTime = 700; // milliseconds
Marvin.prototype.initialState = logic.initialState;
Marvin.prototype.turnLeft = function(state) { if (!logic.isPlaced(state)) return; // not placed yet? ignore
const newState = logic.turnLeft(state)
motors.left.reverse(motorSpeed); motors.right.forward(motorSpeed); return sleep(turnTime, (res) => { motors.left.stop() motors.right.stop() res(newState); }); });
![Page 145: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/145.jpg)
const logic = require("./logic");
function Marvin(motors) { ... }
const motorSpeed = 100; // 0 - 250 const turnTime = 700; // milliseconds const forwardTime = 700; // milliseconds
Marvin.prototype.initialState = logic.initialState;
Marvin.prototype.turnLeft = function(state) { if (!logic.isPlaced(state)) return; // not placed yet? ignore
const newState = logic.turnLeft(state)
motors.left.reverse(motorSpeed); motors.right.forward(motorSpeed); return sleep(turnTime, (res) => { motors.left.stop() motors.right.stop() res(newState); }); });
![Page 146: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/146.jpg)
const logic = require("./logic");
function Marvin(motors) { ... }
const motorSpeed = 100; // 0 - 250 const turnTime = 700; // milliseconds const forwardTime = 700; // milliseconds
Marvin.prototype.initialState = logic.initialState;
Marvin.prototype.turnLeft = function(state) { if (!logic.isPlaced(state)) return; // not placed yet? ignore
const newState = logic.turnLeft(state)
motors.left.reverse(motorSpeed); motors.right.forward(motorSpeed); return sleep(turnTime, (res) => { motors.left.stop() motors.right.stop() res(newState); }); });
![Page 147: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/147.jpg)
const j5 = require("johnny-five"); const rp = require("raspi-io"); const hat = j5.Motor.SHIELD_CONFIGS.ADAFRUIT_V2; const board = new j5.Board({io: rp()}); const Marvin = require("./marvin"); board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors);
// ... });
![Page 148: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/148.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors);
// ... });
![Page 149: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/149.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = [ "PLACE 1,1,NORTH", "LEFT", "FORWARD", "RIGHT", // ... ];
// ... });
![Page 150: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/150.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...];
// ... });
![Page 151: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/151.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...]; const commands = stringToCommands(input);
// ... });
![Page 152: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/152.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...]; const commands = stringToCommands(input); commands.reduce((p, command) => {
}, Promise.resolve(r.initialState)); });
![Page 153: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/153.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...]; const commands = stringToCommands(input); commands.reduce((p, command) => { switch(command.type) { case "PLACE": return p.then(state => { log(`Place on ${x},${y} facing ${dir}`); return state; }); } }, Promise.resolve(r.initialState)); });
![Page 154: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/154.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...]; const commands = stringToCommands(input); commands.reduce((p, command) => { switch(command.type) { case "PLACE": return p.then(passThrough(() => log(`Place on ${x},${y} facing ${dir}`); ));
} }, Promise.resolve(r.initialState)); });
![Page 155: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/155.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...]; const commands = stringToCommands(input); commands.reduce((p, command) => { switch(command.type) { case "PLACE": return p.then(passThrough(() => ...));
// ... } }, Promise.resolve(r.initialState)); });
![Page 156: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/156.jpg)
board.on("ready", function() { const motors = { left: ..., right: ... }; const r = new Marvin(motors); const input = ["PLACE 1,1,NORTH","LEFT",...]; const commands = stringToCommands(input); commands.reduce((p, command) => { switch(command.type) { case "PLACE": return p.then(passThrough(() => ...)); case "LEFT": return p.then(r.turnLeft); // ... } }, Promise.resolve(r.initialState)); });
![Page 157: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/157.jpg)
commands.reduce((p, command) => { switch(command.type) { case "PLACE": return p.then(passThrough(() => log(`Place on ${x},${y} facing ${dir}`) )); case "LEFT": return p.then(r.turnLeft);
// ... }, Promise.resolve(r.initialState)); });
![Page 158: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/158.jpg)
commands.reduce((p, command) => { switch(command.type) { case "PLACE": return p.then(passThrough(() => log(`Place on ${x},${y} facing ${dir}`) )); case "LEFT": return p.then(r.turnLeft); case "RIGHT": return p.then(r.turnRight); case "FORWARD": return p.then(r.moveForward); case "REPORT": return p.then(passThrough((state) => log(`${state.x},${state.y},${dirStr(state.dir)}`) )); }, Promise.resolve(r.initialState)); });
![Page 159: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/159.jpg)
PLACE 2,1,NORTH LEFT MOVE RIGHT MOVE RIGHT RIGHT RIGHT LEFT MOVE LEFT MOVE
> .then(r.place(1,1,north)) .then(r.turnLeft) .then(r.moveForward) .then(r.turnRight) .then(r.moveForward) .then(r.turnRight) .then(r.moveForward) .then(r.turnRight) .then(r.moveForward) .then(r.turnRight) .then(r.turnRight)
![Page 160: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/160.jpg)
![Page 161: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/161.jpg)
"PLACE 1,2,EAST LEFT RIGHT ..."
robot() .move(instructions) .withConnection(serial) .asFutureChain() .toPromise()
⚡
+ console.log(…) console.log(…)console.log(…)
it('moves around',()=>{ let r = robot(); let instructions = [ ... ];});
const instructions = [ place(1,2,east), left, right, ...];
[...]
[{"t":"PLACE", "x":1,"y":2, "f":"EAST"}, {"t":"LEFT"}, {"t":"RIGHT"}, ...]
"{…}"
1. Left2. Right3. ...
"..."
![Page 162: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/162.jpg)
“ ”"Functional Core,
Imperative [Effectful] Shell"
— Gary Bernhardt, "Boundaries"https://www.youtube.com/watch?v=yTkzNHF6rMs
![Page 163: A Toy Robot...A Toy Robot and a Functional Pattern 関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。 A Functional](https://reader034.fdocument.pub/reader034/viewer/2022050308/5f7068142a07f030c75ff615/html5/thumbnails/163.jpg)
A Toy Robot and a Functional Pattern関数型プログラミングにインスピレーションを 得た模様は、命令と解釈を分離します。
A Functional Programming-inspired pattern to separate instructions and interpretations.
Rob Howard@damncabbagehttp://robhoward.id.au