Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

varargs, mini logic programs to determine the meta_predicate signature

32 views
Skip to first unread message

burs...@gmail.com

unread,
Aug 28, 2017, 11:10:52 AM8/28/17
to
Dear All,

Just chewing on the meta_prediate signature for varargs
predicates. The simplest example beeing call/n itself:

:- meta_predicate call(0).
:- meta_predicate call(1,?).
:- meta_predicate call(2,?,?).
Etc..

Current solution in some Prolog systems: Put meta_predicate
directives for some n=<k, for a fixed k, for example k=8.

Otherwise 'après moi, le déluge'. Here is an idea that
meta_predicate declarations could be itself determined

by some mini logic programs. For example if meta_predicate
declaration where internally represented as lists:

:- meta_predicate_internal [call,0].
:- meta_predicate_internal [call,1,?].
:- meta_predicate_internal [call,2,?,?].
Etc..

Further if the meta specifier for a closure index 0,1,2,...
were interally represented as 0,? -> 0,? -> ? -> 0,...

:- meta_predicate_internal [call,0].
:- meta_predicate_internal [call,(? -> 0),?].
:- meta_predicate_internal [call,(? -> ? -> 0),?,?].
Etc..

We could simply have a rule, which defines implicitly a type
constructor for a type T such that meta_predicate_internal [call|T]:

meta_predicate_internal([call,0]).
meta_predicate_internal([call,(? -> C),?|D]) :-
meta_predicate_internal([call,C|D]).

In calculus of constrution we would have some sort rules
I guess. Here is an example run:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.13)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- meta_predicate_internal(X).
X = [call, 0] ;
X = [call, ((?)->0), ?] ;
X = [call, ((?)->(?)->0), ?, ?] ;
X = [call, ((?)->(?)->(?)->0), ?, ?, ?] ;
X = [call, ((?)->(?)->(?)->(?)->0), ?, ?, ?, ?] ;
X = [call, ((?)->(?)->(?)->(?)->(?)->0), ?, ?, ?, ?, ?] .
Etc...

Bye

burs...@gmail.com

unread,
Aug 28, 2017, 11:16:53 AM8/28/17
to
Maybe this could lead to a sort expansion, or
somesuch. With the predicates:

multifile sort_expansion/2: The sort expansion hook.
expand_sort/2: Invoking sort expansion.

The time when these hooks are called would be
during predicate indicator resolution. The predicate

table would be such that it would held only the
minimal arity, for example arity=1 plus varargs=true.

There are lookup techniques that can find a predicate
for arity=n in such a dictionary, for example a

near find in a tree. The dictionary would then hold
a meta_predicate rump for example:

:- meta_predicate [call,_|_].

This would give the final meta_predicate declaration
together with the given arity and the sort expansion.

This final meta_predicate declaration is cached at
the call-site, together with the resolved

predicate table entry.

Bye

j4n bur53

unread,
Aug 28, 2017, 3:06:02 PM8/28/17
to
Dear All,

Inspired by a feature of XPath, here is a simple
solution. XPath, for example in the incarnation of
the SWI-Prolog xpath, allows to specify a child by
the followig set of expressions:

Integer
The N-th element with the given name, with 1 denoting the first
element. Same as index(Integer).
last
The last element with the given name. Same as index(last).
last - IntExpr
The IntExpr-th element before the last. Same as index(last-IntExpr).
http://www.swi-prolog.org/pldoc/man?predicate=xpath/3

Now we could extend the meta argument specifier syntax of
for meta predicate declaration as follows. This
is the current meta agument specifier syntax:

meta_arg_spec --> integer
| "?".

We could extend this syntax by the following
additional syntax productions for meta specifier
syntax. Namely:

meta_arg_spec --> "arity" - integer
| "arity" + integer
| "arity"
| integer
| "?".

We could then simply use the rump of the predicate,
and place a meta_predicate specifier for the rump,
using these new meta argument specifier.

:- varargs call/1.
:- meta_predicate call(arity-1).

As a rule all arguments not in the rump would be
automatically have the meta argument specifier
"?". So from the above and wih varargs flag=true,

we would get, for call/1, call/2, call/3, etc:
:- meta_predicate call(0).
:- meta_predicate call(1,?).
:- meta_predicate call(2,?,?).
Etc..

There are more use cases than only call/n. Our
abstraction operator (\)/2 could be typed with
such a rump declaration and the varargs flag=true.

Bye

burs...@gmail.com schrieb:

burs...@gmail.com

unread,
Jun 18, 2018, 9:17:55 AM6/18/18
to
I am considering again varargs in Prolog. Like for the
second or third time. But this time for OO-systems. So
its not really call/n, but (::)/2. But there is a twist,

you can have (::)/2 and call/n combined, so the solution
is then to define (::)/3, (::)/4, ... so that for example
this call here:

?- call(X::invert, Y). /* step 1 */

Gives the same result as:

?- ::(X,invert,Y). /* step 2 */

Which then transforms itself to:

?- X::invert(Y). /* step 3 */

Actually I am skipping step 2 and go directly from step
1 to step 3. But I have some meta_predicate definitions
for step 2, so that pretty printing works.

So what is the benefit of best kept secret in Prolog,
reexport/1 as IS-A and adding an (::)/2 operator:

- Pythonesk methods can be catalogued like any
other predicates. The have the arity N+1, where
N is the number of message parameters. The additional
parameter is self.

- They can be catalogued to the module where they
are defined. Also the module gives already enough
information concerning inheritance, just check
the reexport/1 directives of the module.

- Native tools like apropos/1, edit/1, etc.. work
all unchanged. They can find a Pythonesk method
definition, and they can yield information for this
Pythonesk method or give navigation to this Pythonesk
method. Also a debugger works unchanged.

- Likewise external tools. If your Prolog system uses
some external IDE, cooperates with such an external
IDE, by some wire protocol etc.., not much changes
for this IDE. Pythonesk methods are just predicates
like any other predicate. You should be able to set
break points and even inspect variables. You will see
a self variable, the name is given by the user.

But if call/n is involved, I guess it is recommended to
do some additional meta-predicate definitions, so that these
tools can better understand source code. For example
pretty printing works better with more meta-predicate
definitions. So I am considering varargs again.

Here is what can be done without varargs, just make
some meta-predicate declarations up to some maximum arity:

The meta-predicate definitions for (::)/[4,5,6,..] are here:
http://www.jekejeke.ch/idatab/doclet/blog/en/docs/05_run/05_frequent/standard/apply.html

The meta-predicate definitions for (::)/[2,3] are here:
http://www.jekejeke.ch/idatab/doclet/blog/en/docs/05_run/02_reference/runtime/quali.html

I remember in the past, that introducing varargs alone
doesn't solve the problem. We would also have arity based
meta argument specifiers. So these meta predicate definitions
for example here:

:- meta_predicate ::(?,::(0)).
:- meta_predicate ::(?,::(1),?).
:- meta_predicate ::(?,::(2),?,?).
:- meta_predicate ::(?,::(3),?,?,?).
:- meta_predicate ::(?,::(4),?,?,?,?).
Etc...

How can they be replaced by a single varargs meta-predicate
declaration? We would need to replace the numbers 2, 3, 4, ...
etc.. by a formula arity-2 or somesuch. And let the interpreter
understand such formulas at runtime.

Am Montag, 28. August 2017 17:10:52 UTC+2 schrieb burs...@gmail.com:
0 new messages