Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Objective-C
de
lambda
松浦 明彦
@matu_ani
1
13年9月4日水曜日
自己紹介
• コップ本読んでる途中な程度
• 札幌C++勉強会メンバー(最年長w)
•

「プログラミングの魔導少女」:巻末記事

•
•

「C++の設計と進化」(通称:D&E)

• 監修メンバー
「ストラウストラップのプログラミング入門」...
お話しすること・ねらい
• Objective-Cの紹介がてら、関数型つなが
りでObjective-Cのラムダ式(Blocks)に
ついてお話します。

•

めざせBlocks完全制覇!!

• 実装・シンタックス寄り、現場的なお話し
です...
もくじ
• Objective-C 文法基礎
• Objective-C Blocks基礎
• Objective-C Blocks応用
• C++とBlocks
4
13年9月4日水曜日
Objective-C
文法基礎
さらっと流します...

5
13年9月4日水曜日
Objective-Cとは
• C言語にオブジェクト指向機能を追加:☓
• Smalltalk風 Object Systemの言語環境にて、C
言語も使うことが出来る:○

• Cの言語仕様自体には、何も足さない何も引かない。

6
13年9月...
Objective-Cとは
• C言語にオブジェクト指向機能を追加:☓
• Smalltalk風 Object Systemの言語環境にて、C
言語も使うことが出来る:○

• Cの言語仕様自体には、何も足さない何も引かない。
スクリプト言語並...
Smalltalk 例
"initializeメッセージをaMyObjectに送信"
aMyObject initialize.
"引数30のsetSizeメッセージをaSquareに送信"
aSquare setSize : 30.
"オブジ...
Objective-Cでのメッセ
ージ送信

• メソッド呼び出しは、メッセージ(セ
レクタ)送信の結果である。
// 単項メッセージ(引数なし)
[receiver msg];
// receiver->msg();
// 引数付きメッセージ...
Objective-Cでのメッセ
ージ送信

• メソッド呼び出しは、メッセージ(セ
レクタ)送信の結果である。
// 単項メッセージ(引数なし)
[receiver msg];
// receiver->msg();

[] で囲う
メッセー...
クラスの宣言・定義
• クラスの宣言・定義には@コンパイラデ
ィレクティブを使う。

• 通常、宣言部を.hファイル、実装部を.m
ファイルに記述する。(一緒でもよい)

