SubjectiveScript.m 0.1.2

SubjectiveScript.m 0.1.2

测试已测试
Lang语言 Obj-CObjective C
许可协议 MIT
更新时间上次更新2014年12月

未指定用户 维护。



  • 作者
  • Kevin Malakoff

Subjective-Script 使 Objective-C 更加符合脚本风格!

注意: Subjective-Script 要求您的 Objective-C 项目启用 ARC。

想法

我的首选语言是 CoffeeScript,每当我在 Objective-C 中开发时,我发现自己经常需要查找 [NSSomething reallyLongFunctionName:YES withAVerboseParameterName:YES and:[NSSomethingElse whichAddsMoreBrackets]],这不是一件很有趣或快速的事情!

当我从原始的 Underscore.js_.m 的测试迁移到 Objective-C 中时,它是易于阅读的

var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
people = _.sortBy(people, function(person){ return person.age; });
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');

它在 Objective-C 中的样子如下

NSArray *people = [NSArray arrayWithObjects:
  [NSDictionary dictionaryWithObjectsAndKeys: @"moe", @"name", [NSNumber numberWithInt:30], @"age", nil],
  [NSDictionary dictionaryWithObjectsAndKeys: @"curly", @"name", [NSNumber numberWithInt:50], @"age", nil],
  nil];

STAssertEqualObjects([_.pluck(people, @"name") componentsJoinedByString:@", "],
                     @"moe, curly",
                     @"stooges sorted by age");

键值的顺序不正确,涉及到太多的输入,变得难以阅读。所以我写了 Subjective-Script 并将 QUnit.m 迁移到以下格式

A* people = AO(OKV({@"name", @"curly"}, {@"age", N.I(50)}), OKV({@"name", @"moe"}, {@"age", N.I(30)}));
people = _.sortBy(people, ^(O* person){ return person.get(@"age"); });
equal(_.pluck(people, @"name").join(@", "), @"moe, curly", @"stooges sorted by age");

好多了!最重要的是,我可以通过函数名称重用我的 JavaScript 知识,这样我就不必查找东西,直接完成工作!

语法

类型

虽然 JavaScript 允许灵活的变量类型,但 Objective-C 要求显式变量类型。为了使之更加简洁,我尽量将类型缩短到最简名称

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

并且我也尝试缩短 NSNumbers,使用上述缩写(B, I, UI, F, D)

N* value = N.B(true);
equal(value.B, true, @"YES it is!")

使用聚集类型

我尝试了多种不同的方法,但这种方法看起来既易于阅读又简洁(编译器通过键值对匹配来检查)

A* arrayOfInts = AI(1, 2, 3);
A* arrayOfObjects = AO(N.I(1), N.F(2.0), @"hello", nil, O.new);
I intValue = arrayOfInts.getAt(0).I;    // or: intValue = arrayOfInts.get(@"1").I;
arrayOfInts.setAt(0, N.I(intValue+1));  // or: arrayOfInts.set(@"1", N.I(intValue+1));

O* obj = OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}, {@"string", @"hello"}, {@"nil", nil}, {@"dictionary", O.new});
intValue = obj.get(@"int").I;
obj.set(@"int", N.I(intValue+1));

等价于如下 Javascript

var arrayOfInts = [1, 2, 3];
var arrayOfObjects = [1, 2.0, 'hello', null, {}];
var intValue = arrayOfInts[0];
arrayOfInts[0] = intValue+1;

var obj = {int: 1, float: 2.0, string: 'hello', nil: null, dictionary:{}};
intValue = obj.int;       // or: intValue = obj['int'];
obj.int = intValue+1;     // or: obj['int'] = intValue+1;

如果您有兴趣,Objective-C 未来可能会通过使用 Objective-C 文本 来进一步简化语法

NSA* arrayOfInts = @[@1, @2, @3];
NSA* arrayOfObjects = @[@1, @2.0, @"hello", NSNull.null, @{}];
NSD* obj = @{@int: @1, @float: @2.0, @string: @"hello", @nil: NSNull.null, @dictionary:@{}};

JavaScript 启发库

为了能够重用我的 JavaScript 知识,并且不必查阅 StackOverflow 来查找难以记住的 Objective-C 中的基本功能,我已经移植了一些常见的 JavaScript 函数。

所有对象

N.I(1).instanceof(N.class);
// true

(A.new).instanceof(NSA.class);
// true

N.B(true).toString();
// @"true"

OKV({@"key1", @"value1"}).toString();
// @"[object Object]"

AO(AI(1,2,3),N.F(4.5),OKV({@"five", @"5"})).toString();
// @"[[1,2,3],4.5,[object Object]]

