## A.15 library(option): Option list processing

See also
  - `library(record)`
  - Option processing capabilities may be declared using the directive predicate_options/3.
To be done
  We should consider putting many options in an assoc or record with appropriate preprocessing to achieve better performance.

The `library(option)` provides some utilities for processing option lists. Option lists are commonly used as an alternative for many arguments. Examples of built-in predicates are open/4 and write_term/3. Naming the arguments results in more readable code, and the list nature makes it easy to extend the list of options accepted by a predicate. Option lists come in two styles, both of which are handled by this library.

Name(Value)
  This is the preferred style.
Name = Value
  This is often used, but deprecated.

Processing options inside time-critical code (loops) can cause serious overhead. One possibility is to define a record using `library(record)` and initialise this using make_<record>/2. In addition to providing good performance, this also provides type-checking and central declaration of defaults.

    :- record atts(width:integer=100, shape:oneof([box,circle])=box).

    process(Data, Options) :-
            make_atts(Options, Attributes),
            action(Data, Attributes).

    action(Data, Attributes) :-
            atts_shape(Attributes, Shape),
            ...

Options typically have exactly one argument. The library does support options with 0 or more than one argument with the following restrictions:

- The predicate option/3 and select_option/4, involving default are meaningless. They perform an `arg(1, Option, Default)`, causing failure without arguments and filling only the first option-argument otherwise.
- meta_options/3 can only qualify options with exactly one argument.

[semidet]option(?Option, +OptionList, +Default)
  Get an Option Qfrom OptionList. OptionList can use the Name=Value as well as the Name(Value) convention.

  Option | Term of the form Name(?Value).

[semidet]option(?Option, +OptionList)
  Get an Option from OptionList. OptionList can use the Name=Value as well as the Name(Value) convention. Fails silently if the option does not appear in OptionList.

  Option | Term of the form Name(?Value).

[semidet]select_option(?Option, +Options, -RestOptions)
  Get and remove Option from an option list. As option/2, removing the matching option from Options and unifying the remaining options with RestOptions.
[det]select_option(?Option, +Options, -RestOptions, +Default)
  Get and remove Option with default value. As select_option/3, but if Option is not in Options, its value is unified with Default and RestOptions with Options.
[det]merge_options(+New, +Old, -Merged)
  Merge two option lists. Merged is a sorted list of options using the canonical format Name(Value) holding all options from New and Old, after removing conflicting options from Old.

  Multi-values options (e.g., `proxy(Host, Port)`) are allowed, where both option-name and arity define the identity of the option.

[det]meta_options(+IsMeta, :Options0, -Options)
  Perform meta-expansion on options that are module-sensitive. Whether an option name is module-sensitive is determined by calling `call(IsMeta, Name)`. Here is an example:

              meta_options(is_meta, OptionsIn, Options),
              ...

      is_meta(callback).

  Meta-options must have exactly one argument. This argument will be qualified.

  To be done
    Should be integrated with declarations from predicate_options/3.