im
Immutable collection datatypes
15.1.0
31M downloads/mo
#1641 most downloaded on crates.io
bodil/im-rs
What this package is like to depend on
Last release 4 years ago
no release in 18 months
Ships unpredictably
gaps range from 2 weeks to 2.0 years
Some releases are documented
notes for 17 of 32 stable releases
4 versions withdrawn
withdrawn after publishing
9 years old
36 releases · first in 2017
0 releases in the last 12 months
see the full history below
Release timeline
36 releases · Apr 2017 to Apr 2022Releases
latest 36-
15.1.029 Apr 2022Release notes
Open source →Added
-
HashSetnow implementsFrom<Vector<A>>andFrom<&Vector<A>> where A: Clone. -
Fixed
-
Fixed a long standing crash bug in
OrdMap/OrdSet. (#154, #143, #152, #124) -
The
unionmethod on maps/sets will now prefer to mutate the larger set (which leads to less work) rather than the first set. (#163) -
Ensure
TreeFocusonly implementsSend/Syncwhen the underlying type does. (#157, #158) -
There was an issue where nodes in very large
OrdMaps could overflow when removing an element and cause a panic, which has now been fixed. (#141)
Release notes
Open source →Added
HashSetnow implementsFrom<Vector<A>>andFrom<&Vector<A>> where A: Clone.
Fixed
- Fixed a long standing crash bug in
OrdMap/OrdSet. (#154, #143, #152, #124) - The
unionmethod on maps/sets will now prefer to mutate the larger set (which leads to less work) rather than the first set. (#163) - Ensure
TreeFocusonly implementsSend/Syncwhen the underlying type does. (#157, #158) - There was an issue where nodes in very large
OrdMaps could overflow when removing an element and cause a panic, which has now been fixed. (#141) - Assorted doc cleanup. (#150, #173, #186, #194)
-
-
15.0.015 May 2020Release notes
Open source →Changed
- Map iterators now return
(&K, &V)and(&K, &mut V)respectively, to be consistent withstd::collections's API.DiffIterforOrdMaphas also changed in the same manner. (#121)
Removed
- The
poolfeature flag has been removed from theimversion of the crate, asrefpoolno longer supports threadsafe pools. HashSet::iter_mut()has been removed, because if you modify the hashed values in a hash set, you break the hash set.
Added
- The
poolfeature flag was missing from theim-rcversion of the crate, which is the version where it's actually useful. It's been added now. DiffIternow has aDebugimplementation.- There is now a
Vector::is_inline()method to determine whether aVectoris currently inlined. (#129)
Fixed
- A smarter implementation of the sorting algorithm for
Vectorhas improved the performance ofVector::sortby approximately 2x. (#126)
Release notes
Open source →Changed
- Map iterators now return
(&K, &V)and(&K, &mut V)respectively, to be consistent withstd::collections's API.DiffIterforOrdMaphas also changed in the same manner. (#121)
Removed
- The
poolfeature flag has been removed from theimversion of the crate, asrefpoolno longer supports threadsafe pools. HashSet::iter_mut()has been removed, because if you modify the hashed values in a hash set, you break the hash set.
Added
- The
poolfeature flag was missing from theim-rcversion of the crate, which is the version where it's actually useful. It's been added now. DiffIternow has aDebugimplementation.- There is now a
Vector::is_inline()method to determine whether aVectoris currently inlined. (#129)
Fixed
- A smarter implementation of the sorting algorithm for
Vectorhas improved the performance ofVector::sortby approximately 2x. (#126)
- Map iterators now return
-
14.3.003 Mar 2020Release notes
Open source →Changed
propteststrategies have been moved toim::proptest. The previous locations of the strategies (im::vector::proptestetc) are still available, but have been deprecated.
Added
OrdSetandOrdMapnow haveget_prevandget_nextmethods (with equivalentget_prev_mutandget_next_mutmethods forOrdMap) which will return the closest key match to the requested key in the specified direction if the key isn't in the set. (#95)- The
retainmethod, inexplicably missing fromHashMapbut notHashSet, has been added. (#120) - The
get_mutmethod onOrdMapwas, equally inexplicably, private. It has now been made public.
Release notes
Open source →Changed
propteststrategies have been moved toim::proptest. The previous locations of the strategies (im::vector::proptestetc) are still available, but have been deprecated.
Added
OrdSetandOrdMapnow haveget_prevandget_nextmethods (with equivalentget_prev_mutandget_next_mutmethods forOrdMap) which will return the closest key match to the requested key in the specified direction if the key isn't in the set. (#95)- The
retainmethod, inexplicably missing fromHashMapbut notHashSet, has been added. (#120) - The
get_mutmethod onOrdMapwas, equally inexplicably, private. It has now been made public.
-
14.2.017 Jan 2020Release notes
Open source →[14.2.0] - 2020-01-17
Added
- Both map types now have the
get_key_value()method, corresponding to the equivalent additions to the standard library. - The
ptr_eqmethod has been added to all data types, allowing you to test whether two values refer to the same content in memory, by testing for pointer equality. (#117) HashMaphad lost itsArbitraryimplementation for thequickcheckfeature flag. It's now been restored. (#118)- Implementations for
Arbitraryfrom thearbitrarycrate have been added behind thearbitraryfeature flag.
Fixed
- Fixed a bug when reversing a consuming iterator over a
Vectorby replacing the consuming iterator with a much simpler and slightly more efficient version. (#116)
Release notes
Open source →Added
- Both map types now have the
get_key_value()method, corresponding to the equivalent additions to the standard library. - The
ptr_eqmethod has been added to all data types, allowing you to test whether two values refer to the same content in memory, by testing for pointer equality. (#117) HashMaphad lost itsArbitraryimplementation for thequickcheckfeature flag. It's now been restored. (#118)- Implementations for
Arbitraryfrom thearbitrarycrate have been added behind thearbitraryfeature flag.
Fixed
- Fixed a bug when reversing a consuming iterator over a
Vectorby replacing the consuming iterator with a much simpler and slightly more efficient version. (#116)
- Both map types now have the
-
14.1.016 Dec 2019Release notes
Open source →Added
- If you enable the
poolfeature flag, im now supports constructing data types usingrefpoolto speed up chunk allocation. The performance boost will vary between use cases and operating systems, but generally at least a 10% speedup can be expected when constructing a data type from an iterator, and the more complex an operation is, the more likely it is to benefit from being able to quickly reallocate chunks. Note that in order to use this feature, you have to construct your data types using thewith_pool(&pool)constructor, it's not enough just to enable the feature flag.
Release notes
Open source →Added
- If you enable the
poolfeature flag, im now supports constructing data types usingrefpoolto speed up chunk allocation. The performance boost will vary between use cases and operating systems, but generally at least a 10% speedup can be expected when constructing a data type from an iterator, and the more complex an operation is, the more likely it is to benefit from being able to quickly reallocate chunks. Note that in order to use this feature, you have to construct your data types using thewith_pool(&pool)constructor, it's not enough just to enable the feature flag.
- If you enable the
-
14.0.019 Nov 2019Release notes
Open source →Changed
- As
sized-chunksnow requires a slightly more recent version ofrustcto compile, specifically version 1.36.0, so doesim. This is a breaking change, but will of course only affect your code if you're using an olderrustc.
Fixed
Release notes
Open source →Changed
- As
sized-chunksnow requires a slightly more recent version ofrustcto compile, specifically version 1.36.0, so doesim. This is a breaking change, but will of course only affect your code if you're using an olderrustc.
Fixed
- Fixed a quadratic time worst case scenario in the quicksort implementation for
Vector. (#101) - Fixed an edge case bug when splitting and joining large
Vectors. (#105, #107)
- As
-
13.0.018 May 2019Release notes
Open source →The minimum supported Rust version is now 1.34.0.
Changed
im::iter::unfoldnow gives you the owned state value rather than an immutable reference to it, which makes it a little more useful.
Removed
- The deprecated
singletonconstructors have been removed. Please useunitinstead. - The deprecated methods
Vector::chunksandVector::chunks_muthave been removed in favour ofVector::leavesandVector::leaves_mutrespectively. (#50) - The deprecated reference to
sized-chunkshas been removed. If you need it, please use thesized-chunkscrate directly. im::iter::unfold_muthas been removed, as there's no meaningful difference between it and rust-std 1.34.0'sstd::iter::from_fnwith a captured state variable.
Fixed
Vectornow usessized_chunks::InlineArrayinstead of anEmptyenum case to avoid allocation at very small sizes, letting you store a handful of elements on the stack before needing to grow into a full chunk. This has a beneficial effect on performance as well, as there's no pointer into the heap to dereference, making it faster thanstd::vec::Vecin this configuration.- Some complexity timings have been added and corrected. (#87)
OrdSet::is_subset(&self, other)now returns immediately whenselfis larger thanotherand thus could not possibly be a subset of it. (#87)
Release notes
Open source →The minimum supported Rust version is now 1.34.0.
Changed
im::iter::unfoldnow gives you the owned state value rather than an immutable reference to it, which makes it a little more useful.
Removed
- The deprecated
singletonconstructors have been removed. Please useunitinstead. - The deprecated methods
Vector::chunksandVector::chunks_muthave been removed in favour ofVector::leavesandVector::leaves_mutrespectively. (#50) - The deprecated reference to
sized-chunkshas been removed. If you need it, please use thesized-chunkscrate directly. im::iter::unfold_muthas been removed, as there's no meaningful difference between it and rust-std 1.34.0'sstd::iter::from_fnwith a captured state variable.
Fixed
Vectornow usessized_chunks::InlineArrayinstead of anEmptyenum case to avoid allocation at very small sizes, letting you store a handful of elements on the stack before needing to grow into a full chunk. This has a beneficial effect on performance as well, as there's no pointer into the heap to dereference, making it faster thanstd::vec::Vecin this configuration.- Some complexity timings have been added and corrected. (#87)
OrdSet::is_subset(&self, other)now returns immediately whenselfis larger thanotherand thus could not possibly be a subset of it. (#87)
-
12.3.408 Apr 2019Release notes
Open source →Changed
Cloneconstraints have been further relaxed on maps and sets, so that you can now lookup and iterate over them without requiring aCloneconstraint (though you do still needCloneto actually insert data into them to lookup or iterate over). (#81)
Fixed
Release notes
Open source →Changed
Cloneconstraints have been further relaxed on maps and sets, so that you can now lookup and iterate over them without requiring aCloneconstraint (though you do still needCloneto actually insert data into them to lookup or iterate over). (#81)
Fixed
- Enforces the latest bugfix release of sized-chunks. (#78)
- Another edge case bugfix to
Vector's size table handling. (#79)
-
12.3.311 Mar 2019Release notes
Open source →Fixed
- A number of issues were fixed where
Vector's size table would get out of sync with the node structure if exercised too much and cause erroneous behaviour. (#72, #74) - Comprehensive generative tests were added to test all data structures through more unexpected code paths.
- A number of issues were fixed where
-
12.3.205 Mar 2019Release notes
Open source →Changed
Cloneconstraints on all data structures, as well as relevant constraints on maps and sets, have been relaxed where possible, so that you can now construct empty instances and call most query methods without requiring values implementCloneetc. (#63)
Fixed
Release notes
Open source →Changed
Cloneconstraints on all data structures, as well as relevant constraints on maps and sets, have been relaxed where possible, so that you can now construct empty instances and call most query methods without requiring values implementCloneetc. (#63)
Fixed
- Constructing an empty
Vectorwill not allocate any heap memory, instead deferring allocation until you perform an operation that would increase its length. (#65) - Some bugs arising when using
Vector::appendrepeatedly were fixed. (#67, #70)
-
12.3.119 Feb 2019Release notes
Open source →Changed
- Unsafe chunks have been separated out into the
sized-chunkscrate, which is now a dependency ofim.
- Unsafe chunks have been separated out into the
-
12.3.015 Jan 2019Release notes
Open source →Added
singletonmethods have been deprecated and renamed tounit.Vector::chunksandVector::chunks_muthave been deprecated and renamed toleavesandleaves_mutto avoid confusion withVec::chunks. (#50)
Fixed
- Fixed an issue where the
HashMapdraining iterator might access uninitialised memory leading to undefined behaviour. (#60) - Fixed multiple issues in
Vector::split_offandVector::appendthat would cause lookup errors and unexpectedly unbalanced trees. (#55).
-
12.2.012 Oct 2018 withdrawnRelease notes
Open source →Added
OrdMapandOrdSetnow have arange()method which makes an iterator over a bounded subset of the values. The improved iterator implementation is also considerably more efficient than the previous (about an order of magnitude faster for nontrivial data sets).iter()has been updated to take advantage of this, and is now just an alias forrange(..). (#27)FocusMutnow has anunmutmethod to turn it into an immutableFocus, releasing its exclusive hold on the underlyingVector.Focusnow implementsClone.
-
12.1.025 Sep 2018 withdrawnRelease notes
Open source →Added
- Maps and sets now have the
clearmethod just likeVector. (#46)
Changed
- Single chunk
Vectors are no longer allocated directly on the stack, meaning that they're now comparable in performance tostd::vec::Vecrather than slightly faster, but they also won't eat up your stack space quite as quickly, and they'll clone without copying and share structure with clones as you'd expect.
- Maps and sets now have the
-
12.0.030 Aug 2018 withdrawnRelease notes
Open source →Starting with this release, the
arcflag is gone, in favour of publishingimas two separate crates:im(usingArc) andim-rc(usingRc). They're identical (and built from the same code), except thatimis thread safe andim-rcis a little bit more performant.This is a major release as a consequence, but there should be no breaking code changes other than the new default choice of reference counter.
Added
- The
Chunkdatatype that's used to buildVectorandOrdMaphas been exposed and made generally usable. It's somewhere between aGenericArrayand a ring buffer, offers O(1)* push in either direction, and is generally hyperoptimised for its purpose of serving as nodes for Bagwell tries, but it's also a powered up version ofGenericArraythat might be useful to others, hence the public API. Vectornow hasFocusandFocusMutAPIs for caching index lookups, yielding huge performance gains when performing multiple adjacent index lookups.Vector::iterhas been reimplemented using this API, and is now much simpler and about twice as fast as a result, andVector::iter_mutnow runs nearly an order of magnitude faster. Likewise,Vector::sortandVector::retainare now usingFocusMutand run considerably faster as a result.FocusandFocusMutcan also be used as stand ins for subslices through thenarrowandsplit_atmethods. You can also iterate over foci, making this the most efficient way to iterate over a subset of aVector.Vectornow implements Rayon's parallel iterators behind therayonfeature flag.
Changed
- As
std::ops::RangeBoundsis now stabilised in Rust 1.28, theVector::slicemethod is now unconditionally available on the stable channel. - Union/difference/intersection/is_submap methods on
HashMapandOrdMapthat take functions now takeFnMutinstead ofFn. This should not affect any existing code. (#34) Vector::split_offcan now take an index equal to the length of the vector, yielding an empty vector as the split result. (#33)Vector::setnow returns the replaced value.
Fixed
Vectoris now represented as a single inline chunk until it grows larger than the chunk size, making it even faster thanVecat small sizes, thoughclonecould now be slower if the clone is expensive (it's still absurdly fast forA: Copy).
- The
-
11.0.230 Aug 2018 withdrawnNothing published for this version
-
11.0.123 Jul 2018Release notes
Open source →Fixed
- Various performance improvements, amounting to a 5-10% speedup for both kinds of map/set.
- Fixed an edge case bug in
sort::quicksort.
-
11.0.010 Jul 2018Release notes
Open source →Changed
This is a major release with many breaking changes, and is intended to stabilise the API more than to denote that the rewrite is now production ready. You should expect future releases with significant performance improvements as well as additional APIs, but there should be no further major release with breaking changes in the immediate future, barring very serious unforeseen issues.
Specifically, you should expect imminent minor releases with performance improvements for
VectorandOrdMap, for which I have a number of known optimisations that remain unimplemented.No More
ArcAll data structures have been reworked to take values of
A: Cloneinstead ofArc<A>, meaning that there's less performance overhead (as well as mental overhead) when using values that clone cheaply. The performance gain when values areA: Copyis a factor of two or more. It's expected that users should wrap values inArcthemselves when using values which are expensive to clone.Data structures still use reference counters internally to reference nodes, but values are stored directly in the nodes with no further indirection. This is also good for cache locality.
Data structures now use
Rcinstead ofArcby default to do reference counting. If you need a thread safe version that implementsSendandSync, you can enable thearcfeature on the package to compile withArcinstead.std::collectionsCompatible APIThe API has been reworked to align more closely with
std::collections, favouring mutable operations by default, so that operations that were previously suffixed with_mutare now the standard operations, and immutable operations which return a modified copy have been given different names altogether. In short, all your code using previous versions of this library will no longer work, and if it was relying heavily on immutable operations, it's recommended that you rewrite it to be mutable by preference, but you should generally be able to make it work again by using the new method names for the immutable operations.Here is a list of the most notable changed method names for maps and sets:
Previous immutable Current immutable Previous mutable Current mutable insertupdateinsert_mutinsertremovewithoutremove_mutremovepopextractpop_mutremoveYou should expect to be able to rewrite code using
std::collections::HashMapandstd::collections::BTreeMapwith minimal or no changes usingim::HashMapandim::OrdMaprespectively.Vectorhas been completely rewritten and has an API that aligns closely withstd::collections::VecDeque, with very few immutable equivalents. It's expected that you should useVector::clone()to take a snapshot when you need it rather than cause an implicit clone for each operation. (It's still O(1) and practically instant.)I'm considering adding back some of the immutable operations if I can come up with good names for them, but for now, just
cloneit if you need it.RRB Vector
Vectoris now implemented as an RRB tree with smart head/tail chunking, obsoleting the previous Hickey trie implementation.RRB trees have generally similar performance characteristics to the Hickey trie, with the added benefit of having O(log n) splitting and concatenation.
Operation RRB tree Hickey trie Vec VecDeque Push front O(1)* O(log n) O(n) O(1)* Push back O(1)* O(log n) O(1)* O(1)* Pop front O(1)* O(log n) O(n) O(1)* Pop back O(1)* O(log n) O(1) O(1)* Lookup by index O(log n) O(log n) O(1) O(1) Split O(log n) O(log n) O(n) O(n) Join O(log n) O(n) O(n) O(n) (Please note that the timings above are for the
imversion of the Hickey trie, based on the Immutable.js implementation, which performs better than the original Clojure version on splits and push/pop front, but worse on push/pop back).The RRB tree is the most generally efficient list like data structure currently known, to my knowledge, but obviously it does not and cannot perform as well as a simple
Vecon certain operations. It makes up for that by having no operations you need to worry about the performance complexity of: nothing you can do to an RRB tree is going to be more expensive than just iterating over it. For larger data sets, being able to concatenate (and, by extension, insert and remove at arbitrary locations) several orders of magnitude faster thanVeccould also be considered a selling point.No More
CatListAndConsListCatListhas been superseded byVector, andConsListwas generally not very useful except in the more peculiar edge cases where memory consumption matters more than performance, and keeping it in line with current API changes wasn't practical.No More Funny Words
Though it breaks my heart, words like
cons,snoc,car,cdrandunconsare no longer used in theimAPI, to facilitiate closer alignment withstd::collections. Even thehead/tailpair is gone, thoughheadandlastremain as aliases forfrontandback. -
10.2.015 Apr 2018Release notes
Open source →Added
- Map/set methods which accept references to keys will now also take any value that's borrowable
to the key's type, ie. it will take a reference to a type
Borrowablewhere the key implementsBorrow<Borrowable>. This is particularly handy for types such asStringbecause you can now pass&strto key lookups instead of&String. So, instead of the incredibly cumbersomemap.get(&"foo".to_string())you can just domap.get("foo")when looking up a mapping for a string literal.
- Map/set methods which accept references to keys will now also take any value that's borrowable
to the key's type, ie. it will take a reference to a type
-
10.1.012 Apr 2018Release notes
Open source →Added
Vector,OrdMapandHashMapnow implementIndexandIndexMut, allowing for syntax likemap[key] = value.- Added
cons,snoc,unconsandunsnocaliases where they were missing. - Everything now implements
SumandExtendwhere possible.
Changed
- Generalised
OrdMap/OrdSet's internal nodes soOrdSetnow only needs to store pointers to its values, not pairs of pointers to value andUnit. This has causedOrdMap/Set's type constraints to tighten somewhat - in particular, iteration over maps/sets whose keys don't implementOrdis no longer possible, but as you would only have been able to create empty instances of these, no sensible code should break because of this. HashMap/HashSetnow also cannot be iterated over unless they implementHash + Eq, with the same note as above.- Constraints on single operations that take closures on
HashMapandOrdMaphave been relaxed fromFntoFnOnce. (Fixes #7.)
Fixed
- Hashes are now stored in
HashMaps along with their associated values, removing the need to recompute the hash when a value is reordered inside the tree.
-
10.0.006 Apr 2018Release notes
Open source →Added
This is the first release to be considered reasonably stable. No changelog has been kept until now.
-
9.0.007 Feb 2018Nothing published for this version
-
8.0.007 Jan 2018Nothing published for this version
-
7.1.007 Jan 2018Nothing published for this version
-
7.0.027 Sep 2017Nothing published for this version
-
6.0.001 Aug 2017Nothing published for this version
-
5.0.004 Jul 2017Nothing published for this version
-
4.1.002 Jul 2017Nothing published for this version
-
4.0.126 Jun 2017Nothing published for this version
-
4.0.026 Jun 2017Nothing published for this version
-
3.0.023 Jun 2017Nothing published for this version
-
2.0.317 Apr 2017Nothing published for this version
-
2.0.217 Apr 2017Nothing published for this version
-
2.0.117 Apr 2017Nothing published for this version
-
2.0.017 Apr 2017Nothing published for this version
-
1.0.017 Apr 2017Nothing published for this version