• #importは#includeと基本同じだが、二
重include...
#import <Foundation/Foundation.h>
// クラスの宣言
@interface MyClass : NSObject {
int val;
}
- (id)init;
+ (void)classMethod:(id...
#import <Foundation/Foundation.h>
// クラスの宣言
@interface MyClass : NSObject {
int val;
}
- (id)init;
+ (void)classMethod:(id...
制御構文
• if,while,for,とか、JavaやC++と同じ。
AlarmFake* f = [[AlarmFake alloc]init];
if( [f conformsToProtocol:@protocol(Alarm)]
{
...
基礎編、もうちょい
• C/C++との共存
• メモリ管理について

12
13年9月4日水曜日
C/C++との共存
• 普通にC/C++が使える。
• C++を使う場合、.mでなく、.mmにす
る。(ていうか基本.mmにすべし)

• boostも使える。
• Xcode4.2のllvm-clangはC++11(一
部)も!
13
13年...
#import <Foundation/Foundation.h>
#include <iostream>
#include <boost/shared_ptr.hpp>
class CppClass{
public:
C++のクラス
! Cp...
メモリ管理
• Objective-Cのクラスは静的には生成で
きない。必ずallocする。
MyObject* obj = [[MyObject alloc] init];
[obj method :arg with:10];

15
13年...
参照カウンタ
• 難敵:retain,release,autorelease
MyObject* obj = [[MyObject alloc] init]; // 参照カウント1
[obj retain]; // 参照カウント2
NSLog(...
簡単にリークするw
• release忘れ
• retainしすぎ
• autorelease忘れ
• しかも、これらが絡み合うww
• ..... Appleが示した解決策は
17
13年9月4日水曜日
Automatic Reference
Counting (ARC)

• iOS5、MacOSX10.6から
• Xcode4.2ではデフォルト
• 参照カウンタ管理をコンパイル時に解決し
てくれる。ヽ(^。^)ノ
• retain/rele...
その他の機能
•
•
•
•
•
•
•
•
•

ランタイムシステム
プロパティ
プロトコル
カテゴリ
クラスエクステンション
クラスクラスタ
例外
GC
高速列挙

•

・・・などなど、あと、フレームワークには一切触れてません

19
1...
Objective-C
Blocks

20
13年9月4日水曜日
Blocks基礎

21
13年9月4日水曜日
Blocksって
• ようはラムダです。
•

ラムダ式のリテラル

• MacOSX 10.6/iOS 4.0以降
• AppleのC言語の拡張
•

http://www.open-std.org/jtc1/sc22/wg14/
www/d...
Declaring a Block

•
•

シンタックスはCの関数ポインタと似ている。
^ を使う。
23

13年9月4日水曜日
Using a Block
void (^b1)(int) = ^(int x){NSLog(@"Hello Blocks %d",x);};
b1(100); // Hello Blocks 100
// パラメータ無しなら定義側は()を省略...
パラメータにBlock
void blocks_caller( void (^f)(void) )
{
! f();
}
void blocks_test()
{
! blocks_caller( ^(){ NSLog(@"test1");} ...
Blocksどーよ
• 最近のCocoaAPI は積極的にBlockを

使う傾向にある(iCloud APIとか)。

• なんだかんだメモリ管理を意識。

Automatic Reference Counting
(ARC) のもとで使うの...
Blocks応用
といっても、
キャプチャとかBlockの寿命とかそのへん

27
13年9月4日水曜日
変数のキャプチャ
• ローカル変数、グローバル変数をBlock
内で使用可能

• ローカル変数はデフォルトで、イミュー
タブル、かつBlock構築時のコピー

28
13年9月4日水曜日
キャプチャの例
int g=999; // グローバル変数
・・・
int x = 100;
void (^b)() = ^(){NSLog(@"x=%d g=%d",x,g);};
b(); // x=100 g=999
x=200;
b()...
ミュータブルで共有なキャ
プチャ
__block int x=100;
void (^b)() = ^(){NSLog(@"x=%d g=%d", x++, g);};
b(); // x=100 g=999
b(); // x=101 g=9...
クラスで使う
@interface testClass : NSObject{
int x_;
}
-(void) myprint;
-(void) print:(void(^)(int x))printer;
@end
@implementa...
selfのキャプチャ
-(void)myprint { // testClassのメソッド
x_ = 100;
void(^b)()=^{ NSLog(@"x_=%d", x_);};
b(); // x_ = 100
x_ = 200;
b(...
高階関数、部分適用
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++11
a...
Blockだと。。
void blocks_test()
{
! typedef int (^add_function)(int);
! add_function (^f)(int) =
! ! ! ! ! ^(int x){
! ! ! ! ...
Blocks大事なこと
• Blockの生存期間はそのスタックと同じ。
• スタック外で使うならコピーが必要。
•
•

Block_copy / Block_release
ただ、コピーしなくてもコンパイル通る(事が多い)し、
動くから恐ろし...
ARCありなら...
void blocks_test()
{
! typedef int (^add_function)(int);
! add_function (^f)(int) =
^(int x){return ^(int y){re...
軽くまとめ
• ローカル変数のキャプチャはデフォルトで

イミュータブルかつBlock構築時のコピー。

• __block修飾されたローカル変数は、ミュー
タブルとなり、そのスタック内のblockで共
有される。

• Blockの寿命はスタ...
BlocksとC++
実はここを一番話したかったという噂もw...

38
13年9月4日水曜日
C++11のfunction<T>
にBlockを
std::function<void(int)> f
= ^(int x){NSLog(@"Hello function!! x=%d",x);};
f(1); // Hello functi...
簡易function作った
template<typename R, typename ...V>
struct my_function {
struct HolderBase{
virtual R run(V... arg)=0;
};
te...
my_functionにも
my_function<void,int> mf(^(int x){NSLog(@"my_function!! x=%d",x);});
mf(100); // my_function!! x=100

• my_f...
C++11 autoで型推論
// blockをautoで型推論
auto af = ^(int x){NSLog(@"Hello C++11 auto!! x=%d",x);};
af(5); // Hello C++11 auto!! x=...
C++11 autoで型推論
// blockをautoで型推論
auto af = ^(int x){NSLog(@"Hello C++11 auto!! x=%d",x);};
af(5); // Hello C++11 auto!! x=...
ご清聴
ありがとうございました

43
13年9月4日水曜日
Upcoming SlideShare
Loading in …5
×

Objc lambda

836 views

Published on

  • Be the first to comment

  • Be the first to like this

Objc lambda

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

×