Skip to content

Instantly share code, notes, and snippets.

@futpib
Last active August 29, 2015 14:13
Show Gist options
  • Save futpib/ebcab968dc23f7deb5ff to your computer and use it in GitHub Desktop.
Save futpib/ebcab968dc23f7deb5ff to your computer and use it in GitHub Desktop.
Bidirectional map in CoffeeScript (on top of Harmony Map)
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