Elixir v1.8.0-rc.1 Protocol View Source

Functions for working with protocols.

Link to this section Summary

Functions

Checks if the given module is loaded and is an implementation of the given protocol.

Checks if the given module is loaded and is protocol.

Receives a protocol and a list of implementations and consolidates the given protocol.

Returns true if the protocol was consolidated.

Defines a new protocol function.

Derives the protocol for module with the given options.

Extracts all types implemented for the given protocol from the given paths.

Extracts all protocols from the given paths.

Link to this section Functions

Link to this function

assert_impl!(protocol, base)

View Source

Specs

assert_impl!(module(), module()) :: :ok

Checks if the given module is loaded and is an implementation of the given protocol.

Returns :ok if so, otherwise raises ArgumentError.

Link to this function

assert_protocol!(module)

View Source

Specs

assert_protocol!(module()) :: :ok

Checks if the given module is loaded and is protocol.

Returns :ok if so, otherwise raises ArgumentError.

Link to this function

consolidate(protocol, types)

View Source

Specs

consolidate(module(), [module()]) ::
  {:ok, binary()} | {:error, :not_a_protocol} | {:error, :no_beam_info}

Receives a protocol and a list of implementations and consolidates the given protocol.

Consolidation happens by changing the protocol impl_for in the abstract format to have fast lookup rules. Usually the list of implementations to use during consolidation are retrieved with the help of extract_impls/2.

It returns the updated version of the protocol bytecode. If the first element of the tuple is :ok, it means the protocol was consolidated.

A given bytecode or protocol implementation can be checked to be consolidated or not by analyzing the protocol attribute:

Protocol.consolidated?(Enumerable)

This function does not load the protocol at any point nor loads the new bytecode for the compiled module. However each implementation must be available and it will be loaded.

Specs

consolidated?(module()) :: boolean()

Returns true if the protocol was consolidated.

Link to this macro

def(signature)

View Source (macro)

Defines a new protocol function.

Protocols do not allow functions to be defined directly, instead, the regular Kernel.def/* macros are replaced by this macro which defines the protocol functions with the appropriate callbacks.

Link to this macro

derive(protocol, module, options \\ [])

View Source (macro)

Derives the protocol for module with the given options.

If your implementation passes options or if you are generating custom code based on the struct, you will also need to implement a macro defined as __deriving__(module, struct, options) to get the options that were passed.

Examples

defprotocol Derivable do
  def ok(a)
end

defimpl Derivable, for: Any do
  defmacro __deriving__(module, struct, options) do
    quote do
      defimpl Derivable, for: unquote(module) do
        def ok(arg) do
          {:ok, arg, unquote(Macro.escape(struct)), unquote(options)}
        end
      end
    end
  end

  def ok(arg) do
    {:ok, arg}
  end
end

defmodule ImplStruct do
  @derive [Derivable]
  defstruct a: 0, b: 0

  defimpl Sample do
    def ok(struct) do
      Unknown.undefined(struct)
    end
  end
end

Explicit derivations can now be called via __deriving__:

# Explicitly derived via `__deriving__`
Derivable.ok(%ImplStruct{a: 1, b: 1})

# Explicitly derived by API via `__deriving__`
require Protocol
Protocol.derive(Derivable, ImplStruct, :oops)
Derivable.ok(%ImplStruct{a: 1, b: 1})
Link to this function

extract_impls(protocol, paths)

View Source

Specs

extract_impls(module(), [charlist() | String.t()]) :: [atom()]

Extracts all types implemented for the given protocol from the given paths.

The paths can be either a charlist or a string. Internally they are worked on as charlists, so passing them as lists avoid extra conversion.

Does not load any of the implementations.

Examples

# Get Elixir's ebin directory path and retrieve all protocols
iex> path = :code.lib_dir(:elixir, :ebin)
iex> mods = Protocol.extract_impls(Enumerable, [path])
iex> List in mods
true
Link to this function

extract_protocols(paths)

View Source

Specs

extract_protocols([charlist() | String.t()]) :: [atom()]

Extracts all protocols from the given paths.

The paths can be either a charlist or a string. Internally they are worked on as charlists, so passing them as lists avoid extra conversion.

Does not load any of the protocols.

Examples

# Get Elixir's ebin directory path and retrieve all protocols
iex> path = :code.lib_dir(:elixir, :ebin)
iex> mods = Protocol.extract_protocols([path])
iex> Enumerable in mods
true