LudovicoVan schrieb:
> Indirect calls are needed in the loop, but no additional "decoding" that
> I can see. But again, isn't this an overhead that is common to both
> kinds of solutions (and, essentially, to both a bootstrapped and a
> native approach, where natively you'd be dealing with function pointers
> or delegates)? In fact, my guess and implied question is that our
> benchmark so far shows non-backtrackable assignment to be competitive to
> native code.... no? (I was running SWI with default settings, BTW.)
Well, change your code from:
loop :-
... S1 is S+A ...
?- loop.
Into the following:
add(S1,S,A) :- S1 is S+A.
loop(X) :-
... call(X,S1,S,A) ...
?- loop(add).
And do a measurement.
As long as the interpreter does not do partial evaluation
from a top query down into invoked predicates, there is not
much chance that this is fast. i.e. as long as loop/1 is
not inlined you see a performance degradation.
In SWI there is probably one. Jekejeke Prolog there is
also probably one, but I tried hard to minimize it. Currently
implementation uses a polymorphic cache, since call/2 is
important in the forward chainer. There we have f(X1,..,Xn)
events which are handled by f(X1,..,Xn,Y) predicates.
Actually now that I mentioned it, I have used call/n in the
incremental prototype. This meta predicate does also do a goal
expansion and goal conversion. Maybe should give a try to the
buddy predicate sys_call/n which bypasses these steps. Oki
Doki. New figures coming soon.
> > If aggregate/3 were a spec and not a library, every system can
> > implement as it likes. And it would not be required that some
> > file
aggregate.pl is shuffeld around.
>
> +1 for discussing the ISO standard and for keeping a standard base
> library, if any, to the essential. That said, I'd still take that
> RISC-like approach I had mentioned: namely, here I'd rather
> advocate for the standardization of non-backtrackable assignment...
I was not refering to the ISO standard when I mentioned "spec".
What I wanted to express is that the predicte aggregate/3 has a
conceptual existence independent of some
aggregate.pl. This is
also seen in the SICStus documentation, which initial referes
to SQL aggregates as a motivator.
Non backtrackable assigment and the like have already been
proposed as an inclusion to some ISO standard. If you search for
example here for "Global Variables" you find quite a number of hits:
http://people.sju.edu/~jhodgson/wg17/doclist.html
http://people.sju.edu/~jhodgson/wg17/proporsal4.pdf
The destructive compound approach is probably supperior to globally
named variables, since it allows to quickly have garbage collected
thread local value holders. If you have a FFI (Foreign Function
Interface) and a reference datatype, you can also easily implement
such value holders. The reference datatype is necessary, since in
the present case the compounds are not mutable. (*)
Until now I was not very fond of global variables and/or destructive
compounds. I was hoping to cover state via the forward chaining. But
the present case of aggregates seems to produce a business case
for something in this direction. But from the way I would implement
it, i.e. for example the FFI solution, I think it would differ
from the SWI solution, in that it would not be based on compounds.
Maybe this is indicative that it is more difficult to find
consense about low level features than about high level features.
Bye
(*)
Here is a sketch how to do it in the Jekejeke Prolog API. Garbage
collection is left to Java. I was using something similar in my
trial of the incremental aggregates:
public class Holder {
public Term holds;
}
public class DestructiveHolderAPI {
public static TermRef createHolder() {
return new TermRef(new Holder());
}
public static Term accessHolder(TermRef r) {
return ((Holder)r.getValue()).holds;
}
public static void updateHolder(TermRef r, Term v) {
v = .. make a copy of v ..
((Holder)r.getValue()).holds = v;
}
}