Hello all,
One critique of prolog I see often is the lack of functional notation.
Therefore, to chain calls to predicates, we need to introduce additional variables (and find names for them).
However, this critique is too simple, because there are what I call functional islands in prolog (and swi-prolog).
Here is my own-compiled list of functional notation used in swi-prolog:
- prolog standard arithmetic:
- iso prolog
- scope:
is
,=:=
,=\=
,<
and all arithmetic comparison operators - only works with numbers (letās ignore edge cases for now ^^) for speed reason ?
- calling convention: input as args, single implicit output
- ā.ā functional notation for dicts
- swi-prolog specific
- works anywhere
- polymorphic through the use of different dict tags (here dict tags and module are squashed)
- bugs: expansion inside lambdas doesnāt work correctly
- calling convention:
R = Dict.func(Args)
, which is compile time expanded to'.'(Dict, func(Arg), R)
- is defined as
Dict.func(Arg) := R :- ...
, which is compile time expanded tofunc(Dict, Arg, R)
- expansion time:
system
- library(arithmetic)
- builtin pack for swi-prolog
- same scope as prolog arithmetic
- user extensible
- expansion time:
system
- library(arithmetic_types)
- extra pack for swi-prolog, so kind of swi-prolog specific
- same scope as prolog arithmetic, but prefix standard arithmetic operator by
.
like.+
,.*
etc - user extensible
- polymorphic depending on args
- calling convention: same as prolog arithmetic, is defined by putting output as last argument
- expansion time:
user
- library(func)
- extra pack for swi-prolog, so kind of swi-prolog specific
- works anywhere
- user extensible
- works with the module system, polymorphic
- calling convention can be very complex and use extra operators like
$
,of
,~
- expansion time:
user
- has some support for dicts
- library(macros)
- default pack for swi-prolog
- works anywhere
- user extensible
- only expand values, does not call predicates. Functional in the sense that the return value is implicit
- dcg for chaining calls
- more of a hack than anything else
- wrapping predicate:
clpfd:#=
,clpqr:{}
,clpBNR:{}
,units:qeval
- reimplements DSLs
- fully runtime
not user extensible, clpBNR provides supports for custom op- very difficult to mix with each other
- incompatible with compile time expansion of functional notation
As you can see, most of these functional islands works through compile time expansion.
This approach has pros and cons:
- pros, apart from the functional notation
- can be as efficient as normal code, if expanded to concrete predicates, but the need for polymorphism often kills this
- polymorphic predicates (sometimes)
- user extensible
- cons
- needs unambiguous operator at compile time. ā.ā for dicts is quite natural, but
.+
of arithmetic_types and the use of$
andof
infunc
is quite ugly - breaks prolog standard evaluation order unless explicitly taken care of
- dict expansion takes care of correctly expanding when used with meta-predicate but breaks when used in a lambda
- arithmetic_types takes care of correctly expanding prolog arithmetic expression but not dict functional notation
- needs unambiguous operator at compile time. ā.ā for dicts is quite natural, but