More C# λ
自己紹介 名称  := K 泉将久  |  のぶ  | Nobuhisa | 特技 ⇒
C# における λ 式 Func<int, int> f = (x => x * x);
C#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 = () => {};
意外と嬉しい コレクション初期化子 var lst = new List{ 1, 2, 4, 8 };
C#3.0 – Collection Initializers Before… List<Employee> lst =  new  List<Employee>(); Employee john =  new  Employee(); john.Name = &quot;john&quot;; john.Age = 58; Employee michael =  new  Employee(); michael.Name = &quot;taro&quot;; michael.Age = 62; lst.Add( john ); lst.Add( michael );
C#3.0 – Collection Initializers After ! var +  オブジェクト初期化子  +  コレクション初期化子 var  lst =  new  List<Employee>() { new  Employee { Name = &quot;john&quot;, Age = 22 }, new  Employee { Name = &quot;taro&quot;, Age = 24 }, };
C#3.0 – Collection Initializers クラス変数の dic を初期化 public class  Foo { Dictionary< string , int > dic =  new  Dictionary< string , int >{ { &quot;one&quot;, 1 }, { &quot;two&quot;, 2 }, { &quot;three&quot;, 3 } }; /*public Foo() { this.dic.Add( &quot;one&quot;, 1 ); this.dic.Add( &quot;two&quot;, 2 ); this.dic.Add( &quot;three&quot;, 3 ); }*/ }
型パラメータによって 振る舞いを変える Foo<ClassA>.Method( x ); Foo<ClassB>.Method( x );
Generics 渡された型 T は実行時に if 文等で判別できない ( 引数なしの場合 ) 静的フィールドと静的コンストラクタを活用する ⇒  Demo C#3.0 の拡張メソッドを使う ⇒ 容易だがこの場合やや柔軟性に欠ける
1 .  静的フィールドの利用 ジェネリッククラスに属する静的な変数は、型パラメータが違うとどんな扱いになる? class  Foo<T> {  public static int  Value; } ~ Foo< int >.Value = 99; Foo< string >.Value++; Console.WriteLine( Foo< int >.Value ); Console.WriteLine( Foo< string >.Value ); 99 1
Demonstration 型パラメータによって振る舞いを変える -  静的フィールド利用編  -
型パラメータの判別 渡された型 T は実行時に if 文等で判別できない ( 引数なしの場合 ) 静的フィールドと静的コンストラクタを活用する ⇒  Demo C#3.0 の拡張メソッドを使う ⇒ 容易だがこの場合やや柔軟性に欠ける
2 .  拡張メソッドを使った場合 拡張メソッドの使い方 静的クラス、静的メソッド 第一引数の 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
2 .  拡張メソッドを使った場合 public class  Foo<T> { } public static class  FooExtensions { public static void  Method(  this  Foo< string > f,  int  x ) { Console.WriteLine( x + &quot; かもしれない &quot; ); } public static void  Method(  this  Foo< int > f,  int  x ) { Console.WriteLine( x + &quot; じゃないと思う &quot; ); } public static void  Method<T>(  this  Foo<T> f,  int  x ) { Console.WriteLine( x ); } } つづく
2 .  拡張メソッドを使った場合 public void  Test() { new  Foo< string >().Method( 10 ); new  Foo< int >().Method( 100 ); new  Foo<Foo< string >>().Method( 1000 ); } 10 かもしれない 100 だと思う 1000
2 .  拡張メソッドを使った場合 好きそうな人向けのおまけ ~ カリー化 拡張メソッドの第一引数部分に f を束縛した状態 本格的なカリー化はクロージャで var  f =  new  Foo< string >(); Action< int > curry = f.Method; curry( 10 );  // 10 かもしれない
C# における クロージャのからくり x => y => x * y;
函数は ファーストクラスオブジェクト f = Console.WriteLine;
ファーストクラスオブジェクト? (ほぼ)第一級オブジェクトです だから何?(←みんなの心の声) 次ページから具体例をお見せします 高階関数が直感的に書ける これを使う利点が分かりません(←みんなの心の声) 後ほど扱います
実用例~関数の足し算 public  Func< string > GetFunc() { string  data = &quot;hello&quot;; Func< string > fns = null; fns += (() => data += &quot; world&quot;); fns += (() => data = data.ToUpper()); fns += (() => data = &quot;<b>&quot;+data+&quot;</b>&quot;); return  fns; } ~ var  f =  this .GetFunc(); Console.WriteLine( f() );  // <b>HELLO WORLD</b> “ 責任”を動的に組み替えられる ⇒ ミニマムな Decorator パターン
実用例2~ switch の除去 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  &quot;taro&quot;:  return   new   ネオちくわ (); case  &quot;hanako&quot;:  return new   いも (); case  &quot;mae&quot;:  return new   みそしる (); default :  throw new  ArgumentException(); } } Before…
実用例2~ switch の除去 private  Dictionary< string , Func< Food >> table = new  Dictionary< string , Func< Food >>() { { &quot;taro&quot;, () =>  new   ネオちくわ () }, { &quot;hanako&quot;, () =>  new   いも () }, { &quot;mae&quot;, () =>  new   みそしる () } }; public  Food Create(  string  name ) { if (  this .table.ContainsKey( name ) ) return   this .table[ name ](); throw new  ArgumentException(); } After !
高階関数をもう少し (sort '((one . 1) (two . 2) (three . 3)) #'> :key #'cdr)
高階関数 「関数を受け取る」高階関数 関数の抽象化が可能となり、汎用性が増す 従来の抽象化の概念がクラスレベルから関数レベルへ 「関数を返す」高階関数 関数を動的に生成したり、改造したりできる 知らなくても良い情報を隠蔽する価値もある 前者より脚光を浴びてない(?)ので、 今日はこっちを主役にします
高階関数~メモ化 本日ご紹介するのはコレ! ⇒ 渡された関数にキャッシュ機能を追加して返す 処理が重い && 複数回実行される関数などを渡す 2 回目以降は高速化が期待できる 外部の可変変数に依存していない関数を渡す 引数と計算結果のペアを、コレクションに保存しておき、クロージャにして返す このような機能をメモ化 ( memoization,memoize ) という
高階関数~メモ化 Demo プログラムの主要部分抜粋 public Func<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 )
Demonstration メタボ関数を軽くする -  メモ化  -
ちょっとマイナーな 標準クエリ演算子 SelectMany. ToLookup. OfType.
Demonstration いくつかクエリを - LINQ -
質問タイム \ ( ^ o ^ ) /
まとめ
まとめ 色々な λ 式の書き方 コレクション初期化子、オブジェクト初期化子 型パラメータによって振る舞いを変える ファーストクラスオブジェクト 高階関数 関数を受け取る 関数を返す( demo: メモ化) 標準クエリ演算子( LINQ )
最後に Demonstration.
ご清聴どうもありがとうございました。 Nobuhisa Koizumi.

