aearly / icepick Goto Github PK
View Code? Open in Web Editor NEWUtilities for treating frozen JavaScript objects as persistent immutable collections
License: MIT License
Utilities for treating frozen JavaScript objects as persistent immutable collections
License: MIT License
This will allow for arbitrary updates inside a chain. See #18.
Last tag is 1.3.0: https://github.com/aearly/icepick/releases
See https://github.com/Psykar/test-icepick-uglify
RCA transpiles to ES5 before it attempts to uglify, but seems it's falling over on some ES6 syntax. Installing icepick@<2
does work, and I don't have the time to debug this further right now unfortunately, but the repro is pretty simple.
create-react-app test-icepick-uglify
cd test-icepick-uglify
yarn add icepick
src/App.js
to add an icepick importyarn build
yarn build v0.24.6
$ react-scripts build
Creating an optimized production build...
Failed to compile.
static/js/main.fd1459b7.js from UglifyJs
Unexpected token: operator (>) [./~/icepick/icepick.js:16,0][static/js/main.fd1459b7.js:11521,25]
error Command failed with exit code 1.
Alternatively, clone https://github.com/Psykar/test-icepick-uglify then yarn build
and you'll also see it :)
Could you please add a LICENSE file with the full text of the MIT license and the copyright holder's name? It is needed to pass a legal review. Simply specifying that the license is "MIT" is not sufficient because it's not legally definable what EXACTLY does "MIT" mean.
Thanks a lot!
Obvious mistakes:
//In getIn section
var coll = i.freeze([
{a: 1},
{b: 2}
]);
var result = i.getIn(coll, [1, "b"]); // 2
//In merge section
var defaults = {a: 1, c: {d: 1, e: [1, 2, 3], f: {g: 1}};
var obj = {c: {d: 2, e: [2], f: null};
var result1 = i.merge(defaults, obj); // {a: 1, c: {d: 2, e: [2]}, f: null}
var obj2 = {c: {d: 2}};
var result2 = i.merge(result1, obj2);
assert(result1 === result2); // true
would be neat to have a lodash/fp interface in icepick/fp.
with curried: fn(a, b, c) => fn(b, c, a);
versions of icepick functions.
Docs says that assign
is always returning a new, immutable object
which I believe is not true since #22
Proposed as a shortcut, implemented as follows:
import { updateIn, merge } from 'icepick'
const mergeIn = (dest, path, source, associator) =>
updateIn(dest, path, v => merge(v, source, associator))
Would be willing to implement. I'm not even sure if it's helpful, given how easy (and explicit) it is to construct on the fly. Just a thought.
I use Icepick on React/Redux projects for two main reasons:
Typically, I deep freeze every slice in my Redux store. However, for some data-heavy apps, there's a performance hit for doing so. What would you think of a variant of Icepick (that could be used in production) that provide the same helper functions but skips the freezing?
In the docs, it says seamless-immutable is the most similar to icepick. Its main difference is that it adds more methods to the prototypes of objects
, but I was under the impression that icepick didn't add any methods to the prototypes of objects. If that's the case, we should delete the 'more' from above to make that clear.
I find assocIn
etc to be useful, and sometimes wish similar functions existed for the other functions. Here's a prototype of an at
(because in
is a reserved word) function and chain
method that let you apply any operator to a path:
https://runkit.com/tlrobinson/5dc341aa7f9859001a1b54f4
e.x.
icepick.at(object, ["foo", "bar"]).push(4)
icepick.chain(object)
.at(["foo", "bar"]).push(4)
.at(["new", "object"]).assoc(5)
.at(["new", "array"]).push(6)
.value()
Using process.env.NODE_ENV
like in seamless-immutable
Which is usable in browsers too with Browserify and Webpack.
Would make production builds faster.
hi, I'm from cdnjs. Because your lib is very popular, we want to host it on https://cdnjs.com, can I add icepick.js
to cdnjs directly for browser user? or if it doesn't work, can you also provide browserified icepick.js
in every git tag(released versions) so that we can use git auto-update to add your lib to cdnjs automatically.
thank you very much!
Consider the following snippet, run against Icepick 2.4.0:
var icepick = require("icepick")
const BEFORE = {
first: {
name: "First",
items: [{key: "first-a", value: 12}]
},
second: {
name: "Second",
items: [{key: "second-a", value: 13}]
},
third: {
name: "Third",
items: [{key: "third-a", value: 15}]
}
};
console.log(BEFORE);
const AFTER = icepick.updateIn(BEFORE, ["second", "items"], items => [
...items,
{
key: "second-x",
value: 42
},
]);
console.log(AFTER);
In this case, the output is:
Object
first: Object {name: "First", items: [Object {key: "first-a", value: 12}]}
second: Object {name: "Second", items: [Object {key: "second-a", value: 13}]}
third: Object {name: "Third", items: [Object {key: "third-a", value: 15}]}
Object
third: Object {name: "Third", items: [Object {key: "third-a", value: 15}]}
second: Object {items: [Object {key: "second-a", value: 13}, Object {key: "second-x", value: 42}], name: "Second"}
first: Object {name: "First", items: [Object {key: "first-a", value: 12}]}
Notice that the order of keys has been reversed by this operation (where an item was added to the items
collection of the 2nd value in the map). I realize that maps are inherently unordered, but it might still be useful if this operation didn't change the order.
The package query-string is generating objects that have no prototype by using Object.create(null)
.
I want to deep merge with those objects, but icepick is not thinking they are objects because the isObject
test check for prototype.
import {merge} from 'icepick';
// build object like query-string does
let query = Object.create(null);
query['q'] = 'search-term';
const route = {url: './', query: query};
// prepare action for history
const nextPage = merge(route, {query: {page: 2}});
// what I expect to be the result
assert.same(nextPage, {url: './', query: {q: 'search-term', page: 2}});
Recommended for an alias
i.assoc -> i.set
i.dissoc -> i.unset
i.assocIn -> i.setIn
There seem to be 2 camp on immutable object:
I believe icepick
is in the first camp (as opposed to immutable.js
or seamless-immutable
, which are likely in the 2nd camp).
Am I right in thinking icepick
assume developers will pass its instance directly? Because I see no method to extract mutable data out of it.
Hi Alexander, thank a lot for icepick!
As a great fan of functional programming, I am used to chaining functions like here:
var _ = require("lodash");
// Transform [{name: Kirk, address: {country: Norway, city: Oslo}},...] to [Oslo,..]:
_.chain(crewMembers).map("address").filter({country: "Norway"}).map("city").value()
With icepick this quickly becomes difficult to read (as in old good Lisp) since I have to read it inside-out:
i.map(
i.filter(
i.map(crewMembers, myMakeGetter("address"))
myMakePredicate({country: "Norway"}))
myMakeGetter("city")
It would be great if Icepick supported chaining these operations for example in the same way that lodash does witch chain
... value()
.
Thank you!
weCareAbout()
returns true
for null
, since typeof null === 'object'
.
A .merge of two identical objects that contain an array is returning a new object.
For example:
var a = {foo: []}
var b = {foo: []}
var ab = icepick.merge(a, b)
ab === a // => false
Without a nested array it works as expected:
var a = {foo: {}}
var b = {foo: {}}
var ab = icepick.merge(a, b)
ab === a // => true
Just as dissoc
is the pair to assoc
but removes a key, dissocIn
should be the pair to assocIn
and remove the key at the end of a path (passed as an array).
[].map
, [].filter
, Object.assign
-- anything that returns a collection.
I know it was done on purpose, but having the "main" entrypoint in package.json pointing to ES6 module is unfortunate. It can't be easily integrated into project that targets older browsers. Babel does not process node_modules by default and having exception for just one library pollutes the build script.
Proposal: Keep main entrypoint ES5, use "module" or "jsnext:main" for ES6
package.json
...
"main": "icepick.js", // this is ES5 compatible module
"module": "icepick.mjs" // this is ES6 module
...
The following code fails because it looks like the map and filter exports work differently to the other exports?
There is a following typo in REAMDE.md
:
icepick does not modify the the methods or properties of collections in order to function
I discover this when trying to modify an object with structure like { a: [ {b:1}, {b:2} ] }
.
The best way I can think of to push {b:3}
onto a
array is to:
var arr = I.push(store.a, {b:3});
I.assoc(store, 'a', arr);
Then I realize {b:3}
isn't freezed in the process.
Am I doing this right? Is it by design?
(not that it's a problem, I can certainly I.freeze
the data before I.push
).
Hello,
I wonder whether I should pick seamless-immutable or icepick. They both seem to be doing the same thing, providing utilities for "modifying" deeply frozen data structures. I can see some differences but know too little to be able to really compare them and decide. Could you be so kind and describe the advantages of seamless over icepick and vice versa? Thanks a lot!
PS: I'll ask at the other project as well
Coming from Clojure1. I was surprised that assocIn
and updateIn
does not create the intermediate objects if they are missing. I find that behavior extremely useful when creating complex data structures.
I know the current behavior is documented and the change would be backwards incompatible but since icepick is not at 1.0 yet I wanted to bring this up.
Would it be possible/sensible to add the ability to delete keys?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.