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

The interaction of OO-Prolog and clause indexing

71 views
Skip to first unread message

janb...@easel.ch

unread,
Jun 15, 2018, 11:51:26 AM6/15/18
to
There is some peculiar interaction of OO-Prolog
and clause indexing. Lets compare the two approaches
PythonCallStyle and DictCallStyle.

- DictCallStyle: The passing of an OO call is translated
from X = Y.M(A1,..,An) to N:M(A1,..,An,Y,X) where N
is the class of Y. For a very primitive Prolog system, as

a last resort, which only has first argument indexing,
it could still index A1. Thats probably the advantage of
the DictCallStyle. It would work with very primitive

Prolog systems, and could still take advantage
of clause indexing.

- PythonCallStyle: The passing of an OO call is
translated from Y::M(A1,..,An) to N:M(Y,A1,..,An) where
N is the class of Y. This requires a more advanced

Prolog system. Ideally the Prolog system decides on
its own what kind of index it builds. And then since
typically the self variable is not in the first argument,

it must have enough index building logic, to not unnessarely
index this argument.

There are some Prolog systems that could probably already
deal with PythonCallStyle, since they have enough good
automatic indexing, what comes to mind are YAP, SWI, Jekejeke,

etc.. which all have just-in-time multi-argument indexing.
Multi-argument indexing could also index more than only
A1 in PythonCallStyle, depending on the sensitivity

further subsets or cascades of A2,..An could be index.
If the index is not just-in-time automatic, things get
annoying. One would need to manually direct indexes for

a Phytonesk like method predicate.

j4n bur53

unread,
Jun 15, 2018, 12:31:22 PM6/15/18
to
Strange question by Paulo Moura. The operator (::)/2
is part of the Jekejeke Prolog runtime library.
You can download it from here:

*Android Appstores:*
https://play.google.com/store/apps/details?id=jekpro.platform.headless

*Download:*
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/05_run/05_down.jsp

The operator (::)/2 exists already for a couple of
releases. To be exact it was introduce as a native
built-in in the following release

Jekejeke Prolog 1.1.1 (Object-Orientation via ISO Moduls)
http://www.jekejeke.ch/idatab/doclet/intr/en/docs/5_ext/94_arc2016/099_releases/topic_999588.html

>> On 11 Jun 2018, at 16:21, Proof Easel <janb...@easel.ch> wrote:
>>
>> You call others trolling, when you don't have any arguments
>> anymore? Thats ad hominem.
>
> *I* have nothing to prove. Logtalk is open
> source, well documented, comes with ~130
> examples, its design and implementation is
> described in my PhD thesis and several
> published papers, both reviewed by academic
> peers. Anyone can try if for free, anonymously,
> read the sources, run the examples, ...
>
> *You*, on the other hand, have *years* of
> bashing Logtalk and wild speculation on how
> you can do Logtalk features with just modules
> features. What's the download URL for your
> solution again?

janb...@easel.ch schrieb:

janb...@easel.ch

unread,
Jun 15, 2018, 12:54:31 PM6/15/18
to
Corr.:
typically the self variable is in the first argument,
it must have enough automatic index building logic

Otherwise in Python style a Prolog system that
would blindly do first argument indexing, would

always see a variable in the first argument,
and the resulting index would be not very useful.

burs...@gmail.com

unread,
Jun 16, 2018, 8:50:36 AM6/16/18
to
Concerning benchmarking the PythonCallStyle or DictCallStyle,
a dict data structure is a wellcome addition. They consist
a data structure that is also able to hold state of objects

that result from multiple inheritance. And slot number or
param number design cannot do this directly. A present instance
might have a totally different memory layout.

So the dict data structure solves the problem in that the
fields are accessed symbolically by names. The data structure
needs to incorporate some lookup mechanism to translate

from the field names to some slot indexes. SWI-Prolog solves
that already in that it uses sorted dict compounds, and can
then use the sorted invariant for its slot search.

