Objective-CでSQLっぽい記法を書いてみる

思う所あって試しに開発のことなどを書いてみたり。

NSArrayのオブジェクトをフィルタ・加工するのに、SQLよろしく

// objはNSInteger number, NSString *nameを持つとする

// numberが10より大のオブジェクトを見つけてそのnameのリストを返す
id result = [list where: obj.number > 10
                 select: obj.name];

みたいに書けたらいいなあ、なんて思ったりする。blockを使うと近いことは可能で、

@implementation NSArray (QUERY)
- (NSArray*)where:(BOOL (^)(id obj))filter
           select:(id (^)(id obj))projection
{
    id ret = [NSMutableArray array];
    for(id obj in self)
    {
        if(filter(obj))
            [ret addObject: projection(obj)];
    }
    return [[ret copy] autorelease];
}
@end

void test(NSArray *list)
{
    id result = 
      [list where: ^BOOL (Type *obj) { return obj.number > 10; }              
           select: ^id (Type *obj) { return obj.name; }];
}

しかしこれはどうにもこうにも記法がキモイのでマクロを併用したいところ。

#define $where(ARG,BODY) (^BOOL (ARG) { return ({ BODY; }); })
#define $select(ARG,BODY) (^id (ARG) { return ({ BODY; }); })

void test2(NSArray *list)
{
    id result = [list where: $where(Type *obj, obj.number > 10)
                     select: $select(Type *obj, obj.name)];
}

BODY部を複文式で受けているので、もう少し複雑な条件でもいける。

where/selectが二重だからこれもマクロに食わせる手はあるのだが、エディタのインデントを考慮するとこの方がいいんじゃないかと思う。(:は区切り扱いされるのでマクロ名には使えない)

NSPredicateでやれよって?

Objective-CでSQLっぽい記法を書いてみる” への1件のコメント

  1. fowardInvocation利用して、送信したメッセージをSqlとして解釈させてやると面白いですよ。本物のSQLを真似ようとすると比較演算子や関数が鬼門になりますが。

    // SqlクラスオブジェクトがFowardInvocationでメッセージを解釈しクエリを生成する。
    [db request:[Sql select: [NSArray arrayWithObjects:”column1″, “column2”] from: [NSArray arrayWithObjects: “table1”]];

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です