{"_id":"pop-swap","_rev":"48689","name":"pop-swap","description":"Range content change operator for arrays and array-like objects","dist-tags":{"latest":"1.0.0"},"maintainers":[{"name":"kriskowal","email":""}],"time":{"modified":"2021-06-03T10:14:57.000Z","created":"2015-01-27T06:45:44.472Z","1.0.0":"2015-01-27T06:45:44.472Z"},"users":{},"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-swap.git"},"versions":{"1.0.0":{"name":"pop-swap","version":"1.0.0","description":"Range content change operator for arrays and array-like objects","main":"pop-swap.js","scripts":{"test":"jasminum test"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-swap.git"},"keywords":["array","swap","polymorphic","operator"],"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"license":"MIT","bugs":{"url":"https://github.com/kriskowal/pop-swap/issues"},"homepage":"https://github.com/kriskowal/pop-swap","devDependencies":{"jasminum":"^2.0.5"},"gitHead":"b87628e548b91da5d1bdc30cf4f0c1f89d402467","_id":"pop-swap@1.0.0","_shasum":"88b440553e085d0179d32255b09f93aab9890c66","_from":".","_npmVersion":"1.4.21","_npmUser":{"name":"kriskowal","email":"kris.kowal@cixar.com"},"maintainers":[{"name":"kriskowal","email":""}],"dist":{"shasum":"88b440553e085d0179d32255b09f93aab9890c66","size":3462,"noattachment":false,"key":"/pop-swap/-/pop-swap-1.0.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/pop-swap/download/pop-swap-1.0.0.tgz"},"directories":{},"publish_time":1422341144472,"_cnpm_publish_time":1422341144472,"_hasShrinkwrap":false}},"readme":"\n# Swap\n\nAt first blush, every method of an array that modifies its content can be\nimplemented in terms of `splice`.\n\n```\npop(): splice(length - 1, 1)[0]\npush(...values): splice(length, 0, ...values)\nshift(): splice(0, 1)[0]\nunshift(...values): splice(0, 0, ...values)\nclear(): splice(0, length)\n```\n\nSplice always returns an array of the values removed, which is not useful for\nmodeling all of these methods.\n\nSplice, at first blush, is also the appropriate operator to apply operational\ntransforms. An operational transform either adds values at a position, or\nremoves values from a position.\nFor this purpose, splice has some disadvantages.\n\n1.  For sparse arrays, splice cannot be used to add new values beyond the end of\n    the array; splice shifts the change to the end of the arrray.\n2.  Becuase splice is variadic, accepting any number of arguments, those\n    arguments get projected onto the stack.\n    For a sufficiently large change, splice will throw a stack overflow\n    RangeError.\n\n## Swap rather than Splice\n\nSwap has no return value and accepts an optional array of values to add.\nIt is well-suited as the underlying operator for operational transforms since it\nwastes nothing for addition only and removal only, can add sparce arrays beyond\nthe end of a sparse array, and does not deal with the arguments object.\n\n```js\nvar swap = require(\"pop-swap/swap\");\nswap(array, index, length, values?);\n```\n\nSwap accepts an array, an index, the number of values to to remove after that\nindex, then the values to add after that index.\nThe added values are optional.\nThe array or array of values to add may be sparse.\nSwap returns nothing.\n\nIt is also suitable for implementing the remaining array methods.\nOf course, this is only really useful if you need to implement all of those\narray methods in a way that channels through swap.\nThis is the story behind [observable arrays][Collections] in the Montage\nCollections package.\n\n[Collections]: https://github.com/montagejs/collections\n\n```\nsplice(index, minus, ...values):\n    index = Math.min(index, this.length);\n    var result = this.slice(index, index + minus);\n    swap(index, minus, values);\n    return result;\npop():\n    var last = this[this.length - 1];\n    swap(this.length - 1, 1);\n    return last;\npush(...values)\n    swap(this.length, 0, values);\nshift():\n    var first = this[0];\n    swap(0, 1);\n    return first;\nunshift(...values):\n    swap(0, 0, values);\nclear();\n    swap(0, this.length);\n```\n\n## Polymoprhic operators\n\nA well planned system of objects is beautiful: a system where every meaningful\nmethod for an object has been anticipated in the design.\nInevitably, another layer of architecture introduces a new concept and with it\nthe temptation to monkey-patch, dunk-punch, or otherwise cover up the omission.\nBut reaching backward in time, up through the layers of architectures doesn't\nalways componse well, when different leaves introduce concepts of the same name\nbut distinct behavior.\n\nA polymorphic operator is a function that accepts as its first argument an\nobject and varies its behavior depending on its type.\nSuch an operator has the benefit of covering for the types from higher layers of\narchitecture, but defers to the eponymous method name of types yet to be\ndefined.\n\n```js\nvar swap = require(\"pop-swap\");\nvar array = ['Hello', 'World!'];\nswap(array, 0, 1, ['Farewell']);\n\nvar proxy = {\n    array: ['Hello', 'World!'],\n    swap: function (start, minusLength, plus) {\n        swap(this.array, start, minusLength, plus);\n    }\n};\nswap(proxy, 0, 1, ['Farewell']);\n```\n\n","_attachments":{},"homepage":"https://github.com/kriskowal/pop-swap","bugs":{"url":"https://github.com/kriskowal/pop-swap/issues"},"license":"MIT"}