35
More C# λ

CLR/H No.35-2

Embed Size (px)

DESCRIPTION

Session2の内容

Citation preview

Page 1: CLR/H No.35-2

More C#

λ

Page 2: CLR/H No.35-2

自己紹介自己紹介

• 名称 := K 泉将久 | のぶ | Nobuhisa |• 特技 ⇒

Page 3: CLR/H No.35-2

C#におけるλ式

Func<int, int> f = (x => x * x);

Page 4: CLR/H No.35-2

C#3.0 – lambda expressionC#3.0 – lambda expression

• 書き方色々 Func<T1, .., T4, TResult>

Func<string> f1 = () => “hello, world”;

Func<int, int> f2 = (int x) => x + 1;Func<int, string> f3 = x => (x<=5 ? “foo” : “bar”);

Func<int, int, int> f4 = (x, y) => x * y;

Func<string, int> f5 = x => {int length = x.Length;return length;

};

System.Action nop = () => {};

Page 5: CLR/H No.35-2

意外と嬉しいコレクション初期化子

var lst = new List{ 1, 2, 4, 8 };

Page 6: CLR/H No.35-2

C#3.0 – Collection InitializersC#3.0 – Collection Initializers

• Before…

List<Employee> lst = new List<Employee>();

Employee john = new Employee();john.Name = "john";john.Age = 58;Employee michael = new Employee();michael.Name = "taro";michael.Age = 62;

lst.Add( john );lst.Add( michael );

Page 7: CLR/H No.35-2

C#3.0 – Collection InitializersC#3.0 – Collection Initializers

•After !var + オブジェクト初期化子 + コレクション初期化子

v a r l s t = n e w Li s t <Emp l o y e e >( ) {n e w Emp l o y e e { Na me = " j o h n " , Ag e = 2 2 } ,n e w Emp l o y e e { Na me = " t a r o " , Ag e = 2 4 } ,

} ;

Page 8: CLR/H No.35-2

C#3.0 – Collection InitializersC#3.0 – Collection Initializers

• クラス変数の dic を初期化

public class Foo{

Dictionary<string,int> dic = new Dictionary<string,int>{{ "one", 1 }, { "two", 2 }, { "three", 3 }

};

/*public Foo() {this.dic.Add( "one", 1 );this.dic.Add( "two", 2 );this.dic.Add( "three", 3 );

}*/}

Page 9: CLR/H No.35-2

型パラメータによって振る舞いを変える

Foo<ClassA>.Method( x );Foo<ClassB>.Method( x );

Page 10: CLR/H No.35-2

GenericsGenerics

渡された型 T は実行時に if 文等で判別できない

( 引数なしの場合 )

.4 静的フィールドと静的コンストラクタを活用する

⇒ Demo

.5 C#3.0 の拡張メソッドを使う

⇒ 容易だがこの場合やや柔軟性に欠ける

Page 11: CLR/H No.35-2

11 . . 静的フィールドの利用静的フィールドの利用

• ジェネリッククラスに属する静的な変数は、型パラメータが違うとどんな扱いになる?

class Foo<T> { public static int Value; }~

Foo<int>.Value = 99;Foo<string>.Value++;

Console.WriteLine( Foo<int>.Value );Console.WriteLine( Foo<string>.Value );

991

Page 12: CLR/H No.35-2

Demonstration

型パラメータによって振る舞いを変える

- 静的フィールド利用編 -

Page 13: CLR/H No.35-2

型パラメータの判別型パラメータの判別

渡された型 T は実行時に if 文等で判別できない

( 引数なしの場合 )

.4 静的フィールドと静的コンストラクタを活用する

⇒ Demo

.5 C#3.0 の拡張メソッドを使う

⇒ 容易だがこの場合やや柔軟性に欠ける

Page 14: CLR/H No.35-2

22 . . 拡張メソッドを使った場合拡張メソッドを使った場合

• 拡張メソッドの使い方– 静的クラス、静的メソッド

– 第一引数の this キーワード

public static class SampleExtensions{

public static int Add( this int a, int b ){

return a + b;}

}~

int a = 60;int result = a.Add( 40 ); // 100

Page 15: CLR/H No.35-2

22 . . 拡張メソッドを使った場合拡張メソッドを使った場合

public class Foo<T> { }

public static class FooExtensions{

public static void Method( this Foo<string> f, int x ){

Console.WriteLine( x + " かもしれない " );}public static void Method( this Foo<int> f, int x ){

Console.WriteLine( x + " じゃないと思う " );}public static void Method<T>( this Foo<T> f, int x ){

Console.WriteLine( x );}

}つづく

Page 16: CLR/H No.35-2

22 . . 拡張メソッドを使った場合拡張メソッドを使った場合

public void Test(){

new Foo<string>().Method( 10 );new Foo<int>().Method( 100 );new Foo<Foo<string>>().Method( 1000 );

}

10 かもしれない

100 だと思う1000

Page 17: CLR/H No.35-2