For smaller dicts we can also search without this invariants.
We just completed such a simple dict realization and did
some preformance comparison of the message dispatch

mechanism. Here are the results for a color point problem:

SWI-Prolog 7 formulation:

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

?- X = colorpoint{x:1,y:2,color:0}.multiply(3), Y = X.invert().
Y = colorpoint{color:255, x:3, y:6}.

Jekejeke Prolog formulation (Preview):

Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- colorpoint(x,1,y,2,color,0)::multiply(3,X), X::invert(Y).
Y = colorpoint(x,3,y,6,color,255)

The results so far are encouraging. Calling the
above 500'000 times gives the following results:

Result for SWI-Prolog 7:

% 30,000,012 inferences, 1.750 CPU in 1.749 seconds
(100% CPU, 17142864 Lips)

Result for Jekejeke Prolog:

% Up 2,268 ms, GC 26 ms, Thread Cpu 2,188 ms
(Current 06/16/18 14:47:53)

For more details see here:

Preview: Module dict in native, better performance. (Jekejeke)
https://plus.google.com/+JekejekeCh/posts/f2SGiCytgrS

burs...@gmail.com

unread,
Jun 16, 2018, 9:13:03 AM6/16/18
to
What I do not yet know, whether we should have rather
strict dicts or more flexible dicts. Python provides
flexible dicts and also uses them in objects.

This is for example seen here (sorry for the annoying
voice of the presenter, sounds like a female dictator
robot, which made me fall asleep quickly):

Python Classes and Objects
https://www.youtube.com/watch?v=apACNr7DC_s

So in the above example they repeatedly do things
like self.first_name = "Dave", etc.. when the
object does not yet have the field first_name.

In my current dict_put/4 implementation, I only
allow to replace an existing field. The built-in
currently fails if the field doesn't exist,

but it could also throw an exception, to maybe
indicate a typo in the field name. Also inside
classes a directive field could automatically

create setters and getters, so that together
with a constructor policy field name typos
wont happen. Python is not the only language

