Slide 1

Slide 1 text

スコープファンクションでコード の見通しを改善する 2018/09/26 Gotanda.unity #8 @yashims85

Slide 2

Slide 2 text

誰 ● Twitter: @yashims85 ● 会社: モバイルファクトリー@ 五反田 ● Unity: 趣味でさわってる ● 最近気になる言語: Rust ● 緩募: 継続するダイエット

Slide 3

Slide 3 text

質問です 皆さんはイケてないな。。。 と思いながら、そんなもんだろうと諦めて コードを書いていることはありませんか?

Slide 4

Slide 4 text

● PBXProjectのプロパティ ● 関数に外出しするほどではないちょっとし た計算 ● Builder, Factoryパターンを採用するほど でもないちょっとした手順 ● 大量のnullチェックもしくは ?. 地獄 私がイケてなぁと思いながらコードを書 いているとき

Slide 5

Slide 5 text

スコープファンクション もしかしたらスコープ ファンクションがそれ らの悩みを一助にな るかもしれません。

Slide 6

Slide 6 text

スコープファンクション ● Kotlinの文脈で登場する ● (基本的に)引数にLambdaを1つとって、そ の中で自己参照をする ● C#のExtensionで作った関数のように全部 のObjectに生えてる

Slide 7

Slide 7 text

なるほど

Slide 8

Slide 8 text

いくつか移植してみた CSharpScopeExtensions: https://github.com/yashims/CSharpScop eExtensions ここでスター欲しいって言えば 優しい人がしてくれるって聞きました

Slide 9

Slide 9 text

導入方法 ● releaseにunitypackageがおいてあるので ご自由にお使い下さい ● もしくは簡単なのでコピペ

Slide 10

Slide 10 text

実際の実装 今回は諸般の事情により2つだけ紹介

Slide 11

Slide 11 text

Also

Slide 12

Slide 12 text

Also public static T Also(this T self, Action action) { action(self); return self; }

Slide 13

Slide 13 text

Also public static T Also(this T self, Action action) { action(self); return self; } ジェネリクスのExtensionなので、どの Objectからも呼び出せる

Slide 14

Slide 14 text

Also public static T Also(this T self, Action action) { action(self); return self; } 自分自身を引数に取る Actionに自分 自身を渡す

Slide 15

Slide 15 text

Also public static T Also(this T self, Action action) { action(self); return self; } 戻り値として自分を返す。

Slide 16

Slide 16 text

Let

Slide 17

Slide 17 text

Let public static R Let(this T self, Func action) { return action(self); }

Slide 18

Slide 18 text

Let public static R Let(this T self, Func action) { return action(self); } ジェネリクスのExtensionなので、どの Objectからも呼び出せる

Slide 19

Slide 19 text

Let public static R Let(this T self, Func action) { return action(self); } 自分自身をFuncに渡し、Funcの戻り 値がLetの戻り値となる。

Slide 20

Slide 20 text

それがどしたの

Slide 21

Slide 21 text

実際の使用感をみてみる

Slide 22

Slide 22 text

Alsoの使い所 例えばインスタンスのプロパティ設 定

Slide 23

Slide 23 text

Alsoを使わない void Start() { Transform t1 = GetComponent(); Quaternion q1 = new Quaternion(); q1.x = 0; q1.y = 0; q1.x = 0; t1.rotation = q1; }

Slide 24

Slide 24 text

Alsoを使う void Start() { Transform t2 = GetComponent().Also((it) => { it.rotation = new Quaternion().Also((that) => { that.x = 0; that.y = 0; that.z = 0; }); }); }

Slide 25

Slide 25 text

Alsoを使う ● Start()のスコープを一時変数で汚さない ● いくつかの処理が記述されてるようならコレはメリット ● 引数の変数名を`it`等の代名詞にしておけば、何に対して の処理かが明確になり、それ以外に言及するコードを避 けられる ● コレを使えばPBXProjectの設定が超絶スッキリする

Slide 26

Slide 26 text

Letの使い所 例えばLINQのSelectの様に使う

Slide 27

Slide 27 text

Letを使わない Transform t = GetComponent(); float distanceX = t.parent.transform.localPosition.x + t.localPosition.x;

Slide 28

Slide 28 text

Letを使う float distanceX = GetComponent().Let((it) => { return it.parent.transform.localPosition.x + it.localPosition.x; });

Slide 29

Slide 29 text

Letを使う ● LINQやRxのSelectと同じイメージで、Lambda内で変形を 行える ● Alsoと同じく、一時変数でスコープを汚さない

Slide 30

Slide 30 text

Letの使い所 例えばC#6.xのnullableの unwrapping

Slide 31

Slide 31 text

Letを使わない string say(string comment) { return comment != null ? $"I said: {comment}" : ""; }

Slide 32

Slide 32 text

Letを使う string say(string comment) { return comment?.Let(it => $"I said: {it}") ?? ""; }

Slide 33

Slide 33 text

Letを使う ● C#でのnull条件演算子「?.」は、nullチェックして、非null であればローカル変数に格納するのと同義 ● それをLetの引数で受け取っているので、Letの中では Null安全な変数を自由に使える

Slide 34

Slide 34 text

できなかったこと

Slide 35

Slide 35 text

できなかったこと ● Lambdaの中でthisコンテキストを変える ● KotlinではLambdaの中ではthisがそれ自身になるス コープファンクションがある(例: Apply)

Slide 36

Slide 36 text

Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; }

Slide 37

Slide 37 text

Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; } ジェネリクスのExtensionなので、どの Objectからも呼び出せる

Slide 38

Slide 38 text

Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; } TをthisとしてActionを呼び出す

Slide 39

Slide 39 text

Apply(実現できたら) public static T Apply(this T self, Action action) { self.action(); return self; } 自分自身を返す

Slide 40

Slide 40 text

Applyを使えたら void Start() { Transform t2 = GetComponent().Apply(() => { this.rotation = new Quaternion().Apply(() => { x = 0; y = 0; z = 0; }); }); } this以外の事について言及する余地 が無くなる

Slide 41

Slide 41 text

まとめ

Slide 42

Slide 42 text

まとめ ● ScopeFunctionを使うと一時変数が減ら せ、コードの見通しが良くなる ● ブロックで区切られることで、何について述 べられているコードかが簡潔になる ● Lambdaの中でthisを変える方法があった ら誰か教えてください

Slide 43

Slide 43 text

ありがとうございました