Hamster collections are immutable. Whenever you modify a Hamster
collection, the original is preserved and a modified copy is returned. This
makes them inherently thread-safe and shareable. At the same time, they remain
CPU and memory-efficient by sharing between copies.

While Hamster collections are immutable, you can still mutate objects stored
in them. We recommend that you don't do this, unless you are sure you know
what you are doing. Hamster collections are thread-safe and can be freely
shared between threads, but you are responsible for making sure that the
objects stored in them are used in a thread-safe manner.

Hamster collections are almost always closed under a given operation. That is,
whereas Ruby's collection methods always return arrays, Hamster collections
will return an instance of the same class wherever possible.

Like most Hamster methods, the set-theoretic methods #union, #intersection, #difference, and #exclusion (aliased as #|, #&, #-, and #^) all work with regular Ruby collections, or indeed any Enumerable object. So just like all the other Hamster collections, Hamster::Set can easily be used in combination with "ordinary" Ruby code.

Hamster.interval(from, to) creates a lazy list
equivalent to a list containing all the values between
from and to without actually creating a list that big.

Hamster.stream { ... } allows you to creates infinite
lists. Each time a new value is required, the supplied
block is called. To generate a list of integers you
could do:

count =0Hamster.stream { count +=1 }

Hamster.repeat(x) creates an infinite list with x the
value for every element.

Hamster.replicate(n, x) creates a list of size n with
x the value for every element.

Hamster.iterate(x) { |x| ... } creates an infinite
list where the first item is calculated by applying the
block on the initial argument, the second item by applying
the function on the previous result and so on. For
example, a simpler way to generate a list of integers
would be:

Hamster.iterate(1) { |i| i +1 }

or even more succinctly:

Hamster.iterate(1, &:next)

You also get Enumerable#to_list so you can slowly
transition from built-in collection classes to Hamster.

And finally, you get IO#to_list allowing you to lazily
process huge files. For example, imagine the following
code to process a 100MB file:

How many times/how long did you read the code before it became
apparent what the code actually did? Now compare that to the
following:

File.open("my_100_mb_file.txt") do |file|
file.map(&:chomp).map(&:downcase).map(&:reverse).take(10)
end

Unfortunately, though the second example reads nicely, it
takes around 13 seconds to run (compared with 0.033 seconds
for the first) even though we're only interested in the first
10 lines! However, using a little #to_list magic, we
can get the running time back down to 0.033 seconds!

File.open("my_100_mb_file.txt") do |file|
file.to_list.map(&:chomp).map(&:downcase).map(&:reverse).take(10)
end

How is this even possible? It's possible because IO#to_list
creates a lazy list whereby each line is only ever read and
processed as needed, in effect converting it to the first
example without all the syntactic, imperative, noise.

Code of Conduct

As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.

Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.

Licensing

Copyright (c) 2009-2014 Simon Harris

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.