数组

AI(1,2,3).length;
// 3

AI(1,2,3).hasOwnProperty(@"2");
// true

AI(1,2,3).get(@"2");
// N.I(3)

AI(1,2,3).concat(AI(1,2,4);
// [1,2,3,1,2,4]

AO(@"Banana", @"Orange", @"Lemon", @"Apple", @"Mango").slice(-3,-1);
// [Lemon,Apple]

AI(1,2,3).reverse();
// [3,2,1]

AO(N.I(1),AI(2,3)).flatten(true);
// [1,2,3]

AI(1,2,3).pop();
// N.I(3)

AI(1,2,3).push(N.I(4)).push(@"out the door");
// [1,2,3,4,out the door]

AI(3,2,1,2).sort(nil);
// [1,2,2,3]

AO(@"Banana", @"Orange", @"Apple", @"Lemon").splice(2,1, @"Kiwi", @"Mango", nil);
// [Banana,Orange,Kiwi,Mango,Lemon]

AI(3,4,5).unshift(N.I(1),N.I(2),nil);
// [1,2,3,4,5]

AI(1,2,3,4,5).shift();
// [2,3,4,5]

对象/字典

OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}).hasOwnProperty(@"int");
// true

OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}).delete_(@"int").hasOwnProperty(@"int");
// false

@"int".in(OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}));
// true
delete obj.key or delete obj['key'] -> obj.delete_(@"key") -> what is the delete resevered word for..can it be used?

字符串

@"hello world!".split(@" ")
// [@"hello", @"world!"]

@"hello world!".split(@"");
// [@"h", @"e", @"l", @"l", @"o", @"w", @"o", @"r", @"l", @"d", @"!"]

@"hello".add(@"world!");
// @"hello world!"

S* message = S.newS(@"hello"); message.append(@" world!");
// message == @"hello world!"

日期

SS.stringify(Date.newYMD_JS(2012, 7, 31));
// @"2012-08-30T15:00:00.000Z"

功能

O* obj = OKV({@"mirror", ^(NSS* string){return string.add(@" mirror"); }});
@"mirror".call(obj, @"hello", nil);
// @"hello mirror"

@"mirror".apply(obj, AO(@"hello"));
// @"hello mirror"

工具

Subjective-Script基对象上有一些工具,而不是像JavaScript那样使它们全局。

SS.stringify(AO(N.I(1), N.F(2.0), N.F(3.1), @"hello", nil, O.new));
// @"[1,2,3.1,\"hello\",null,{}]"

SS.parseInt(@"123");
// N.I(123)

SS.typeof_(N.B(true));
// @"boolean"

SS.typeof_(@"string");
// @"string"

SS.typeof_(Date.new);
// @"object"

__block BOOL called1 = false;
SSTimeout* timeout1 = SS.setTimeout(^{ called1 = true; }, NSEC_PER_SEC*1);
SS.clearTimeout(timeout1);
// not called

__block BOOL called2 = false;
SS.setTimeout(^{ called2 = true; }, NSEC_PER_SEC*2);
// called

仅此一点

您也可以轻松地为您自己的对象添加命名属性

@interface MyObject : O
  @property (strong) NSS* name;
@end
@implementation MyObject : O
  @dynamic name;
  IMPLEMENT_NAMED_PROPERTIES
@end

MyObject* obj = MyObject.new;
obj.name = @"Steve";
// they call me Steve

所以您可以像这样编写初始示例

@interface Stooge : O
  @property (strong) NSS* name;
  @property (strong) N* age;
@end
@implementation Stooge
  @dynamic name, age;
  IMPLEMENT_NAMED_PROPERTIES
@end

A* people = AO(OTKV(Stooge, {@"name", @"curly"}, {@"age", N.I(50)}), OTKV(Stooge, {@"name", @"moe"}, {@"age", N.I(30)}));
people = _.sortBy(people, ^(Stooge* person){ return person.age; }); // no get(@"age") required
equal(_.pluck(people, @"name").join(@", "), @"moe, curly", @"stooges sorted by age");

用法

要运行示例项目;首先从项目目录中克隆仓库并运行 pod install

要求

安装

作者

Kevin Malakoff, [email protected]

许可证

SubjectiveScript.m正处于MIT许可证下。有关更多信息,请参阅LICENSE文件。

请为SubjectiveScript.m做出贡献

目前,这仍处于早期阶段,还有很多要添加和测试。请帮忙!

如果您想添加其他内容,只需在适当的位置实现它,编写适当的测试,然后在GitHub上提交拉取请求。

此外,如果您想提交其他语言中您喜欢的特性,只要它们易于记忆并有助于加快开发速度即可!