that uses more flexible dicts. This was already
the case in JavaScript, one could do self["first_name"]
= "Dave" (double quotes or single quotes, don't remember),

even if "first_name" was not yet there.

burs...@gmail.com

unread,
Jun 16, 2018, 9:29:04 AM6/16/18
to
Begin: Obligatory Logtalk Punch

Disclaimer: The goal is not like in Logtalk to build some OO on
top of Prolog. The goal is to build some OO inside of Prolog.
Like Python did, some few nudges to get an OO-system.

Why? Because of performance and because of user-friendlyness.
We do not want that our user need a PhD to understand the
million variations of portocols, objects, and whatever,

and need to read million peer reviewed academic papers
behind paywalls to understand these million variations of
portocols, objects, and whatever. Everything should be

as simple and classy as in Java, Python, etc.. All that
should be needed are the existing ISO core module system,
the usual reexport/1 directive, and a new operator (::)/2

for message dispatch. So that for example existing code
can be gradually lifted. Thats all. Well now also the module
dict. But maybe the module dict can be made a little bit

disappear. SWI-Prolog 7 already sits on such a trove. It
effectively works together with reexport/1, and the ('.')/2
has a seamless multi job. The ('.')/2 has a double role,

its also a gateway to the native dict module of SWI-Prolog 7
and at the same time it is used in the defined methods and
in the message dispatch. This is quite elegant.

Let me think whether something can be done in this direction
with the (::)/2 operator, not yet sure. When using the (::)/2
operator we would not need to tweak the ISO core list syntax.

End: Obligatory Logtalk Punch

burs...@gmail.com

unread,
Jun 16, 2018, 9:53:56 AM6/16/18
to
Here is the typical Logtalk job interview:

Q: Do I need some special education for Logtalk
A: Yes it is recommended an extra 2 years PhD

Q: Can I start working with Logtalk after this education
A: No it is recommended two additional extra years practice

Q: Can I write the Python user/age example in Logtalk then
A: No the example doesn't define a protocol first

Q: Why are protocol definitions needed in this example
A: see peer reviewed Logtalk paper "foo" from 1998, with
the comments from peer reviewed Logtalk paper "bar" from
2003, and well you have to also wait for the upcoming
Logtalk paper "baz" submitted for publishing in 2019.

j4n bur53

unread,
Jun 16, 2018, 2:09:31 PM6/16/18
to
Ok, this was a busy saturday, was also doing the color
point for Logtalk. Both SWI-Prolog 7 and Jekejeke Prolog
beat Logtalk in the given example:

Logtalk Result:
?- time((between(1,500000,_), colorpoint(1,2,0)::multiply(3,X),
X::invert(Y), fail; true)).
% 16,500,001 inferences, 2.828 CPU in 2.832 seconds
(100% CPU, 5834254 Lips)
true.

Although we did Logtalk a favor in using argument indexes,
which also results in shorter terms, Logtalk performs
behind Jekejeke Prolog and SWI-Prolog. Logtalk needs 2.83
secs, whereas the dict based example needs 2.31 sec
respectively 1.75 sec in the corresponding other systems.

Maybe new testing in the future shows different results.
Somehow the Jekejeke Prolog and SWI-Prolog dicts payoff.
What I didn't find in Logtalk was a set_parameter/2 builtin,
so maybe the choice of Logtalk solution of the problem
with (=..)/2 gives the slowdown.

We have uploaded the Logtalk version source code of
this test case to Gist. For more info see:

Objects: SWI-Prolog 7 and Jekejeke Prolog are faster than Logtalk
https://plus.google.com/+JanBurse/posts/CNE8ed86SYJ

burs...@gmail.com schrieb:

burs...@gmail.com

unread,
Jun 20, 2018, 10:52:17 AM6/20/18
to
There is nothing like contrived code. There are
only academics who don't understand how
OO-style programming works.

Logtalk presented a different implementation
of the colorpoint problem. In our opinion its
not a fully encapsulated solution, since every
class that extends point would need to write its
own with_point/4 predicate and every class that
extends colorpoint would need to write its own
with_color/3 predicate.

Such a solution is obviously complete nonsense.
No real world OO-system would ever use this
approach. A subclass should be able to autonomically
cooperate with the state of an object.

A subclass need not need to have any knowledge at
all how superclass change the state of an object,
or even help a superclass in any way. This would
blow up practical code immensly.

This last resort method of managing the state of
objects was given us to notice by Paulo Moura himself
and the programming technique is seen here:

https://gist.github.com/pmoura/153a4dde11e12b2d820ab35acacd6e9d

The problem with this programming technique
is this method definition in the class colorpoint,
which deals with something from point:

:- object(colorpoint(_X_,_Y_,_C_),

with_position(X, Y, colorpoint(X, Y, _C_)).

:- end_object.

In the original problem statement, there was no
such method in the class colorpoint.

burs...@gmail.com

unread,
Jun 20, 2018, 10:58:38 AM6/20/18
to
But the "with" programming style is independent
of the two best kept secrets of Prolog. Namely
the "with" programming style is independent of:

- Using reexport/1 for IS-A relationship
- Using some (::)/2 based on (:)/2 for message dispatch

Thats the blind spot of Logtalk. The "with" programming
style can also be used with the best kept secrets
in Prolog. I made already a test with Jekejeke Prolog.

I will soon also make a test with SWI-Prolog and
its dot notation. I have to figure out whether SWI-Prolog
allows the dot notation also with non-dicts to make

a fair comparison. But I guess the same Jekejeke Prolog
code, that uses the best kept secrets of Prolog can
be more or less also used with SWI-Prolog, and

we would still see a little speed up with SWI-Prolog,
since SWI-Prolog is notoriously a little faster than
Jekejeke Prolog. But the results for Jekejeke Prolog

so far are encouraging:

Logtalk on SWI "with" Solution:
0.812 secs

Jekejeke Prolog "with" Solution:
1.073 secs

For more information see here:

Preview: Jekejeke Prolog same speed "with" Solution like Logtalk
https://plus.google.com/+JekejekeCh/posts/5EUPvyyBC9G

burs...@gmail.com

unread,
Jun 20, 2018, 11:01:59 AM6/20/18
to
I guess the SWI7 dot notation could currently
not make the test, since it retrieves the type
tag via the dict builtin:

is_dict(@Term, -Tag): True if Term is a dict of Tag.
http://www.swi-prolog.org/pldoc/doc_for?object=is_dict/2

So to compare with SWI7, we would need to re-implement
(::)/2 in SWI7. I guess this can be done by just
using functor/3 instead of is_dict/2 to get the Tag.

With functor/3 we could provide the same parametric
objects as Logtalk in SWI7, and conclude the benchmark
also for a "with" Solution, concerning the 2 best

kept secrets of Prolog IS-A and (:)/2 dispatch.

burs...@gmail.com

unread,
Jun 20, 2018, 11:34:28 AM6/20/18
to
Ok making a SWI7 dispatcher wasnt so much work. It
shows that SWI7 with 0.712 secs is like 100ms faster
than Logtalk with 0.813 secs.

See also:

Same "with" Solution SWI-Prolog 7 dispatcher beats Logtalk
https://plus.google.com/+JekejekeCh/posts/6YYKsVJ1ab9

burs...@gmail.com

unread,
Jun 21, 2018, 8:12:47 AM6/21/18
to
Maybe @LogtalkDotOrg needs to take a 101 course in
benchmarking. Its still comparing apples with
oranges. It would stop trolling if it would
compare the SWI7 colorpoint/3 solution here
https://twitter.com/janburse/status/1009458896598130689
and not something else.

Normal people would be happy to see that ISO
module standard reexport/1 as IS-A relationship
and ISO module standard (:)/2 as message dispatch
indeed does work and is performant. But
@LogtalkDotOrg doesn't belong to the reasonable
side of the spectrum.

Anyway my demonstration is complete. I have not
planned further demonstrations. All I wanted to
demonstrated was reexport/1 and (:)/2. Of course
there are much more dimensions, how to model
object state, dicts or compounds.

But the object state is not in the scope of my
demonstration. What is the scope of my demonstration
was reexport/1 and (:)/2. I think the colorpoint
is still too small to really only test reexport/1
and (:)/2 and an message dispatch (::)/2 based on it.

A better example would feature a greater taxonomy,
with depth and width, so that we can further investigate
reexport/1 and (:)/2. How they would behave under
more extended conditions. But for a start colorpoint
is Ok, since it does use reexport/1.

But the rest, object state accessors and modifiers,
is not in the scope of my testing. It is part of
colorpoint and makes colorpoint a real challenge,
but this is more accidential. What I wanted to test
was the best kept secret of Prolog:

- rexport/1 as IS-A relationship works
- (:)/2 to implement (::)/2 on top works

burs...@gmail.com

unread,
Jun 21, 2018, 8:24:21 AM6/21/18
to
The problem is that object state is a very large
field. And I dunno whether the ISO module standard
has anything to say here. From the ISO module standard
by using reexport/1 and (:)/2 inside (::)/2 we have

only a mechanism for static and dynamic binding
even in the precense of objects and inheritance. The
reexport/1 by its nature can also deal with with
method overriding, see the SWI7 colorpoint/3 solution.

Thats all!

Everything else is anyway personal preferences based,
I have noticed. I remember when Erlang introduced their
maps, and Richard O'Keefe made fun of setters/getters
in Java, thought that this is something from La La Land.

I don't care whether somebody likes or dislikes
settters/getters, you find it also in Telescript by
General Magic. The reexport/1 and (::)/2 via (:)/2 is
agnostic to whether one likes setters/getters or not.

If you don't like setters and getters, don't do it.
If you like setters and getters you can do it also
with reexport/1 and (::)/2 via (:)/2 as my first
variant of colorpoint benchmark showed.

Then Paulo Moura made another version, using his
"with", and he called the example contrived. But this
is irrelevant whether he likes or dislikes setters/
getters. Because the example is not about setters/getters,

the example is about static and dynamic binding
of method calls, and what role the ISO core module
standard could play here. Anyway you can read how
people value setters/getters here (Its actually old):

[erlang-questions] Fear and Loathing in Programming La La Land
Richard O'Keefe - Thu Mar 29 09:32:33 CEST 2012
http://erlang.org/pipermail/erlang-questions/2012-March/065519.html

Maybe I should also post how Erlang finally did
maps. And maybe one should do a comparison between
maps and SWI7 dicts. But maps and dicts are about
object state mainly, which is independent from

what I propose reexport/1 and (::)/2 via (:)/2.

burs...@gmail.com

unread,
Jun 21, 2018, 8:30:43 AM6/21/18
to
Also a lot of the slightly superficial discussion
by ROK, which somehow deals with syntax, is somehow
relativized, in that by the Pythonesk approach.

we can switch between the following two:

fs.SetFileName("foo/bar.txt");

And the following:

set_title(f, "foo/bar.txt");

Just notice how (::)/2 is implemented in the Pythonesk
approach. What you loose in the later variant is dynamic
binding. But for efficiency, for example if you

know that a method is final, even the interpreter
can choose this variant, and maybe we would also
allow the end-user to choose this variant.

Anyway, setters and getters can be a real shock
depending of the expectations one has, so can be
a lot of OO-programming styles. But I guess the situation

is now a little bit different. Even Python has classes.
But we might still have a look what has become
of the Erlang maps and whether something can be

learnt to model object state.

burs...@gmail.com

unread,
Jun 21, 2018, 1:03:13 PM6/21/18
to
Reexport/1 and (:)/2 proof of concept: Complete
test material was always tweeted. One gist
"with" solution, and other gist dict solution.
With the time to come more tests should be
conducted with deeper and wider taxonomy,
improved or novel ISO module implementations.

Reexport/1 and (:)/2 proof of concept: Who
observed it first? I find for example A.
Pineda and M. Hermenegildo. O'ciao: An
Object Oriented Programming Model for
(Ciao) Prolog. TR CLIP 5/99.0, Facultad
de Informática, UPM, July 1999.
http://oa.upm.es/14764/1/HERME_TCREP_ANDMANS_1999-3.pdf

They explicitly write:
Support for polymorphically module calling
is already present in the form of higher order
(or meta programational) structures.

And then they give a (:)/2 example where the
first argument is a variable.

burs...@gmail.com

unread,
Jun 21, 2018, 1:17:30 PM6/21/18
to
Anybody a pointer to a PDF of this?

Ohki, M., Takeuchi, A., and Furukawa,
K. "An Object Oriented Programming Language
based on the Parallel Logic Programming
Language KL1", In Logic Programming:
Proc. of the 4th Int. Conf., J.L.
Lassez (ed.), MIT Press, Cambridge, MA,
Vol. 2, pp. 894-909. 1988.

burs...@gmail.com

unread,
Jun 21, 2018, 2:06:27 PM6/21/18
to
Last remark: In case somebody is critical
towards using (:)/2 with a first argument,
that is only determined at runtime.

Many Prolog systems will try to optimize
and have a good performance of their system
for this situation anyway.

Why?

Because under the hood of many attribute
variable implementations, here and then
also such a calls are used.

See also here when Ken Asked:
"Please tell me. Is there a DCG, CLP code
written within the ISO-Prolog standard?"
https://groups.google.com/d/msg/comp.lang.prolog/4_2WRm2EXCQ/VgU3XHHdAgAJ

My recommendation was and still is:
When you want CLP, try attribute
variables first. When you want attributed
variables, try modules first.

janb...@easel.ch

unread,
Jun 21, 2018, 6:28:20 PM6/21/18
to
Ha Ha, Paulo Moura called my first example code
smelly. The only smelly thing was his light
yellow scrennshot, which looked like piss.

If you compare two solutions, that use the
same setter and getter granularity, also if
the setter and getter don't do much, you are
comparing apples with apples. With was my
first test case, I only used =... for the
setter, which turned out to

be a speed brake for SWI-Prolog. But there is
nothing wrong with that. In Java and other
programming languages, you often code setters
and getters, even if they don't do a lot. You
do this for various reasons:

- You can use the visibility modifiers of the setters and
getters to regulate what can go out and in of an object.

- This probably doesn't completely translate to parametric
objects, which have their equivalent in Java and Scala
as so called value objects. Usually value objects are
immutable, so they don't have usually setters.

- But by using the name with/n to make a copy (in your case
for a parametric object and not a map), you are in
good company, this is found for example in Erlang:

with(Ks, Map1) -> Map2
http://erlang.org/doc/man/maps.html

- In usually OO-programming, some setters or getters
might exists, so that subclasses override them. We
might even see example code, where some setters
and getters are declared abstract or from an interface.

- The later is no so much required for Prolog VM,
since the dynamic dispatch doesn't need types. But
we would need bigger test examples to test that.
Theoretically I can call anything anytime with any
method I desire. This is even more powerful than
duck typing as found in the Go programming language.

What I am planning to do more on testing, is to test the
colorpoint problem against Java and Scala. Testing against
Scala is especially interesting, since they have pattern
matching, which is in competition with Prolog rules.

Writing a similar value object based code for Java and
Scala could give empirical results what is theoretical
possible, and found at the formost front of virtual methods.
One could of course also try C++ or Python variants

and compare. This would probably give a lower bound
on what a Prolog VM can practically reach in the future,
concering the ISO module required dispatch.

Am Donnerstag, 21. Juni 2018 20:06:27 UTC+2 schrieb burs...@gmail.com:

janb...@easel.ch

unread,
Jun 21, 2018, 6:33:53 PM6/21/18
to
So what I am more planning is to compare
against Java and Scala. On the other hand
Paulo Moura has already provided some

interesting empirical data on comparing
the reexport/1 and (:)/2 idea for some
other Prolog systems.

If I understand correctly, the good performance
could so far only be reproduced for SWI-Prolog.
At least Paulo Moura reports something

to this end here:
"I don't expect a meaningful difference in other
Prolog VMs but I was only able to load Jan
Burse Prolog version on YAP (there his Prolog
version is 6x slower than the Logtalk version
but, given the current beta status of YAP, it's
not wise to draw conclusions from those numbers).
The Prolog version doesn't load (i.e. we get
compilation errors) in ECLiPSe 7.0 #41,
SICStus Prolog 4.4.1 or XSB 3.8.0."
https://groups.google.com/d/msg/swi-prolog/f8LpJN8MYm0/6f3ffsfYCAAJ

Logtalk could provide a "ISO module" option,
and for those Prolog systems that have a good
VM, it could do a different compilation and
directly compile to "ISO modules". Maybe this
would be also an

incentive to Prolog system vendors to advance
their module system. Possibly this would be
only a Logtalk subset that can work with
this option for the time beeing. Current module
systems are most of the time not

advanced enough to support all visibility
modifiers. Maybe in general the ISO module
standard should be a little bit be revived,

janb...@easel.ch

unread,
Jun 21, 2018, 7:15:24 PM6/21/18
to
Ok, I could already complete the Java comparison,
Java is kind of 50-times faster for the color point example:

colorpoint(1,2,0)
colorpoint(3,6,255)
cpcount 1500003, time 16 (ms)

For more information see here:

ColorPoint in Java indicative of what future Prolog VMs could do
https://plus.google.com/+JekejekeCh/posts/G1Pa1EhtXJh
0 new messages