Clang Language Extensionsによると、C++11のlambda式からBlocksポインタへの変換が自動で行われるみたいなので試してみました。
なお、確認にあたって利用したXcodeのバージョンは5.0 (5A1412)です。
簡単な例
拡張子を.mmにしておけば、lambdaで次のように書くことができます。
auto cmptr = [](id x, id y) -> NSComparisonResult { return [x compare:y]; }; auto array = @[ @"spam", @"foo", @"bar", @"bazz" ]; auto sorted = [array sortedArrayUsingComparator:cmptr]; NSLog(@"%@", [sorted componentsJoinedByString:@", "]); //=> bar, bazz, foo, spam
なお、内部的にはこのlambdaから該当シグネチャのBlockへの変換演算子 (返されるBlockオブジェクトはlambdaへの転送だけを行う) を使うことで実現しているようです。
詳細はClang Language Extensionsの「Interoperability with C++11 lambdas」を参照ください。
複雑な例
もう少し複雑な例として、以前の記事「Objective-C上でブロックオブジェクトによる高階関数を用いてソートする方法について」と同じコードをlambdaで書き直してみました。
auto compByName = [](File* a, File* b) { return [a.name compare:b.name]; }; auto compByIName = [](File* a, File* b) { return [a.name caseInsensitiveCompare:b.name]; }; auto makeCompByDir = [](NSComparator f) { return [f](File* a, File* b) { BOOL adir = a.isDirectory; BOOL bdir = b.isDirectory; if (a.isDirectory == b.isDirectory) return f(a, b); return (adir && ! bdir)? NSOrderedAscending : NSOrderedDescending; }; }; auto makeCompByKind = [](NSComparator f) { return [f](File* a, File* b) -> NSComparisonResult { NSComparisonResult res = [a.name.pathExtension caseInsensitiveCompare:b.name.pathExtension]; return res == NSOrderedSame? f(a, b) : res; }; }; auto sorted = [array sortedArrayUsingComparator:makeCompByDir(makeCompByKind(compByName))];
以前の記事がARC未対応であったりしますが、上のコードと比べてもあまり代わりませんね。
ちょっと違うのは、auto
を利用していることと、f
を明示的にキャプチャしていることくらいでしょうか。
なお、Objective-C++にするとautoでBlocksの宣言が省略できるようになるので、個人的にはそれだけでもとても嬉しかったりします。
auto compByName = ^(id a, id b) { return [[a name] compare:[b name]]; };
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。