       iex> star_ratings[1.5]
       "★☆"
 
-  Note that the dynamic lookup syntax (`term[key]`) roughly translates to
-  `Access.get(term, key, nil)`.
-
-  `Access` can be combined with `Kernel.put_in/3` to put a value
-  in a given key:
-
-      iex> map = %{a: 1, b: 2}
-      iex> put_in map[:a], 3
-      %{a: 3, b: 2}
-
   This syntax is very convenient as it can be nested arbitrarily:
 
       iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
       iex> put_in users["john"][:age], 28
       %{"john" => %{age: 28}, "meg" => %{age: 23}}
 
-  Furthermore, `Access` transparently ignores `nil` values:
+  Furthermore, the bracket access transparently ignores `nil` values:
 
       iex> keywords = [a: 1, b: 2]
       iex> keywords[:c][:unknown]
       nil
 
-  Since `Access` is a behaviour, it can be implemented for key-value
-  data structures. The implementation should be added to the
-  module that defines the struct being accessed. `Access` requires the
-  key comparison to be implemented using the `===/2` operator.
-
-  ## Static lookups
-
-  The `Access` syntax (`data[key]`) cannot be used to access fields in
-  structs, since structs do not implement the `Access` behaviour by
-  default. It is also a design decision: the dynamic access lookup
-  is meant to be used for dynamic key-value structures, like maps
-  and keywords, and not by static ones like structs (where fields are
-  known and not dynamic).
-
-  Therefore Elixir provides a static lookup for struct fields and for atom
-  fields in maps. Imagine a struct named `User` with a `:name` field.
-  The following would raise:
+  Internally, `data[key]` translates  to `Access.get(term, key, nil)`.
+  Developers interested in implementing their own key-value data
+  structures can implement the `Access` behaviour to provide the
+  bracket-based access syntax. `Access` requires the key comparison
+  to be implemented using the `===/2` operator.
+
+  ### Dot-based syntax
+
+  The `data.field` syntax is used exclusively to access atom fields
+  in maps and structs. If the field accessed does not exist, it
+  raises an error. This is a deliberate decision: since all of the
+  fields in a struct are pre-determined, structs support only the
+  dot-based syntax and not the access one.
+
+  Imagine a struct named `User` with a `:name` field. The following would raise:
 
       user = %User{name: "John"}
       user[:name]
       # ** (UndefinedFunctionError) undefined function User.fetch/2 (User does not implement the Access behaviour)
 
-  Structs instead use the `user.name` syntax to access fields:
+  Instead we should use the `user.name` syntax to access fields:
 
       user.name
       #=> "John"
 
-  The same `user.name` syntax can also be used by `Kernel.put_in/2`
-  for updating structs fields:
-
-      put_in user.name, "Mary"
-      #=> %User{name: "Mary"}
-
   Differently from `user[:name]`, `user.name` is not extensible via
   a behaviour and is restricted only to structs and atom keys in maps.
 
-  As mentioned above, this works for atom keys in maps as well. Refer to the
-  `Map` module for more information on this.
-
-  Summing up:
-
-    * `user[:name]` is used by dynamic structures, is extensible and
-      does not raise on missing keys
-    * `user.name` is used by static structures, it is not extensible
-      and it will raise on missing keys
-
-  ## Accessors
-
-  While Elixir provides built-in syntax only for traversing dynamic
-  and static key-value structures, this module provides convenience
-  functions for traversing other structures, like tuples and lists,
-  to be used alongside `Kernel.put_in/2` in others.
-
-  For instance, given a user map with `:name` and `:languages` keys, here is how
-  to deeply traverse the map and convert all language names to uppercase:
+  ### Summing up
+
+  The bracket-based syntax, `user[:name]`, is used by dynamic structures,
+  is extensible and returns nil on misisng keys.
+
+  The dot-based syntax, `user.name`, is used by exclusively to access atom
+  keys in maps and structs, and it raises on missing keys.
+
+  ## Nested data structures
+
+  Both key-based access syntaxes can be used with the nested update
+  functions in `Kernel`, such as `Kernel.get_in/2`, `Kernel.put_in/3`,
+  `Kernel.update_in/3` and `Kernel.get_and_update_in/3`.
+
+  For example, to update a map inside another map of dynamic values,
+  one can do:
+
+     iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
+     iex> put_in users["john"].age, 28
+     %{"john" => %{age: 28}, "meg" => %{age: 23}}
+
+
+  This module provides convenience functions for traversing other
+  structures, like tuples and lists, to be used alongside `Kernel.put_in/2`
+  and others.
+
+  For instance, given a user map with `:name` and `:languages` keys,
+  here is how to deeply traverse the map and convert all language names
+  to uppercase:
 
       iex> languages = [
       ...>   %{name: "elixir", type: :functional},

defmodule Access do
  @moduledoc """
  Key-based access to data structures using the `data[key]` syntax.

  Elixir provides two syntaxes for accessing values. `user[:name]`
  is used by dynamic structures, like maps and keywords, while
  `user.name` is used by structs. The main difference is that
  `user[:name]` won't raise if the key `:name` is missing but
  `user.name` will raise if there is no `:name` key.

  Besides the cases above, this module provides convenience
  functions for accessing other structures, like `at/1` for
  lists and `elem/1` for tuples. Those functions can be used
  by the nested update functions in `Kernel`, such as
  `Kernel.get_in/2`, `Kernel.put_in/3`, `Kernel.update_in/3`,
  `Kernel.get_and_update_in/3` and friends.

  ## Dynamic lookups

  Out of the box, `Access` works with `Keyword` and `Map`:

      iex> keywords = [a: 1, b: 2]
      iex> keywords[:a]
      1

      iex> map = %{a: 1, b: 2}
      iex> map[:a]


  See the functions `key/1`, `key!/1`, `elem/1`, and `all/0` for some of the
  available accessors.
  """

  @type container :: keyword | struct | map
