 
   ## Examples
 
-  In Elixir, only `false` and `nil` are considered falsy values.
-  Everything else evaluates to `true` in `if/2` clauses. Depending
-  on the application, it may be important to specify a `blank?`
-  protocol that returns a boolean for other data types that should
-  be considered "blank". For instance, an empty list or an empty
-  binary could be considered blank.
-
-  Such protocol could be implemented as follows:
-
-      defprotocol Blank do
-        @doc "Returns `true` if `data` is considered blank/empty"
-        def blank?(data)
-      end
-
-  Now that the protocol is defined it can be implemented. It needs to be
-  implemented for each Elixir type; for example:
-
-      # Integers are never blank
-      defimpl Blank, for: Integer do
-        def blank?(number), do: false
-      end
-
-      # The only blank list is the empty one
-      defimpl Blank, for: List do
-        def blank?([]), do: true
-        def blank?(_),  do: false
-      end
-
-      # The only blank atoms are "false" and "nil"
-      defimpl Blank, for: Atom do
-        def blank?(false), do: true
-        def blank?(nil),   do: true
-        def blank?(_),     do: false
-      end
-
-  The implementation of the `Blank` protocol would need to be defined for all
-  Elixir types. The available types are:
+  In Elixir, we have two verbs for checking how many items there
+  are in a data structure: `length` and `size`.  `length` means the
+  information must be computed. For example, `length(list)` needs to
+  traverse the whole list to calculate its length. On the other hand,
+  `tuple_size(tuple)` and `byte_size(binary)` do not depend on the
+  tuple and binary size as the size information is precomputed in
+  the data structure.
+
+  Although Elixir includes specific functions such as `tuple_size`,
+  `binary_size` and `map_size`, sometimes we want to be able to
+  retrieve the size of a data structure regardless of its type.
+  In Elixir we can write polymorphic code, i.e. code that works
+  with different shapes/types, by using protocols. A size protocol
+  could be implemented as follows:
+
+      defprotocol Size do
+        @doc "Calculates the size (and not the length!) of a data structure"
+        def size(data)
+      end
+
+  Now that the protocol can be implemented for every data structure
+  the protocol may have a compliant implementation for:
+
+      defimpl Size, for: Binary do
+        def size(binary), do: byte_size(binary)
+      end
+
+      defimpl Size, for: Map do
+        def size(map), do: map_size(map)
+      end
+
+      defimpl Size, for: Tuple do
+        def size(tuple), do: tuple_size(tuple)
+      end
+
+  Notice we didn't implement it for lists as we don't have the
+  `size` information on lists, rather its value needs to be
+  computed with `length`.
+
+  It is possible to implement protocols for all Elixir types:
 
     * Structs (see below)
     * `Tuple`

      defmodule User do
        defstruct [:email, :name]

        defimpl Blank do
          def blank?(%User{}), do: false
        end
      end

  If a protocol is not found for a given type, it will fallback to
  `Any`. Protocols that are implemented for maps don't work by default
  on structs; look at `defstruct/1` for more information about deriving
  protocols.

  ## Fallback to any

  In some cases, it may be convenient to provide a default
  implementation for all types. This can be achieved by
  setting the `@fallback_to_any` attribute to `true` in the protocol
  definition:

      defprotocol Blank do
        @fallback_to_any true
        def blank?(data)
      end

  The `Blank` protocol can now be implemented for `Any`:

      defimpl Blank, for: Any do
        def blank?(_), do: true
      end

  One may wonder why such behaviour (fallback to any) is not the default one.

  It is two-fold: first, the majority of protocols cannot
  implement an action in a generic way for all types; in fact,
  providing a default implementation may be harmful, because users
  may rely on the default implementation instead of providing a
  specialized one.

  Second, falling back to `Any` adds an extra lookup to all types,
  which is unnecessary overhead unless an implementation for `Any` is
  required.

  ## Types

  Defining a protocol automatically defines a type named `t`, which
  can be used as follows:

      @spec present?(Blank.t) :: boolean
      def present?(blank) do
        not Blank.blank?(blank)
      end

  The `@spec` above expresses that all types allowed to implement the


  The real benefit of protocols comes when mixed with structs.
  For instance, Elixir ships with many data types implemented as
  structs, like `MapSet`. We can implement the `Size` protocol
  for those types as well:

      defimpl Size, for: MapSet do
        def size(map_set), do: MapSet.size(map_set)
      end

  When implementing a protocol for a struct, the `:for` option can