22 . . 拡張メソッドを使った場合拡張メソッドを使った場合

• 好きそうな人向けのおまけ ~ カリー化

– 拡張メソッドの第一引数部分に f を束縛した状態

• 本格的なカリー化はクロージャで

var f = new Foo<string>();Action<int> curry = f.Method;

curry( 10 ); // 10 かもしれない

Page 18: CLR/H No.35-2

C#におけるクロージャのからくり

x => y => x * y;

Page 19: CLR/H No.35-2

函数はファーストクラスオブジェ

クト

f = Console.WriteLine;

Page 20: CLR/H No.35-2

ファーストクラスオブジェクト?ファーストクラスオブジェクト?

• (ほぼ)第一級オブジェクトです– だから何?(←みんなの心の声)

– 次ページから具体例をお見せします

• 高階関数が直感的に書ける– これを使う利点が分かりません(←みんなの心の声)

– 後ほど扱います

Page 21: CLR/H No.35-2

実用例~関数の足し算実用例~関数の足し算

public Func<string> GetFunc() {string data = "hello";Func<string> fns = null;

fns += (() => data += " world");fns += (() => data = data.ToUpper());fns += (() => data = "<b>"+data+"</b>");return fns;

}~

var f = this.GetFunc();Console.WriteLine( f() ); // <b>HELLO WORLD</b>

“ ”責任 を動的に組み替えられる⇒ ミニマムな Decoratorパターン

Page 22: CLR/H No.35-2

実用例2~実用例2~ switchswitch の除去の除去

public abstract class Food { }public class ちくわ : Food { }public class ネオちくわ : ちくわ { }public class いも : Food { }public class じゃがいも : いも { }public class みそしる : Food { }~public Food Create( string name ) {

switch ( name ) {case "taro": return new ネオちくわ ();case "hanako": return new いも ();case "mae": return new みそしる ();default: throw new ArgumentException();

}}

Before…

Page 23: CLR/H No.35-2

実用例2~実用例2~ switchswitch の除去の除去

private Dictionary<string, Func<Food>> table =new Dictionary<string, Func<Food>>()

{{ "taro", () => new ネオちくわ () },{ "hanako", () => new いも () },{ "mae", () => new みそしる () }

};

public Food Create( string name ){

if ( this.table.ContainsKey( name ) )return this.table[ name ]();

throw new ArgumentException();}

After !

Page 24: CLR/H No.35-2

高階関数をもう少し

(sort '((one . 1) (two . 2) (three . 3)) #'> :key #'cdr)

Page 25: CLR/H No.35-2

高階関数高階関数

• 「関数を受け取る」高階関数– 関数の抽象化が可能となり、汎用性が増す

– 従来の抽象化の概念がクラスレベルから関数レベルへ

• 「関数を返す」高階関数– 関数を動的に生成したり、改造したりできる

– 知らなくても良い情報を隠蔽する価値もある

– 前者より脚光を浴びてない(?)ので、今日はこっちを主役にします

Page 26: CLR/H No.35-2

高階関数~メモ化高階関数~メモ化

• 本日ご紹介するのはコレ! ⇒ 渡された関数にキャッシュ機能を追加して返す

– 処理が重い && 複数回実行される関数などを渡す

– 2 回目以降は高速化が期待できる

– 外部の可変変数に依存していない関数を渡す

• 引数と計算結果のペアを、コレクションに保存しておき、クロージャにして返す

• このような機能をメモ化 (memoization,memoize) という

Page 27: CLR/H No.35-2

高階関数~メモ化高階関数~メモ化

• Demoプログラムの主要部分抜粋

publicFunc<T, TResult> Memoize<T, TResult>( Func<T, TResult> fn ){

var dic = new Dictionary<T, TResult>();

return x => {if ( ! dic.ContainsKey( x ) )

dic.Add( x, fn( x ) );return dic[ x ];

};}

関数 + 環境 ⇒ クロージャ ( Closure)

Page 28: CLR/H No.35-2

Demonstration

メタボ関数を軽くする

- メモ化 -

Page 29: CLR/H No.35-2

ちょっとマイナーな標準クエリ演算子

SelectMany.ToLookup.

OfType.

Page 30: CLR/H No.35-2

Demonstration

いくつかクエリを

- LINQ -

Page 31: CLR/H No.35-2

質問タイム

\ (^ o^ )/

Page 32: CLR/H No.35-2

まとめ

Page 33: CLR/H No.35-2

まとめまとめ

• 色々な λ 式の書き方

• コレクション初期化子、オブジェクト初期化子

• 型パラメータによって振る舞いを変える

• ファーストクラスオブジェクト

• 高階関数– 関数を受け取る

– 関数を返す( demo: メモ化)

• 標準クエリ演算子( LINQ )

Page 34: CLR/H No.35-2

最後に

Demonstration.

Page 35: CLR/H No.35-2

ご清聴どうもありがとうございました。

Nobuhisa Koizumi.