Ленивые типы данных в Objective C - PullRequest
6 голосов
/ 09 мая 2011

В SML для моделирования ленивого программирования возможно следующее:

// Have a datatype to wrap a computation
datatype 'a susp = Susp of (unit -> 'a)
// A function to hold the computation
fun delay(f ) = Susp(f)

Я знаю, что замыкания могут быть написаны с использованием Blocks ,

int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
};

Так что я думаю, что могу использовать это как аргумент функции. Следующим шагом будет использование функций без реальных аргументов ( единичное значение , например, в SML fn () =>) и создание ленивых типов данных, как показано выше.

Возможно ли это или я должен искать другой, более очевидный путь?

Конечной целью было бы эмулировать поведение приостановленных вычислений из SML,

let val x = Susp(fn () => horribleComp(345))
in 
   force(x) + force(x)
end

, где сила (х) равна

fun force (Susp(f)) = f ()

1 Ответ

5 голосов
/ 09 мая 2011

Классный вопрос!

Вы могли бы реализовать ленивый контейнер в Objective-C следующим образом (но, вероятно, не стоит, см. Ниже):

typedef id (^SuspBlock)(void);

@interface Susp : NSObjecti
- (id)initWithBlock:(SuspBlock)block;
+ (id)withBlock:(SuspBlock)block;
- (id)force;
@end

// -----

@interface Susp ()
@property (nonatomic, copy) SuspBlock _block;
@end

@implementation Susp
@synthesize _block;

- (id)initWithBlock:(SuspBlock)block {
  self = [super init];
  if (self != nil) {
    self._block = block;
  }

  return self
}

+ (id)withBlock:(SuspBlock)block {
  return [[[self alloc] initWithBlock:bloc] autorelease];
}

- (id)force {
  return self._block();
}

- (void)dealloc {
 self._block = nil;
 [super dealloc];
}

@end

Это много шаблонного, но что угодно.Затем вы можете использовать это так:

id x = [Susp withBlock:^{ return someComputation(); }];
id result = [[x force] plus:[x force]];
// assuming the result of your computation has -plus:

Но это все довольно глупо, поскольку для того, что вы делаете, вам действительно не нужен другой тип данных.Просто используйте блоки в качестве вашего типа данных:

typedef id (^SuspVal)(void);
SuspVal x = ^{ return complicatedThing; };
id result = [x() plus:x()];

Это гораздо более компактный идиоматичный способ решения этой проблемы, и я предлагаю это.Если вам не нужно добавлять в свои ленивые объекты дополнительную семантику, выходящую за рамки базовых утилит блоков, вам не следует оборачивать их без нужды.

Приветствия!

...