CLR/H No.35-2

  • 1.
  • 2.
    自己紹介 名称 := K 泉将久 | のぶ | Nobuhisa | 特技 ⇒
  • 3.
    C# における λ式 Func<int, int> f = (x => x * x);
  • 4.
    C#3.0 – lambdaexpression 書き方色々 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 = () => {};
  • 5.
  • 6.
    C#3.0 – CollectionInitializers Before… List<Employee> lst = new List<Employee>(); Employee john = new Employee(); john.Name = &quot;john&quot;; john.Age = 58; Employee michael = new Employee(); michael.Name = &quot;taro&quot;; michael.Age = 62; lst.Add( john ); lst.Add( michael );
  • 7.
    C#3.0 – CollectionInitializers After ! var + オブジェクト初期化子 + コレクション初期化子 var lst = new List<Employee>() { new Employee { Name = &quot;john&quot;, Age = 22 }, new Employee { Name = &quot;taro&quot;, Age = 24 }, };
  • 8.
    C#3.0 – CollectionInitializers クラス変数の dic を初期化 public class Foo { Dictionary< string , int > dic = new Dictionary< string , int >{ { &quot;one&quot;, 1 }, { &quot;two&quot;, 2 }, { &quot;three&quot;, 3 } }; /*public Foo() { this.dic.Add( &quot;one&quot;, 1 ); this.dic.Add( &quot;two&quot;, 2 ); this.dic.Add( &quot;three&quot;, 3 ); }*/ }
  • 9.
  • 10.
    Generics 渡された型 Tは実行時に if 文等で判別できない ( 引数なしの場合 ) 静的フィールドと静的コンストラクタを活用する ⇒ Demo C#3.0 の拡張メソッドを使う ⇒ 容易だがこの場合やや柔軟性に欠ける
  • 11.
    1 . 静的フィールドの利用 ジェネリッククラスに属する静的な変数は、型パラメータが違うとどんな扱いになる? class Foo<T> { public static int Value; } ~ Foo< int >.Value = 99; Foo< string >.Value++; Console.WriteLine( Foo< int >.Value ); Console.WriteLine( Foo< string >.Value ); 99 1
  • 12.
  • 13.
    型パラメータの判別 渡された型 Tは実行時に if 文等で判別できない ( 引数なしの場合 ) 静的フィールドと静的コンストラクタを活用する ⇒ Demo C#3.0 の拡張メソッドを使う ⇒ 容易だがこの場合やや柔軟性に欠ける
  • 14.
    2 . 拡張メソッドを使った場合 拡張メソッドの使い方 静的クラス、静的メソッド 第一引数の 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
  • 15.
    2 . 拡張メソッドを使った場合 public class Foo<T> { } public static class FooExtensions { public static void Method( this Foo< string > f, int x ) { Console.WriteLine( x + &quot; かもしれない &quot; ); } public static void Method( this Foo< int > f, int x ) { Console.WriteLine( x + &quot; じゃないと思う &quot; ); } public static void Method<T>( this Foo<T> f, int x ) { Console.WriteLine( x ); } } つづく
  • 16.
    2 . 拡張メソッドを使った場合 public void Test() { new Foo< string >().Method( 10 ); new Foo< int >().Method( 100 ); new Foo<Foo< string >>().Method( 1000 ); } 10 かもしれない 100 だと思う 1000
  • 17.
    2 . 拡張メソッドを使った場合 好きそうな人向けのおまけ ~ カリー化 拡張メソッドの第一引数部分に f を束縛した状態 本格的なカリー化はクロージャで var f = new Foo< string >(); Action< int > curry = f.Method; curry( 10 ); // 10 かもしれない
  • 18.
  • 19.
  • 20.
    ファーストクラスオブジェクト? (ほぼ)第一級オブジェクトです だから何?(←みんなの心の声)次ページから具体例をお見せします 高階関数が直感的に書ける これを使う利点が分かりません(←みんなの心の声) 後ほど扱います
  • 21.
    実用例~関数の足し算 public Func< string > GetFunc() { string data = &quot;hello&quot;; Func< string > fns = null; fns += (() => data += &quot; world&quot;); fns += (() => data = data.ToUpper()); fns += (() => data = &quot;<b>&quot;+data+&quot;</b>&quot;); return fns; } ~ var f = this .GetFunc(); Console.WriteLine( f() ); // <b>HELLO WORLD</b> “ 責任”を動的に組み替えられる ⇒ ミニマムな Decorator パターン
  • 22.
    実用例2~ switch の除去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 &quot;taro&quot;: return new ネオちくわ (); case &quot;hanako&quot;: return new いも (); case &quot;mae&quot;: return new みそしる (); default : throw new ArgumentException(); } } Before…
  • 23.
    実用例2~ switch の除去private Dictionary< string , Func< Food >> table = new Dictionary< string , Func< Food >>() { { &quot;taro&quot;, () => new ネオちくわ () }, { &quot;hanako&quot;, () => new いも () }, { &quot;mae&quot;, () => new みそしる () } }; public Food Create( string name ) { if ( this .table.ContainsKey( name ) ) return this .table[ name ](); throw new ArgumentException(); } After !
  • 24.
    高階関数をもう少し (sort '((one. 1) (two . 2) (three . 3)) #'> :key #'cdr)
  • 25.
    高階関数 「関数を受け取る」高階関数 関数の抽象化が可能となり、汎用性が増す従来の抽象化の概念がクラスレベルから関数レベルへ 「関数を返す」高階関数 関数を動的に生成したり、改造したりできる 知らなくても良い情報を隠蔽する価値もある 前者より脚光を浴びてない(?)ので、 今日はこっちを主役にします
  • 26.
    高階関数~メモ化 本日ご紹介するのはコレ! ⇒渡された関数にキャッシュ機能を追加して返す 処理が重い && 複数回実行される関数などを渡す 2 回目以降は高速化が期待できる 外部の可変変数に依存していない関数を渡す 引数と計算結果のペアを、コレクションに保存しておき、クロージャにして返す このような機能をメモ化 ( memoization,memoize ) という
  • 27.
    高階関数~メモ化 Demo プログラムの主要部分抜粋public Func<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 )
  • 28.
  • 29.
  • 30.
  • 31.
    質問タイム \ (^ o ^ ) /
  • 32.
  • 33.
    まとめ 色々な λ式の書き方 コレクション初期化子、オブジェクト初期化子 型パラメータによって振る舞いを変える ファーストクラスオブジェクト 高階関数 関数を受け取る 関数を返す( demo: メモ化) 標準クエリ演算子( LINQ )
  • 34.
  • 35.