1

I'm learning Prolog and I followed this tutorial for graphs. Here's my code:

path(X, Y, Length, [X,Y], _) :- 
   connect(X, Y, Length).   
path(X, Y, Length, [X|P], V) :- 
   \+ member(X, V),
   connect(X, Z, Length1),
   path(Z, Y, Length2, P, [X|V]),
   Length is Length1 + Length2.

To use this, I call

?- path(a, f, Length, Path, []).

However, I would like to shorten it to:

?- path(a, f, Length, Path).

But I can't get the default parameters to work.

Shon
  • 3,989
  • 1
  • 22
  • 35
Suavocado
  • 949
  • 12
  • 27
  • See [`this definition`](http://stackoverflow.com/q/30328433). – false Mar 10 '16 at 22:12
  • @false I did initially link this very question; however, if the edges have values associated with them, it is only half the answer. I want to use this opportunity to ask: is there a single place where one can find all the great code written by you (and some of the great answers)? Currently it is scattered around the Prolog tag, and I often have trouble finding it even though I know it is somewhere out there... –  Mar 11 '16 at 10:16
  • @Boris: See my profile and [this place](http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/). I plan to put them into a more comprehensive form, but it is much more work than it seems for I try to be conforming in *all* possible respects. – false Mar 11 '16 at 10:50
  • @false Yes, I usually find it by looking at your profile. I realize it is a daunting job, but if you have a website anyway even just dumping a working version of each individual solution with a descriptive name would make it easier to browse and search. I guess doing it properly is about the same as writing a textbook. –  Mar 11 '16 at 10:56
  • @Boris: Ideally, the SO answers should be readily available... – false Mar 11 '16 at 11:03

1 Answers1

6

Quite straight-forward: just define a predicate with the same name that calls the predicate doing the work:

path(X, Y, Length, Path) :-
    path(X, Y, Length, Path, []).

In Prolog, predicates are always referred to with Name/Arity because same name but different arity makes them two separate predicates. So, now your program will have both path/4 and path/5 defined.

As to naming: if both predicates are part of your interface, they should have the same name. Many examples in Prolog standard libraries, for example format/1, format/2, format/3.

If, however, the working predicate is only meant to be used as a helper predicate, usually you give it a suffix. To use something simple as list_max/2:

list_max([X|Xs], Max) :-
    list_max_SUFFIX(Xs, X, Max).

I have seen code where SUFFIX is just an underscore: list_max_/3 (and you keep adding underscores for more helper predicates down the same predicate lineage); or, underscore + number: list_max_1/3 (and you increment the number); or, _aux + optional number, if you have more: list_max_aux/3. Using the underscore + number:

list_max_1([], Max, Max).
list_max_1([X|Xs], Max0, Max) :-
    compare(Order, X, Max0),
    list_max_2(Order, X, Max0, Xs, Max).

list_max_2(<, _, Max0, Xs, Max) :- list_max_1(Xs, Max0, Max).
list_max_2(=, _, Max0, Xs, Max) :- list_max_1(Xs, Max0, Max).
list_max_2(>, X, _, Xs, Max) :- list_max_1(Xs, X, Max).

But wait, there's more. If you use a naming scheme for your predicates where the name represents the arguments, you get for example setup_call_cleanup/3, and call_cleanup/2, defined as setup_call_cleanup(true, Goal, Cleanup). With this naming scheme, you would call your "path" predicates maybe from_to_length_path/4 and from_to_length_path_acc/5. I find this naming scheme nice because it is self-documenting, but as this example shows, it could become excessive if your predicate has too many arguments.