Objc lambda

1,716 views
1,607 views

Published on

Published in: Business, Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,716
On SlideShare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
8
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Objc lambda

    1. 1. Objective-C de lambda 松浦 明彦 @matu_ani 1
    2. 2. 自己紹介• コップ本読んでる途中な程度• 札幌C++勉強会メンバー(最年長w) • 「プログラミングの魔導少女」:巻末記事• 監修メンバー • 「C++の設計と進化」(通称:D&E) • 「ストラウストラップのプログラミング入門」 (通称:鈍器w)• ジャズと酒が趣味、シングルパパです。 2
    3. 3. お話しすること・ねらい• Objective-Cの紹介がてら、関数型つなが りでObjective-Cのラムダ式(Blocks)に ついてお話します。 • めざせBlocks完全制覇!!• 実装・シンタックス寄り、現場的なお話し です。• 関数型的なお話は殆どありません m(_ _)m 3
    4. 4. もくじ• Objective-C 文法基礎• Objective-C Blocks基礎• Objective-C Blocks応用• C++とBlocks 4
    5. 5. Objective-C 文法基礎 さらっと流します... 5
    6. 6. Objective-Cとは• C言語にオブジェクト指向機能を追加:☓• Smalltalk風 Object Systemの言語環境にて、C 言語も使うことが出来る:○ • Cの言語仕様自体には、何も足さない何も引かない。 6
    7. 7. Objective-Cとは• C言語にオブジェクト指向機能を追加:☓• Smalltalk風 Object Systemの言語環境にて、C 言語も使うことが出来る:○ • Cの言語仕様自体には、何も足さない何も引かない。 スクリプト言語並の動的言語と静的型付 け言語が共存するハイブリッドな環境 6
    8. 8. Smalltalk 例"initializeメッセージをaMyObjectに送信"aMyObject initialize."引数30のsetSizeメッセージをaSquareに送信"aSquare setSize : 30."オブジェクト「3」にセレクタ「+」を引数「4」で送信"total := 3 + 4. 7
    9. 9. Objective-Cでのメッセージ送信• メソッド呼び出しは、メッセージ(セ レクタ)送信の結果である。// 単項メッセージ(引数なし)[receiver msg];// receiver->msg(); // 引数付きメッセージval = [receiver msg: arg1 with: arg2];// val = receiver->msg( arg1, arg2 ); 8
    10. 10. Objective-Cでのメッセージ送信• メソッド呼び出しは、メッセージ(セ レクタ)送信の結果である。// 単項メッセージ(引数なし)[receiver msg];// receiver->msg(); [] で囲う メッセージキーワード // 引数付きメッセージval = [receiver msg: arg1 with: arg2];// val = receiver->msg( arg1, arg2 ); 8
    11. 11. クラスの宣言・定義• クラスの宣言・定義には@コンパイラ ディレクティブを使う。• 通常、宣言部を.hファイル、実装部を.m ファイルに記述する。(一緒でもよい)• #importは#includeと基本同じだが、二 重includeしない。 9
    12. 12. #import <Foundation/Foundation.h>// クラスの宣言@interface MyClass : NSObject { int val;}- (id)init;+ (void)classMethod:(id)arg; // クラスメソッド- (id)method:(NSObject*)arg1 with:(int)arg2;@end// 実装@implementation MyClass+ (void)classMethod:(id)arg { // some operation}- (id)method:(NSObject*)arg1 with:(int)args2 { return obj;}@end 10
    13. 13. #import <Foundation/Foundation.h>// クラスの宣言@interface MyClass : NSObject { int val;}- (id)init;+ (void)classMethod:(id)arg; // クラスメソッド- (id)method:(NSObject*)arg1 with:(int)arg2;@end// 実装@implementation MyClass+ (void)classMethod:(id)arg { // some operation}- (id)method:(NSObject*)arg1 with:(int)args2 { return obj;}@end 10
    14. 14. 制御構文• if,while,for,とか、JavaやC++と同じ。 AlarmFake* f = [[AlarmFake alloc]init]; if( [f conformsToProtocol:@protocol(Alarm)] ) {// ・・・ } 11
    15. 15. 基礎編、もうちょい• C/C++との共存• メモリ管理について 12
    16. 16. C/C++との共存• 普通にC/C++が使える。• C++を使う場合、.mでなく、.mmにす る。(ていうか基本.mmにすべし)• boostも使える。• Xcode4.2のllvm-clangはC++11(一 部)も! 13
    17. 17. #import <Foundation/Foundation.h>#include <iostream>#include <boost/shared_ptr.hpp>class CppClass{public: C++のクラス! CppClass(){}! void print() const {! ! std::cout << "CppClass::print" << std::endl;! }};@interface ObjcClass : NSObject- (void)print;@end Objective-Cのクラス@implementation ObjcClass- (void)print {! NSLog(@"ObjcClass print");}@endvoid boost_test(){! boost::shared_ptr<CppClass> p(new CppClass);!! ObjcClass* oc = [[ObjcClass alloc]init];!! [oc print]; // ObjcClass print! p->print(); // CppClass::print} 14
    18. 18. メモリ管理• Objective-Cのクラスは静的には生成で きない。必ずallocする。MyObject* obj = [[MyObject alloc] init];[obj method :arg with:10]; 15
    19. 19. 参照カウンタ • 難敵:retain,release,autoreleaseMyObject* obj = [[MyObject alloc] init]; // 参照カウント1[obj retain]; // 参照カウント2NSLog(@"count=%d", [obj retainCount] ); // count=2[obj release] ; // 参照カウント1[obj release] ; // 参照カウント0,開放される・・・// メモリプールが有効なあいだ生きてるMyObject* obj = [[[MyObject alloc] init] autorelease];[obj retain]; // 参照カウント2、メモリプールの生き死に関わらず保持したい! 16
    20. 20. 簡単にリークするw• release忘れ• retainしすぎ• autorelease忘れ• しかも、これらが絡み合うww• ..... Appleが示した解決策は 17
    21. 21. Automatic ReferenceCounting (ARC)• iOS5、MacOSX10.6から• Xcode4.2ではデフォルト• 参照カウンタ管理をコンパイル時に解決し てくれる。ヽ(^。^)ノ• retain/release/retainCount等は書かなく ていい。 • てか、書いたらコンパイルエラー orz• GCとは別(GCもオプションであり) 18
    22. 22. その他の機能• ランタイムシステム• プロパティ• プロトコル• カテゴリ• クラスエクステンション• クラスクラスタ• 例外• GC• 高速列挙 • ・・・などなど、あと、フレームワークには一切触れてません 19
    23. 23. Objective-C Blocks 20
    24. 24. Blocks基礎 21
    25. 25. Blocksって• ようはラムダです。 • ラムダ式のリテラル• MacOSX 10.6/iOS 4.0以降• AppleのC言語の拡張 • http://www.open-std.org/jtc1/sc22/wg14/ www/docs/n1370.pdf 22
    26. 26. Declaring a Block• シンタックスはCの関数ポインタと似ている。• ^ を使う。 23
    27. 27. Using a Blockvoid (^b1)(int) = ^(int x){NSLog(@"Hello Blocks %d",x);};b1(100); // Hello Blocks 100// パラメータ無しなら定義側は()を省略してもOKvoid (^b2)() = ^{NSLog(@"Hello Blocks 2");};b2(); // Hello Blocks 2 24
    28. 28. パラメータにBlockvoid blocks_caller( void (^f)(void) ){! f();}void blocks_test(){! blocks_caller( ^(){ NSLog(@"test1");} );} 25
    29. 29. Blocksどーよ• 最近のCocoaAPI は積極的にBlockを 使う傾向にある(iCloud APIとか)。• なんだかんだメモリ管理を意識。 Automatic Reference Counting (ARC) のもとで使うのが良さそう。• 過渡期っぽい.....が、今後は重要なプロ グラミングスタイルと思われ。 26
    30. 30. Blocks応用 といっても、キャプチャとかBlockの寿命とかそのへん 27
    31. 31. 変数のキャプチャ• ローカル変数、グローバル変数をBlock 内で使用可能• ローカル変数はデフォルトで、イミュー タブル、かつBlock構築時のコピー 28
    32. 32. キャプチャの例int g=999; // グローバル変数・・・int x = 100;void (^b)() = ^(){NSLog(@"x=%d g=%d",x,g);};b(); // x=100 g=999x=200;b(); // x=100(変わらず)g=888;b(); // x=100 g=888 29
    33. 33. ミュータブルで共有なキャ プチャ__block int x=100;void (^b)() = ^(){NSLog(@"x=%d g=%d", x++, g);};b(); // x=100 g=999b(); // x=101 g=999x=200;b(); // x=200 g=999 30
    34. 34. クラスで使う @interface testClass : NSObject{ int x_; } -(void) myprint; -(void) print:(void(^)(int x))printer; @end @implementation testClass -(void)print:(void (^)(int x))printer { printer(x_); }testClass* t = [[testClass alloc]init];[t print:^(int x){ NSLog(@"my printer x=%d", x);}]; 31
    35. 35. selfのキャプチャ-(void)myprint { // testClassのメソッド x_ = 100; void(^b)()=^{ NSLog(@"x_=%d", x_);}; b(); // x_ = 100 x_ = 200; b(); // x_ = 200 !!(コピーと違うの??) // こう書いているのと同じ void(^b2)()=^{ NSLog(@"testClass x_=%d", self->x_);};} • メンバー変数がキャプチャされているのではない • selfがキャプチャされている! 32
    36. 36. 高階関数、部分適用C#Func<int, Func<int, int>> f = x => y => x + y;Func<int, int> fc = f(1);int x = fc(3); // 4 (1 + 3)C++11auto f = [](int x){ return [x](int y){return x+y;}; };auto fc = f(1);int x = fc(3); // 4 (1 + 3) 33
    37. 37. Blockだと。。void blocks_test(){! typedef int (^add_function)(int);! add_function (^f)(int) =! ! ! ! ! ^(int x){! ! ! ! ! ! return Block_copy(^(int y){ return x+y;});! ! ! ! ! };! add_function fc = f(1);! NSLog(@"blocks_test() fc=%d", fc(3)); // 4 (1 + 3)! Block_release(fc);} 34
    38. 38. Blocks大事なこと• Blockの生存期間はそのスタックと同じ。• スタック外で使うならコピーが必要。 • Block_copy / Block_release • ただ、コピーしなくてもコンパイル通る(事が多い)し、 動くから恐ろしい。• ARCのもとでは Block_copy / Block_release 不要。 • てかコンパイルエラーになる 35
    39. 39. ARCありなら...void blocks_test(){! typedef int (^add_function)(int);! add_function (^f)(int) = ^(int x){return ^(int y){return x+y;};};! add_function fc = f(1);! NSLog(@"blocks_test() fc=%d", fc(3)); // 4 (1 + 3)} すっきり(^^) 36
    40. 40. 軽くまとめ• ローカル変数のキャプチャはデフォルトで イミュータブルかつBlock構築時のコピー。• __block修飾されたローカル変数は、ミュー タブルとなり、そのスタック内のblockで共 有される。• Blockの寿命はスタックと同じ。スタック外 でも使いたければcopyが必要。• ARCが吉 37
    41. 41. BlocksとC++ 実はここを一番話したかったという噂もw... 38
    42. 42. C++11のfunction<T> にBlockをstd::function<void(int)> f = ^(int x){NSLog(@"Hello function!! x=%d",x);};f(1); // Hello function!! x=1f(2); // Hello function!! x=2 std::function<T>は、Blocks対応に書き換え てあるのかな?? 39
    43. 43. 簡易function作ったtemplate<typename R, typename ...V>struct my_function { struct HolderBase{ virtual R run(V... arg)=0; }; template<typename F> struct Holder : HolderBase { F f_; Holder(F f):f_(f){} virtual R run(V... arg) { return f_(arg...); } }; boost::scoped_ptr<HolderBase> holder_; template<typename F> my_function(F f) : holder_(new Holder<F>(f) ){} R operator()(V... arg) { holder_->run(arg...); }}; 40
    44. 44. my_functionにもmy_function<void,int> mf(^(int x){NSLog(@"my_function!! x=%d",x);});mf(100); // my_function!! x=100 • my_functionにBlocks固有のコードは無い。 • BlocksはObjC固有の型だが、C++のジェネリッ ク型システムはそれを吸収した(とも言えるか と)。 • 無論、std::functionは変更不要 (のはず) 。 41
    45. 45. C++11 autoで型推論// blockをautoで型推論auto af = ^(int x){NSLog(@"Hello C++11 auto!! x=%d",x);};af(5); // Hello C++11 auto!! x=5// 高階関数も楽チンauto f = ^(int x){ return ^(int y){ return x+y;};};auto fc = f(1);NSLog(@"Hello C++11 auto!! fc=%d",fc(3)); // fc=4 42
    46. 46. C++11 autoで型推論// blockをautoで型推論auto af = ^(int x){NSLog(@"Hello C++11 auto!! x=%d",x);};af(5); // Hello C++11 auto!! x=5// 高階関数も楽チンauto f = ^(int x){ return ^(int y){ return x+y;};};auto fc = f(1);NSLog(@"Hello C++11 auto!! fc=%d",fc(3)); // fc=4 やっぱC++かわいいw 42
    47. 47. ご清聴ありがとうございました 43

    ×