README.md

# SuperList

The Enum and List modules are powerful tools for working with lists in Elixir,
but they generally are designed for manipulating a single list at a time.
Sometimes you need to iterate over multiple lists simultaneously. For
example, to merge two lists, taking the maximum value between the two at each
offset:

    Enum.zip(list1, list2)
    |> Enum.map(fn {element1, element2} ->
      max(element1, element2)
    end)

While this works, it is verbose and inefficient. The Enum.zip call creates
tuples that we immediately match and throw away. If you've attempted to
optimize similar code, you may have written something like:

    def max_of_lists([element1 | list1], [element2 | list2]) do
      [max(element1, element2) | max_of_lists(list1, list2)]
    end
    
    def max_of_lists([], []) do
      []
    end

Don't clutter your codebase with ad-hoc iteration code like this! Write it
more cleanly with SuperList:

    SuperList.map(list1, list2, &max/2)

## So it's like Enum.zip_with, or what?

Yeah, these are equivalent both in semantics and performance:

    Enum.zip_with(list1, list2, func)

    SuperList.map(list1, list2, func)

However things change with 3+ lists. Enum supports variable numbers of
arguments by accepting a list with a variable number of elements, whereas
Superlist defines multiple implementations with variable arities.

    Enum.zip_with([list1, list2, list3], fn [element1, element2, element3] ->
      func.(element1, element2, element3)
    end)

    SuperList.map(list1, list2, list3, func)

In the above example with 3 lists, SuperList is not only cleaner but about 3.8x faster.

## Supported functions

| Enum.each | SuperList.each |
| Enum.map | SuperList.map |
| Enum.map_reduce | SuperList.map_reduce |
| Enum.reduce | SuperList.reduce |
| Enum.unzip | SuperList.unzip |
| Enum.zip | SuperList.zip |

    SuperList.map(list1, func/1)
    SuperList.map(list1, list2, func/2)
    SuperList.map(list1, list2, list3, func/3)
    # ...etc.

## Code generation

These optimizations are achieved using code generation. Implementations for
each function are defined accepting from 1 up to 25 lists. The upper limit
can be increased using a compile time setting.

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `superlist` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:superlist, "~> 0.1.0"}
  ]
end
```