Created
January 12, 2015 10:17
-
-
Save fred-o/61e32b86abe76b7371f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# mutators | |
get = -> | |
set = (newVal) -> (val) -> newVal | |
add = (inc) -> (val) -> val + inc | |
sub = (inc) -> (val) -> val - inc | |
# guards | |
increasing = (oldVal, newVal) -> throw Error "#{newVal} <= #{oldVal}" unless newVal > oldVal | |
decreasing = (oldVal, newVal) -> throw Error "#{newVal} >= #{oldVal}" unless newVal < oldVal | |
immutable = -> throw Error "immutable" | |
# defining classes | |
defineClass = (slotDefs, superClass) -> | |
(slotVals, self) -> | |
dispatcher = (slotName, mutator) -> | |
if def = slotDefs[slotName] | |
type = typeof (newVal = mutator.call self, slots[slotName]) | |
unless newVal is undefined | |
def?.guard slots[slotName], newVal if slots[slotName] isnt undefined | |
throw Error "slot #{slotName} wants #{def.type}; got #{type}" if type isnt def.type | |
slots[slotName] = newVal | |
else | |
throw Error "no slot named #{slotName}" if not parent | |
parent slotName, mutator | |
return slots[slotName] | |
self or= dispatcher | |
parent = superClass slotVals, self if superClass | |
slots = {} | |
for name, def of slotDefs | |
do (name, def) -> | |
self[name] = (mutator) -> dispatcher name, mutator | |
self[name] set slotVals[name] or def.default | |
return dispatcher | |
# example classes | |
Animal = defineClass { | |
_name: { type: 'string' } | |
age: { type: 'number', guard: increasing } | |
} | |
Mammal = defineClass { | |
legs: { type: 'number', default: 4, guard: immutable } | |
parent: { type: 'function' } | |
}, Animal | |
# creating a class instance | |
bird = Animal { _name: 'Birdie', age: 3 } | |
panda = Mammal { _name: 'Mama Panda', age: 10 } | |
cub = Mammal { _name: 'Cubby', age: 1, parent: panda } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment