A.32.1 The strength and weakness of predicate options
Many ISO predicates accept options, e.g., open/4, write_term/3. Options offer an attractive alternative to proliferation into many predicates and using high-arity predicates. Properly defined and used, they also form a mechanism for extending the API of both system and application predicates without breaking portability. I.e., previously fixed behaviour can be replaced by dynamic behaviour controlled by an option where the default is the previously defined fixed behaviour. The alternative to using options is to add an additional argument and maintain the previous definition. While a series of predicates with increasing arity is adequate for a small number of additional parameters, the untyped positional argument handling of Prolog quickly makes this unmanageable.
The ISO standard uses the extensibility offered by options by allowing implementations to extend the set of accepted options. While options form a perfect solution to maintain backward portability in a linear development model, it is not well equipped to deal with concurrent branches because
- There is no API to find which options are supported in a particular implementation.
- While the portability problem caused by a missing predicate in Prolog A can easily be solved by implementing this predicate, it is much harder to add processing of an additional option to an already existing predicate.
Different Prolog implementations can be seen as concurrent development branches of the Prolog language. Different sets of supported options pose a serious portability issue. Using an option O that establishes the desired behaviour on system A leads (on most systems) to an error or system B. Porting may require several actions:
- Drop O (if the option is not vital, such as the layout options to write_term/3)
- Replace O by O2 (i.e., a differently named option doing the same)
- Something else (cannot be ported; requires a totally different approach, etc.)
Predicates that process options are particularly a problem when writing a compatibility layer to run programs developed for System A on System B because complete emulation is often hard, may cause a serious slowdown and is often not needed because the application-to-be-ported only uses options that are shared by all target Prolog implementations. Unfortunately, the consequences of a partial emulation cannot be assessed by tools.