Skip to content

Instantly share code, notes, and snippets.

@carlj
Forked from ole/FunctionalBankAccount.m
Created April 4, 2013 15:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlj/5311255 to your computer and use it in GitHub Desktop.
Save carlj/5311255 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
typedef id(^BankAccount)(char *cmd);
typedef id(^CurrentBalanceMethod)(void);
typedef id(^DepositMethod)(double);
typedef id(^WithdrawMethod)(double);
BankAccount CreateBankAccount(double initialBalance)
{
// Initialization
NSCAssert(initialBalance >= 0.0, @"initialBalance must not be negative");
double __block balance = initialBalance;
// "Method Definitions"
CurrentBalanceMethod currentBalance = ^id{
return @(balance);
};
DepositMethod deposit = ^id(double depositAmount)
{
NSCAssert(depositAmount > 0.0, @"depositAmount must be greater than zero");
balance = balance + depositAmount;
return @(balance);
};
WithdrawMethod withdraw = ^id(double withdrawAmount)
{
NSCAssert(withdrawAmount > 0.0, @"withdrawAmount must be greater than zero");
BOOL hasSufficientBalance = (balance >= withdrawAmount);
if (hasSufficientBalance) {
balance = balance - withdrawAmount;
return @(balance);
} else {
return [NSError errorWithDomain:@"BankAccountErrorDomain" code:2 userInfo:@{ NSLocalizedDescriptionKey : @"Insufficient balance" }];
}
};
// Message Dispatch
id bankAccountBlock = ^id(char *cmd)
{
if (strcmp(cmd, "currentBalance") == 0) {
return currentBalance;
} else if (strcmp(cmd, "deposit") == 0) {
return deposit;
} else if (strcmp(cmd, "withdraw") == 0) {
return withdraw;
} else {
return [NSError errorWithDomain:@"BankAccountErrorDomain" code:1 userInfo:@{ NSLocalizedDescriptionKey : @"Unknown command" }];
}
};
return bankAccountBlock;
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
BankAccount account = CreateBankAccount(100);
NSNumber *balance = ((CurrentBalanceMethod)account("currentBalance"))();
NSLog(@"Balance: %@", balance);
balance = ((DepositMethod)account("deposit"))(50);
NSLog(@"Depositing 50, new balance: %@", balance);
balance = ((WithdrawMethod)account("withdraw"))(30);
NSLog(@"Withdrawing 30, new balance: %@", balance);
balance = ((WithdrawMethod)account("withdraw"))(100);
NSLog(@"Withdrawing 100, new balance: %@", balance);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment