ぴよログ

↓に移転したのでこっちは更新されません、多分。

Underscore.js風Objective-Cライブラリ「_.m」

移転しました →

マニアックなライブラリを見つけたのでメモっておきます!

_.m Home

Underscore.js風のインターフェースを提供するObjective-Cのライブラリです。前書いたこれに少しだけ近い。

ActiveRecordのようなselectやwhereをObjective-Cで使う - PILOG

今回紹介する_.mにはmapとかreduceみたいなものもあるので、より関数型っぽい?んじゃないかと思います。Underscore.jsなどを知っている人には無用だけど、提供されているインターフェースについてざっくりと紹介。

each

_.each(AI(1, 2, 3), ^(N* num, ...){ SS.alert(num); });
// => alerts each number in turn...

_.each(OKV({@"one", N.I(1)}, {@"two", N.I(2)}, {@"three", N.I(3)}), ^(N* num, ...){ SS.alert(num); });
// => alerts each number in turn...

eachは各要素に特定の処理をさせるメソッドで、ループの代わりに使ったりします。まあ普通のeachってことです。

よく見るとAIとかOKVとかNといった謎のキーワードがでてきます。これは同じ人が書いたライブラリSubjectiveScriptで定義されているマクロで、こんな感じになっています。

#define AI(...)   A.newI((I[]){__VA_ARGS__},    sizeof((I[]){__VA_ARGS__})/sizeof(I))
#define OKV(...)        O.newWithKV((KV[]){__VA_ARGS__, /* NIL_TERMINATION */ nil})

ここでもAとかOとか色々略しまくっていてわかりにくいんですが、慣れた人に楽にかけるようにしたいって思想なんでしょうか。このライブラリについては最後に参考リンクと一部の定義を載せておきます。

map

各要素の対する処理結果を配列で得る場合に使うmap関数。

_.map(AI(1, 2, 3), ^(N* num, ...){ return N.I(num.I * 3); });
// => [3, 6, 9]
_.map(OKV({@"one", N.I(1)}, {@"two", N.I(2)}, {@"three", N.I(3)}), ^id(N* num, ...){ return N.I(num.I * 3); });
// => [3, 6, 9]

ここはAIやらOKVなどの略語がわかりさえすれば読めそうです。

reduce

コレクションの中身を集約するときに使うreduceです。初期値を与えてそれに対して各要素を使った値を足したりしていく感じ。Rubyではinject

N* sum = _.reduce(AI(1, 2, 3), ^(N* memo, N* num, ...){ return N.I(memo.I + num.I); }, N.I(0));
// => 6

delay

配列やディクショナリのようなコレクション要素に対する操作以外のこともできるようです。例えばdelayではNミリ秒後に実行させたい処理を簡単に書くことができます。

_.delay(^{ NSLog(@"%d", 1000); }, NSEC_PER_SEC*1);
// => 'logged later' // Appears after one second.

書き切れない

Underscore.jsにあるようなインターフェースのうちの8割〜9割ほどが提供されている感じです。公式のリファレンスが参考になりますが、Underscore.jsのリファレンスを読むのも助けになりそうです。

日本語の場合はこういうまとめが参考になりそう。

便利機能満載のライブラリUnderscore.js - にのせき日記便利機能満載のライブラリUnderscore.js - にのせき日記はてなブックマーク - 便利機能満載のライブラリUnderscore.js - にのせき日記

SubjectiveScript

kmalakoff/SubjectiveScript.m

typedef BOOL            B;
typedef NSInteger       I;
typedef NSUInteger      UI;
typedef float           F;
typedef double          D;
typedef id              KV[2]; // key-value pair

#define NSO             NSObject
#define A               NSMutableArray
#define NSA             NSArray
#define O               NSMutableDictionary
#define NSD             NSDictionary
#define S               NSMutableString
#define NSS             NSString
#define Date            NSDate
#define N               NSNumber
#define E               NSException