Notice - this is deprecated as similar functionality is now in the Elixir standard library.
Switch branches/tags
Nothing to show
Latest commit 8578fac Jul 7, 2014 @jeremyjh deprecation notice
Failed to load latest commit information.
lib Handle maps for elixir 0.13. Apr 23, 2014
test Handle maps for elixir 0.13. Apr 23, 2014
.gitignore Handle maps for elixir 0.13. Apr 23, 2014
LICENSE add license Apr 3, 2013 deprecation notice Jul 7, 2014
mix.exs deprecation notice Jul 7, 2014
mix.lock remove ex_doc Jun 30, 2013
package.exs add expm package defintion Apr 30, 2013

Notice - deprecated

Please note that as of v0.14.0 Elixir provides nested data structure access as part of the standard library. Nested will not be maintained further, and will not compile on v.0.14 or later due to name conflicts.


Updates a hierarchy of heterogeneous record/collection types, given a Structure,a list of Fields and a value (or update function).

Structure can be any hierarchy/combination of:

* Records    
* Lists
* Tuples
* HashDict
* Erlang's :dict and :orddict

You can easily implement the Nested.Accessors protocol to support other structures. See accessors.ex for examples.

List of fields - list of symbols / indices in update path

* for Records, an atom  must indicate accessor e.g. :name for 
* for dictionaries, whatever key value
* for Tuples, a 0-based ordinal
* for Lists: 
  * atom (for Keyword list)
  * integer for ordinal position (position in list is preserved!)
  * [] - empty list (as last field) means prepend to list

Update value can be a function - in that case a record update_ accessor or Dict.update will be called as appropriate.


        import Nested

        defrecord Address, street: nil, city: nil, state: nil
        defrecord Person, first_name: nil, last_name: nil, address: nil, phone_numbers: nil

        home = "101 First Street", city: "Anytown", state: "Denial")
        jeremy = "Jeremy", last_name: "Huffman", address: home, phone_numbers: ["867-5309"])

        #simplest case - set a value in a nested record
        jeremy = put_in(jeremy, [:address, :state], "SC")
        IO.puts jeremy.address.state # "SC"

        #A hierarchy can be arbitrarily deep
        books = [first: [title: "A tale of two keywords", isbn: 12],second: [title: "For whom the code flows", isbn: 93]]
        library = [librarian: jeremy, books: books]

        #keyword lists (and dictionaries) are manipulated like records
        library = put_in(library, [:books, :first, :author], jeremy)

        IO.puts library[:books][:first][:author].first_name # "Jeremy"

        # With a plain list we can either replace an existing item by its ordinal index
        library = put_in(library, [:librarian, :phone_numbers, 0], "555-9191")

        # Or we can pre-pend items to it with an empty list []
        library = put_in(library, [:librarian, :phone_numbers, []], "867-5309")

        IO.inspect library[:librarian].phone_numbers # ["867-5309","555-9191"]

        #we can use update functions from records and dicts (and a fake one for lists)
        library = update_in(library, [:books, :first, :isbn], &1 + 1)

        IO.puts library[:books][:first][:isbn] # 13

        #and yes, there is also a get_in ...

        IO.puts get_in library, [:books, :first, :author, :address, :street] # 101 First Street

For more examples take a look at the tests.