..
   Copyright 2009-2015 Ram Rachum. This work is licensed under a Creative
   Commons Attribution-ShareAlike 3.0 Unported License, with attribution to
   "Ram Rachum at ram.rachum.com" including link. The license may be obtained
   at http://creativecommons.org/licenses/by-sa/3.0/

.. _other_classes:

Other classes
=============

These are smaller, simpler classes that are included in ``combi``.


:class:`MapSpace`
-----------------

.. class:: MapSpace(function, sequence)

   A space of a function applied to a sequence.
   
   This is similar to Python's built-in :func:`map`, except that it behaves
   like a sequence rather than an iterable. (Though it's also iterable.) You
   can access any item by its index number.
   
   Example:
   
      >>> map_space = MapSpace(lambda x: x ** 2, range(7))
      >>> map_space
      MapSpace(<function <lambda> at 0x00000000030C1510>, range(0, 7))
      >>> len(map_space)
      7
      >>> map_space[3]
      9
      >>> tuple(map_space)
      (0, 1, 4, 9, 16, 25, 36)

    
    
:class:`ProductSpace`
---------------------

.. class:: ProductSpace(sequences)

   A product space between sequences.
   
   This is similar to Python's :func:`itertools.product`, except that
   it behaves like a sequence rather than an iterable. (Though it's also
   iterable.) You can access any item by its index number.
   
   Example:
   
      >>> product_space = ProductSpace(('abc', range(4)))
      >>> product_space
      <ProductSpace: 3 * 4>
      >>> product_space.length
      12
      >>> product_space[10]
      ('c', 2)
      >>> tuple(product_space)
      (('a', 0), ('a', 1), ('a', 2), ('a', 3), ('b', 0), ('b', 1), ('b', 2),
       ('b', 3), ('c', 0), ('c', 1), ('c', 2), ('c', 3))

   .. method:: index(given_sequence)
      
      Get the index number of ``given_sequence`` in this product space.



:class:`ChainSpace`
-------------------

.. class:: ChainSpace(sequences)

   A space of sequences chained together.
   
   This is similar to Python's :func:`itertools.chain`, except that items can be fetched
   by index number rather than just iteration.
   
   Example:
   
      >>> chain_space = ChainSpace(('abc', (1, 2, 3)))
      >>> chain_space
      <ChainSpace: 3+3>
      >>> chain_space[4]
      2
      >>> tuple(chain_space)
      ('a', 'b', 'c', 1, 2, 3)
      >>> chain_space.index(2)
      4
      
   .. method:: index(item)
   
      Get the index number of ``item`` in this space.



:class:`SelectionSpace`
-----------------------

.. class:: SelectionSpace(sequence)

   Space of possible selections of any number of items from ``sequence``.
   
   For example:
   
      >>> tuple(SelectionSpace(range(2)))
      (set(), {1}, {0}, {0, 1})
       
   The selections (which are sets) can be for any number of items, from zero to
   the length of the sequence.

   Of course, this is a smart object that doesn't really create all these sets
   in advance, but rather on demand. So you can create a
   :class:`SelectionSpace` like this:
   
      >>> selection_space = SelectionSpace(range(10**4))
       
   And take a random selection from it:
   
      >>> selection_space.take_random()
      {0, 3, 4, ..., 9996, 9997}
       
   Even though the length of this space is around 10 ** 3010, which is much
   bigger than the number of particles in the universe.

   .. method:: index(selection)
   
      Find the index number of set ``selection`` in this 
      :class:`SelectionSpace`.
