Why use / as a data delimiter?

Bratko section 4.4 shows an example for building a (simple) travel agent app, where you can query it for flight info.

He sets up a flight predicate as follows…

timetable(edinburgh, london,
  [
    % dep time / arr time / flight number / days
    9:40 / 10:50 / ba4733 / alldays,
    13:40 / 14:50 / ba4773 / alldays,
    19:40 / 20:50 / ba4833 / [mo,tu,we,th,fr,su]
  ]).

I’m puzzled why he used / to delimit the pieces of data in the list. Earlier on, when building a family database, he used a functor (is that the right word?) as follows…

person(jim, spriggs, date(9,may,1968), works(tesco,8500)).

Isn’t this a clearer way to set up the data? What does he gain by using / over a functor?

Thanks

1 Like

Using this format is indeed less efficient than using a functor:

?- write_canonical(9:40 / 10:50 / ba4733 / alldays).
:(9,:(/(40,10),/(/(50,ba4733),alldays)))

However, it’s easier to read and might have some advantages (e.g., Hour:Minute = 9:40 does what you’d expect).

Does this small amount of efficiency change matter? Probably not. But in general, I prefer a simple functor.

For a readable way of accessing fields in a functor, see library(record).
Also, SWI-Prolog’s extension of “dicts” can make things readable:

person{first:jim, last:spriggs, day:9, month:may, year:1960, works:tesco, salary:8500}

Some people use “comma lists”, but that’s usually considered bad style. Also, some people use regular lists, but that doesn’t make much sense for fixed-length things:

?- write_canonical((jim, spriggs, (9,may,1968), (tesco,8500))). % bad
','(jim,','(spriggs,','(','(9,','(may,1968)),','(tesco,8500))))

% [jim, spriggs, [9,may,1968], [tesco,8500]]  % also bad
3 Likes

Bratko wrote the book ages ago. There weren’t that many people with too much Prolog programming experience back then. Implementations were different, too. So in many cases any differences between what is in the book and what you find in the wild could be explained with “the tooling is different” or “we know better now”.

If we really know better is an open question.

A small example of what I mean:

So here, I would say we now know better and write date(1968, 5, 9) so that the standard order of terms also sorts dates correctly. But we also have date and time predicates in the standard library to make it even less of a choice what to do.

Another confusing common issue is how difference lists are treated. From memory, authors would use List-Tail, or sometimes List/Tail or List\Tail, while today you mostly see List, Tail (as separate variables).

1 Like

It looks like you may learn a lot from Bratko…but not “good style” :sweat_smile: you’re not learning modern Prolog…what you are doing is possibly more akin to archeology than to computer programming…but maybe it has some value too :roll_eyes:

1 Like

I won’t judge the style of Bratko (though this is not a particularly good example). For learning style, I guess “The Craft of Prolog” is probably the best option. I only read the original edition (1990). Seems the current edition is from 2009 and I’d assume it now uses ISO. I would be surprised if it covered things such as modules, constraints or tabling though :frowning:

Still, if you want to approach Prolog with an engineering mindset and think “pure” is nice but not always required it is probably still worth reading.

Another good source are the libraries :slight_smile: Unfortunately some stuff is there is also old and there are some dirty tricks or use of low-level built-ins that obfuscate the beauty :frowning:

3 Likes

Thanx for the suggestions. I don’t know if I want to go so deep with the technical details. “The craft of prolog” is another classic I’ve heard about, but I’ve also read that is somewhat advanced and possibly dealing in depth with things I may not be interested in (NLP was the starting point and possibly still a good guiding star for my interest in these things). Maybe the libraries are a more accessible way to approach the more recent developments :pray:t2:

Its loooong ago that I read it. I recall it touches two things really well: when and where to use cuts and choosing the right data structure. There is surely a lot more in The Craft of Prolog, but these two things are still in my mind.

Thanks for the clear reply. I’m not too worried about efficiency at my stage of learning Prolog, I’m more interested in understanding how to write good code that works. Making it efficient is something to keep an eye on, but something I wouldn’t worry too much about at this stage.

My main thought was how this even works. Most of my programming has been with C-style languages, where operators such as / have a specific job, ie to evaluate their arguments and return a value. From that point of view, his code looked weird.

Having thought about it some more, I have a suspicion about how it may work, but would like to know if I’m right.

Am I right in thinking that an operator in Prolog is just like any other functor, meaning that just like I can write…

parent(jim, john).

…I could create an operator parent and write…

jim parent john

(which is probably not a great example, as the first way was clearer, but I hope you see what I mean!)

Bratko mentions that with few exceptions, operators don’t evaluate their arguments, which makes me wonder if there is really any difference between an operator and a regular predicate, other than the convenience of writing 1 + 2 as opposed to +(1, 2)

Any comments? Thanks again

1 Like

Hmm, which makes me wonder if I’m using the right book. I started off with Clocksin & Mellish, simple because my all-too brief experience with Prolog about 35 years ago was based on that book. I got the impression that it was out of date, and was looking around for something newer, and thought I’d found it in Bratko. Seems not.

To be clear, as much as I would like to, I don’t ever see myself as an expert Prolog programmer. I just don’t have enough time to invest in it, given that I’m not likely to make such a big career change at my stage in life. I’m doing this for the fun of it, and to expand my mind by seeing different programming paradigms (I’m learning Lisp for the same reason). I wonder if Bratko is far enough off the modern line that I should switch, or if it’s close enough that I can iron out the rough spots as I go along? I do find the book clear.

Thanks again for the reply.

1 Like

No operator evaluates its arguments. Some predicate do something with the term defined by an operator may also do something with the arguments. So, in

?- A is +(1,*(2,3)).

is/2 is defined to evaluate the arithmetic expression bottom up (first evaluating the arguments of the expression and then the expression itself.

And yes, it is just syntactic sugar. Just consider X-Y. Given to is/2 it is arithmetic minus, but given to library(pairs) it denotes just a (key/value) pair.

You’ve still got the slight ambiguity of: Is jim the parent of john, or is john the parent of jim?

Personally, I’ve never had any inclination whatsoever to mess with operators. This is clear:

child_parent(jim, john).
1 Like

You are the master of writing and deleting :sweat_smile:

Perhaps it helps to think of Prolog as “everything is quoted (unless it’s a goal)” vs Python/Lisp/etc “everything is evaluated (unless it’s quoted)”.

So (1==1) == true – as a goal – is asking whether the term 1==1 is the same as the term true; and of course it isn’t. On the other hand (1==1) == ==(1,1) because 1==1 and ==(1,1) are just two different ways of writing the same term (and a third way: '=='(1,1)).

1 Like

Completely agreed, which is why I said it wasn’t a good example :grin:

It was the first one that came into my head, not intended as a fine example of a useful operator :blush:

Ah, I’m glad to hear you say that, because I have been struggling with the idea of operators. I can see that there are cases where they would be useful (like defining : to make time clearer), but for the most part, functors seem clearer to me.

Thanks again