<commit_before>Hamster
=======

  - [![Version](https://badge.fury.io/rb/hamster.png)](https://rubygems.org/gems/hamster)
  - [![Climate](https://codeclimate.com/github/hamstergem/hamster.png)](https://codeclimate.com/github/hamstergem/hamster)
  - [![Build](http://img.shields.io/travis-ci/hamstergem/hamster.png)](https://travis-ci.org/hamstergem/hamster)
  - [![Dependencies](https://gemnasium.com/hamstergem/hamster.png)](https://gemnasium.com/hamstergem/hamster)
  - [![License](http://img.shields.io/license/MIT.png?color=green)](http://opensource.org/licenses/MIT)

Efficient, immutable, and thread-safe collection classes for Ruby.

Hamster provides 6 [Persistent Data
Structures][PDS]: [`Hash`][HASH-DOC], [`Vector`][VECTOR-DOC], [`Set`][SET-DOC], [`SortedSet`][SORTED-SET-DOC], [`List`][LIST-DOC], and [`Deque`][DEQUE-DOC] (which works as an immutable queue or stack).

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.

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.

And lastly, Hamster lists are lazy, making it possible to (among other things)
process "infinitely large" lists.

Where possible, Hamster collections offer an interface compatible with Ruby's
built-in `Hash`, `Array`, and `Enumerable`, to ease code migration.

[PDS]: http://en.wikipedia.org/wiki/Persistent_data_structure
[HASH-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Hash
[SET-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Set
[VECTOR-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Vector
[LIST-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/List
[SORTED-SET-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/SortedSet
[DEQUE-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Deque


Using
=====

To make the collection classes available in your code:

``` ruby
require "hamster"
```

Or if you prefer to only pull in certain collection types:

``` ruby
require "hamster/hash"
require "hamster/vector"
require "hamster/set"
require "hamster/sorted_set"
require "hamster/list"
require "hamster/deque"
```

**Hash**

Constructing a Hamster `Hash` is almost as simple as a
regular one:

``` ruby
person = Hamster.hash(:name => "Simon", :gender => :male)
  # => {:name => "Simon", :gender => :male}
```

Accessing the contents will be familiar to you:

``` ruby
person[:name]
  # => "Simon"
person.get(:gender)
  # => :male
```

Updating the contents is a little different than you are
used to:

``` ruby
friend = person.put(:name, "James")
  # => {:name => "James", :gender => :male}
person
  # => {:name => "Simon", :gender => :male}
friend[:name]
  # => "James"
person[:name]
  # => "Simon"
```

As you can see, updating the hash returned a copy leaving
the original intact. Similarly, deleting a key returns
yet another copy:

``` ruby
male = person.delete(:name)
  # => {:gender => :male}
person
  # => {:name => "Simon", :gender => :male}
male.key?(:name)
  # => false
person.key?(:name)
  # => true
```

Hamster's `Hash` doesn't provide an assignment (`Hash#[]=`)
method. The reason for this is simple yet irritating: Ruby
assignment methods always return the assigned value, no
matter what the method itself returns. For example:

``` ruby
counters = Hamster.hash(:odds => 0, :evens => 0)
counters[:odds] += 1
  # => 1
```

Because of this, the returned copy would be lost, thus
making the construct useless. Instead `Hash#put` accepts a
block instead of an explicit value so we can still do
something similar:

``` ruby
counters.put(:odds) { |value| value + 1 }
  # => {:odds => 1, :evens => 0}
```

Or more succinctly:

``` ruby
counters.put(:odds, &:next)
  # => {:odds => 1, :evens => 0}
```

**List**

Hamster `List`s have a head -- the value of the item at the
head of the list -- and a tail -- containing the remaining
items:

``` ruby
list = Hamster.list(1, 2, 3)
list.head
  # => 1
list.tail
  # => Hamster.list(2, 3)
```

To add to a list, you use `List#cons`:

``` ruby
original = Hamster.list(1, 2, 3)
copy = original.cons(0)
  # => Hamster.list(0, 1, 2, 3)
```

Notice how modifying a list actually returns a new list.
That's because Hamster `List` are immutable. Thankfully,
just like other Hamster collections, they're also very
efficient at making copies!

`List` is, where possible, lazy. That is, it tries to defer
processing items until absolutely necessary. For example,
given a crude function to detect prime numbers:

``` ruby
def prime?(number)
  2.upto(Math.sqrt(number).round) do |integer|
    return false if (number % integer).zero?
  end
  true<commit_msg>Worked on README docs for Hash, Vector, List<commit_after>Hamster
=======

  - [![Version](https://badge.fury.io/rb/hamster.png)](https://rubygems.org/gems/hamster)
  - [![Climate](https://codeclimate.com/github/hamstergem/hamster.png)](https://codeclimate.com/github/hamstergem/hamster)
  - [![Build](http://img.shields.io/travis-ci/hamstergem/hamster.png)](https://travis-ci.org/hamstergem/hamster)
  - [![Dependencies](https://gemnasium.com/hamstergem/hamster.png)](https://gemnasium.com/hamstergem/hamster)
  - [![License](http://img.shields.io/license/MIT.png?color=green)](http://opensource.org/licenses/MIT)

Efficient, immutable, and thread-safe collection classes for Ruby.

Hamster provides 6 [Persistent Data
Structures][PDS]: [`Hash`][HASH-DOC], [`Vector`][VECTOR-DOC], [`Set`][SET-DOC], [`SortedSet`][SORTED-SET-DOC], [`List`][LIST-DOC], and [`Deque`][DEQUE-DOC] (which works as an immutable queue or stack).

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.

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.

And lastly, Hamster lists are lazy, making it possible to (among other things)
process "infinitely large" lists.

Where possible, Hamster collections offer an interface compatible with Ruby's
built-in `Hash`, `Array`, and `Enumerable`, to ease code migration.

[PDS]: http://en.wikipedia.org/wiki/Persistent_data_structure
[HASH-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Hash
[SET-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Set
[VECTOR-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Vector
[LIST-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/List
[SORTED-SET-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/SortedSet
[DEQUE-DOC]: http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Deque


Using
=====

To make the collection classes available in your code:

``` ruby
require "hamster"
```

Or if you prefer to only pull in certain collection types:

``` ruby
require "hamster/hash"
require "hamster/vector"
require "hamster/set"
require "hamster/sorted_set"
require "hamster/list"
require "hamster/deque"
```

<h2>Hash <span style="font-size:0.7em">(<a href="http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Hash">API Documentation</a>)</span></h2>

Constructing a Hamster `Hash` is almost as simple as a regular one:

``` ruby
person = Hamster.hash(:name => "Simon", :gender => :male) # => Hamster::Hash[:name => "Simon", :gender => :male]
```

Accessing the contents will be familiar to you:

``` ruby
person[:name]                       # => "Simon"
person.get(:gender)                 # => :male
```

Updating the contents is a little different than you are used to:

``` ruby
friend = person.put(:name, "James") # => Hamster::Hash[:name => "James", :gender => :male]
person                              # => Hamster::Hash[:name => "Simon", :gender => :male]
friend[:name]                       # => "James"
person[:name]                       # => "Simon"
```

As you can see, updating the hash returned a copy leaving
the original intact. Similarly, deleting a key returns
yet another copy:

``` ruby
male = person.delete(:name)         # => Hamster::Hash[:gender => :male]
person                              # => Hamster::Hash[:name => "Simon", :gender => :male]
male.key?(:name)                    # => false
person.key?(:name)                  # => true
```

Since it is immutable, Hamster's `Hash` doesn't provide an assignment
(`Hash#[]=`) method. However, `Hash#put` can accept a block which
transforms the value associated with a given key:

``` ruby
counters.put(:odds) { |value| value + 1 } # => Hamster::Hash[:odds => 1, :evens => 0]
```

Or more succinctly:

``` ruby
counters.put(:odds, &:next)         # => {:odds => 1, :evens => 0}
```

This is just the beginning; see the [API documentation][HASH-DOC] for details on all `Hash` methods.


<h2>Vector <span style="font-size:0.7em">(<a href="http://rubydoc.info/github/hamstergem/hamster/master/Hamster/Vector">API Documentation</a>)</span></h2>

A `Vector` is an integer-indexed collection much like an immutable `Array`. Examples:

``` ruby
vector = Hamster.vector(1, 2, 3, 4) # => Hamster::Vector[1, 2, 3, 4]
vector[0]                           # => 1
vector[-1]                          # => 4
vector.set(1, :a)                   # => Hamster::Vector[1, :a, 3, 4]
vector.add(:b)                      # => Hamster::Vector[1, 2, 3, 4, :b]
vector.insert(2, :a, :b)            # => Hamster::Vector[1, 2, :a, :b, 3, 4]
vector.delete_at(0)                 # => Hamster::Vector[2, 3, 4]
```

Other `Array`-like methods like `#select`, `#map`, `#shuffle`, `#uniq`, `#reverse`,
`#rotate`, `#flatten`, `#sort`, `#sort_by`, `#take`, `#drop`, `#take_while`,
`#drop_while`, `#fill`, `#product`, and `#transpose` are also supported. See the
[API documentation][VECTOR-DOC] for details on all `Vector` methods.


<h2>List <span style="font-size:0.7em">(<a href="http://rubydoc.info/github/hamstergem/hamster/master/Hamster/List">API Documentation</a>)</span></h2>

Hamster `List`s have a "head" (the value at the front of the list),
and a "tail" (a list of the remaining items):

``` ruby
list = Hamster.list(1, 2, 3)
list.head                    # => 1
list.tail                    # => Hamster.list(2, 3)
```

To add to a list, you use `List#cons`:

``` ruby
original = Hamster.list(1, 2, 3)
copy = original.cons(0)      # => Hamster.list(0, 1, 2, 3)
```

Notice how modifying a list actually returns a new list.
That's because Hamster `List`s are immutable. Thankfully,
just like other Hamster collections, they're also very
efficient at making copies!

`List` is, where possible, lazy. That is, it tries to defer
processing items until absolutely necessary. For example,
given a crude function to detect prime numbers:

``` ruby
def prime?(number)
  2.upto(Math.sqrt(number).round) do |integer|
    return false if (number % integer).zero?
  end
  true
{'fraction_non_alphanumeric': 0.15728257996299233, 'fraction_numerical': 0.007665873645255088, 'mean_word_length': 4.094254937163376, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 93, 'https://': 14, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2382200', 'n_tokens_mistral': 3924, 'n_tokens_neox': 3641, 'n_words': 1086}