Last active
August 29, 2015 14:13
-
-
Save futpib/ebcab968dc23f7deb5ff to your computer and use it in GitHub Desktop.
Bidirectional map in CoffeeScript (on top of Harmony Map)
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
class WrappedMap | |
# We need a wrapper because you can't just extends Map: | |
# TypeError: Method Map.prototype.set called on incompatible receiver #<BiMap> | |
constructor: -> | |
@_map = new Map arguments... | |
# clone and wrap Map.prototype properties | |
Object.getOwnPropertyNames(Map::).forEach (name) => | |
desc = Object.getOwnPropertyDescriptor Map::, name | |
for key, value of desc | |
if 'function' == typeof value | |
desc[key] = do (method=value) -> -> method.apply @_map, arguments | |
else | |
desc[key] = value | |
unless name of @:: | |
Object.defineProperty @::, name, desc | |
exports.BiMap = class BiMap extends WrappedMap | |
constructor: (iterable) -> | |
super | |
if not @inverse | |
@inverse = new Inverse this | |
@set l, r for [l, r] in iterable if iterable | |
class Inverse extends BiMap | |
constructor: (original) -> | |
@inverse = original # inverse of inverse is the original map | |
super | |
clear: -> | |
WrappedMap::clear.call this | |
WrappedMap::clear.call @inverse | |
delete: (l) -> | |
r = @get l | |
WrappedMap::delete.call this, l | |
WrappedMap::delete.call @inverse, r | |
set: (l, r) -> | |
WrappedMap::set.call this, l, r | |
WrappedMap::set.call @inverse, r, l | |
# try it with $ coffee --nodejs --harmony ~/Downloads/bimap.coffee | |
do testBiMap = -> | |
bm = new BiMap [ | |
[0, 1], | |
['left', 'right'], | |
[left = { left: 0 }, right = { right: 1 }], | |
] | |
console.log bm.get 'left' # 'right' | |
console.log bm.get 'right' # undefined | |
console.log bm.inverse.get 'left' # undefined | |
console.log bm.inverse.get 'right' # 'left' | |
console.log right is (bm.get left) # true | |
console.log right is (bm.inverse.inverse.get left) # true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment