     { :error, :not_a_protocol } |
     { :error, :no_beam_info }
 
+  defmacrop if_ok(expr, call) do
+    quote do
+      case unquote(expr) do
+        { :ok, var } -> unquote(Macro.pipe(quote(do: var), call))
+        other -> other
+      end
+    end
+  end
+
   def apply_to(protocol, types) when is_atom(protocol) do
-    protocol
-    |> ensure_protocol
-    |> change_debug_info(types)
-    |> compile
+    ensure_protocol(protocol)
+    |> if_ok(change_debug_info types)
+    |> if_ok(compile)
   end
 
   # Ensure the given module is loaded and is a protocol.

  end

  # Finally compile the module and emit its bytecode.
  defp compile({ :ok, protocol, code }) do
    opts = if Code.compiler_options[:debug_info], do: [:debug_info], else: []
    { :ok, ^protocol, binary, _warnings } = :compile.forms(code, [:return|opts])
    { :ok, binary }
  end

  defp compile(other) do
    other
  end
end


  defp change_impl_for([], protocol, _info, _types, is_protocol, acc) do
    if is_protocol do
      { :ok, { protocol, Enum.reverse(acc) } }
    else
      { :error, :not_a_protocol }
    end
