# Recursive travel

**URL:** <https://swi-prolog.discourse.group/t/recursive-travel/1281>\
**Category:** Help!\
**Tags:** discussion\
**Created:** [September 18, 2019, 10:51am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281 "2019-09-18T10:51:53Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 18, 2019, 10:51am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/1 "2019-09-18T10:51:53Z")

</div>

I am doing the exercise travel (byCar, byPlane, byTrain) on this Learn Prolog now page: [LPN section 3.4](http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse12).

My code looks like this:

```prolog
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).

byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).

byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).

travel(X,Y):-byCar(X,Y); byTrain(X,Y); byPlane(X,Y).
travel(X,Z) :-
  (byCar(X,Y); byTrain(X,Y); byPlane(X,Y)),
  (byCar(Y,Z); byTrain(Y,Z); byPlane(Y,Z)).

```

I figured if you can travel from a place by car, train or plane, it should return true.  
And that another condition would be that if you can travel from X to Y by car, train or plane, **and then** from Y to Z by by car, train or plane, it should also return true.  
Unfortunately this does not work. What am I doing wrong?  
Thank you!

---

<div class="post-metadata">

**Author:** ![Ian](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ian/32/1026_2.png) [@Ian](https://swi-prolog.discourse.group/u/Ian)\
**Post date:** [September 18, 2019, 11:07am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/2 "2019-09-18T11:07:42Z")

</div>

Your travel predicate has a maximum length of 2 trips, so it cannot find the much longer journey of valmont to raglan. If you calculate how to get from valmont to raglan by hand, you will see the journey is : valmont-\>saarbruecken-\>frankfurt-\>singapore-\>auckland-\>hamiltion-\>raglan which is 6 trips.

Strangely you named the topic recursive travel, yet your travel definition is not recursive 😃

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 18, 2019, 11:09am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/3 "2019-09-18T11:09:02Z")

</div>

But on the second definition of travel, I extend it to 3 trips, via Y. Is it not enough?

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 18, 2019, 11:33am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/5 "2019-09-18T11:33:50Z")

</div>

Of course.  
Thank you for looking at my code.  
Prolog responds false to the query :

```prolog
travel(valmont,raglan).

```

It should respond true.

---

<div class="post-metadata">

**Author:** ![Ian](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ian/32/1026_2.png) [@Ian](https://swi-prolog.discourse.group/u/Ian)\
**Post date:** [September 18, 2019, 12:12pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/6 "2019-09-18T12:12:08Z")

</div>

You probably should reread [http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse9](http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse9) and the section Example 2. Descendant to give you an idea on how to fix your code.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 18, 2019, 12:15pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/7 "2019-09-18T12:15:07Z")

</div>

The bigest problem with your code is this predicate

```prolog
travel(X,Z) :-
  (byCar(X,Y); byTrain(X,Y); byPlane(X,Y)),
  (byCar(Y,Z); byTrain(Y,Z); byPlane(Y,Z)).

```

When I think about traversing graphs I think of a start node `O` and then a series of connector with a node, `-O`. So a path would be `O-O`, or `O-O-O-O`, etc. In other words you start with `O`, then recursively add `-O`.

The recursive predicate above is `O-O`, when it should be `-O`

Here is the code I used to solve the problem.

The big change for this code is that it passes a state variable around to hold the path, e.g. `Path0`, `Path1`,`Path`. Since the real work is done by a predicate needing two variables to hold the state variables, and the query only needs one variable to return the path, the predicate with two variables is a helper predicate and the query predicate calls the helper predicate.

The other big change is that there needs to be a way to avoid adding a city to the path if you have already been to that city, i.e. `\+ member((_,Y),Path0)`

```prolog
travel_01(X,Y,Path) :-
    travel_01_helper(X,Y,[(start,X)],Path0),
    reverse(Path0,Path).

travel_01_helper(X,Y,Path0,[(Mode,Y)|Path0]) :-
    (
        (byCar(X,Y),Mode = car)
    ;
        (byTrain(X,Y),Mode = train)
    ;
        (byPlane(X,Y),Mode = plane)
    ),
    \+ member((_,Y),Path0).
travel_01_helper(X,Z,Path0,Path) :-
    (
        (byCar(X,Y),Mode = car)
    ;
        (byTrain(X,Y),Mode = train)
    ;
        (byPlane(X,Y),Mode = plane)
    ),
    travel_01_helper(Y,Z,[(Mode,Y)|Path0],Path).

```

Example run:

```prolog
?- travel_01(valmont,raglan,Path).
Path = [(start, valmont), (car, saarbruecken), (train, frankfurt), (plane, bangkok), (plane, auckland), (car, hamilton), (car, raglan)] ;
Path = [(start, valmont), (car, saarbruecken), (train, frankfurt), (plane, singapore), (plane, auckland), (car, hamilton), (car, raglan)] ;
Path = [(start, valmont), (car, saarbruecken), (train, paris), (plane, losAngeles), (plane, auckland), (car, hamilton), (car, raglan)] ;
Path = [(start, valmont), (car, metz), (train, frankfurt), (plane, bangkok), (plane, auckland), (car, hamilton), (car, raglan)] ;
Path = [(start, valmont), (car, metz), (train, frankfurt), (plane, singapore), (plane, auckland), (car, hamilton), (car, raglan)] ;
Path = [(start, valmont), (car, metz), (train, paris), (plane, losAngeles), (plane, auckland), (car, hamilton), (car, raglan)] ;
false.

```

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 18, 2019, 12:36pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/8 "2019-09-18T12:36:11Z")

</div>

It’s very beautifully written :).  
I am not yet familiar with lists and other terms you are using, so I need more time to really get it.  
But still the query should return true?

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 18, 2019, 12:48pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/9 "2019-09-18T12:48:31Z")

</div>

> [@DaJa](#):
>
> But still the query should return true?

You have a lot to learn about logic programming. 😉

In other programming languages, they return a result, and the result holds a value.

Prolog is a logic programming language which means that the only result of a [predicate](https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)) is true or false. However, Prolog can also [bind](https://en.wikipedia.org/wiki/Free_variables_and_bound_variables) a free/unbound variable.

Now if we run the query (predicate) and press Enter after the first result, it does not show true, but the value bound to the variable `Path`.

```prolog
?- travel_01(valmont,raglan,Path).
Path = [(start, valmont), (car, saarbruecken), (train, frankfurt), (plane, bangkok), (plane, auckland), (car, hamilton), (car, raglan)] .

```

If you add this predicate

```prolog
travel_01_a(X,Y) :-
    travel_01(X,Y,_).

```

which will just take the result of the previous query and not show the `Path` value, you will get

```prolog
?- travel_01_a(valmont,raglan).
true .

```

Which is what you seek, `true`.

So the code I gave you that returned

```prolog
Path = [(start, valmont), (car, saarbruecken), (train, frankfurt), (plane, bangkok), (plane, auckland), (car, hamilton), (car, raglan)] .

```

was returning `true` but SWI-Prolog was not displaying `true`. When I suppressed the display of the bound variables, then SWI-Prolog showed the result of just the predicate.

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 18, 2019, 12:50pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/10 "2019-09-18T12:50:39Z")

</div>

> [@EricGT](#):
>
> You have a lot to learn about logic programming. 😉

Haha, so true. I started today.

Thank you for the explanation, I think I need to let it marinate it in my brain for a while.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 18, 2019, 12:57pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/11 "2019-09-18T12:57:42Z")

</div>

> [@DaJa](#):
>
> marinate

Many here do not speak English as a native language and so using such phrases/[metaphors](https://examples.yourdictionary.com/metaphor-examples.html) might cause them confusion. I myself use such phrases/metaphors often but when I do I find the definition that explains it so the others are not confused.

[marinate](https://www.urbandictionary.com/define.php?term=marinate) as opposed to [marinate](https://www.merriam-webster.com/dictionary/marinate)

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 18, 2019, 1:02pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/12 "2019-09-18T13:02:27Z")

</div>

Sorry, it is not considered as a difficult word in my language (I am not a native English speaker either) so I did not think about that.  
It is a cusine term and means put your vegetable in a sauce overnight. By extension, thinking/pondering a long time over an idea.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 18, 2019, 1:05pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/13 "2019-09-18T13:05:08Z")

</div>

> [@DaJa](#):
>
> Sorry

No need to be sorry Just giving some friendly advise.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 18, 2019, 1:11pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/14 "2019-09-18T13:11:11Z")

</div>

Since you are just learning and using LPN, you may not know this, but many others before you have used LPN to learn Prolog and have posted their notes on GitHub, ([example](https://github.com/dragonwasrobot/learn-prolog-now-exercises/blob/2d09a035f094a8d635c51e51c656733b4883e19f/chapter-03/practical-session.pl))

You can search GitHub for Learn Prolog Now ([search](https://github.com/search?q=learn+prolog+now))

Their answers may be more in line with what you seek as they don’t know all of the Prolog options available to them. 😃

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [September 18, 2019, 1:46pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/15 "2019-09-18T13:46:39Z")

</div>

> [@EricGT](#):
>
> [marinate](https://www.urbandictionary.com/define.php?term=marinate) as opposed to [marinate](https://www.merriam-webster.com/dictionary/marinate)

This is the exact same word in two different dictionaries. The definition in urban dictionary is bound to be a metaphor.

Now that I mentioned it, I remembered:  
 ![metafores](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/1X/d8cf30103067499e2eb05aae42803e6a4cd8804d.jpeg)

---

<div class="post-metadata">

**Author:** ![JCR](https://avatars.discourse-cdn.com/v4/letter/j/258eb7/32.png) [@JCR](https://swi-prolog.discourse.group/u/JCR)\
**Post date:** [September 18, 2019, 2:48pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/16 "2019-09-18T14:48:10Z")

</div>

Here a simpler solution without lists, if you want to learn this later (it does not return transportation mode) 🙂

`anyPath(X, Y)` is recursive, which takes a while to understand (it took me several months); i think there is a good explanation on learn prolog now.

```
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).

byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).

byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).

directPath(X, Y):-
    byCar(X, Y);
    byTrain(X, Y);
    byPlane(X, Y).
anyPath(X, Y):-
    directPath(X, Y).
anyPath(X, Y):-
    directPath(X, Z),
    anyPath(Z, Y).
```

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 19, 2019, 9:12am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/17 "2019-09-19T09:12:01Z")

</div>

@JCR Yes, recursion is still hurting my brain. But at the same time it’s so beautiful 🌹!

@EricGT I traced through your code this morning, very very neat. Please allow me to take some more of your time with some last questions!

```prolog
travel_01(X,Y,Path) :-
    travel_01_helper(X,Y,[(start,X)],Path0),
    reverse(Path0,Path).

```

So you assign the current location to Path0, and the one we are seeking to Path?  
When does transportation mode is becoming to Path?

```prolog
travel_01_helper(X,Y,Path0,[(Mode,Y)|Path0]) :-
    (
        (byCar(X,Y),Mode = car)
    ;
        (byTrain(X,Y),Mode = train)
    ;
        (byPlane(X,Y),Mode = plane)
    ),
    \+ member((_,Y),Path0).

```

I don’t understand this syntas +, even though I checked the Prolog dictionary:  
[https://www.swi-prolog.org/pldoc/man?predicate=\%2B/1](https://www.swi-prolog.org/pldoc/man?predicate=%5C%2B/1)

Also, I don’t really get what gets saved in the first occurence of Path0 (outside of the list), and Path0 inside of the list.

```prolog
travel_01_helper(X,Y,Path0,[(Mode,Y)|Path0]) :-

```

Thank you in advance for any answer. There is a lot going on for me in that recursion…

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 19, 2019, 10:15am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/18 "2019-09-19T10:15:34Z")

</div>

> [@DaJa](#):
>
> I don’t understand this syntax \+, even though I checked the Prolog dictionary:  
> [\+](https://www.swi-prolog.org/pldoc/man?predicate=%5C%2B/1)

`\+` is logical not. e.g.  
if the predicate result is true then use not true, which is false.  
if the predicate result is false then use not false, which is true.

`member((_,Y),Path0).` can be understood as follows.

`Path0` will look like `[(start, valmont), (car, saarbruecken), (train, frankfurt), (plane, bangkok)]` which is a list.  
Each item in the list will be `(Mode, Location)` and `(_,Y)` is a pattern to match against each item in the list. [member/2](https://www.swi-prolog.org/pldoc/man?predicate=member/2) will do the matching of the pattern against each item in the list.

`Y` is the `Location`, e.g. `valmont`, most recently added to the end of the list, so `member((_,Y),Path0)` reads the predicate is true when the the Location in Y is the same as any Location in Path0. Which means that if the last location added matches any in the current path then the result is true. But `\+` is not so, when the last location added already exist in the list is found, then the line `\+ member((_,Y),Path0)` will return false and the entire clause will fail.

```prolog
travel_01_helper(X,Y,Path0,[(Mode,Y)|Path0]) :-
    (
        (byCar(X,Y),Mode = car)
    ;
        (byTrain(X,Y),Mode = train)
    ;
        (byPlane(X,Y),Mode = plane)
    ),
    \+ member((_,Y),Path0).`

```

so the next clause will be tried

```prolog
travel_01_helper(X,Z,Path0,Path) :-
    (
        (byCar(X,Y),Mode = car)
    ;
        (byTrain(X,Y),Mode = train)
    ;
        (byPlane(X,Y),Mode = plane)
    ),
    travel_01_helper(Y,Z,[(Mode,Y)|Path0],Path).

```

Ask more questions if that is still not clear.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 19, 2019, 10:48am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/19 "2019-09-19T10:48:38Z")

</div>

> [@DaJa](#):
>
> Also, I don’t really get what gets saved in the first occurence of Path0 (outside of the list), and Path0 inside of the list.
> 
> ```prolog
> travel_01_helper(X,Y,Path0,[(Mode,Y)|Path0]) :-
> 
> ```

The easiest way to find this out is to use either [trace/0](https://www.swi-prolog.org/pldoc/man?predicate=trace/0) or [gtrace/0](https://www.swi-prolog.org/pldoc/man?predicate=gtrace/0). Since gtrace/0 is rather complex being a GUI, I will just use trace for this example.

```prolog
?- trace.
true.

[trace] ?- travel_01(valmont,frankfurt,Path).
   Call: (10) travel_01(valmont, frankfurt, _4260) ? creep
   Call: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], _4520) ? 

```

As you can see trace has shown the call to travel\_01\_helper/4 with the arguments used as input bound, and the augment used as output unbound. `_4520` is a system generated variable which is unbound.

For simple goals, trace/0 can be used with protocol/1. See: [Wiki: How to - protocol/1](https://swi-prolog.discourse.group/t/wiki-how-to-protocol-1/675)

```prolog

?- set_prolog_flag(color_term,false).
true.

?- current_prolog_flag(color_term,X).
X = false.

?- working_directory(_,"C:/Users/Eric/Documents/Prolog").
true.

?- leash(-all),visible(+all).
true.

?- protocol("./trace_output.txt").
true.

?- trace.
true.

[trace] ?- travel_01(valmont,frankfurt,Path).
   Call: (10) travel_01(valmont, frankfurt, _596)
   Unify: (10) travel_01(valmont, frankfurt, _596)
   Call: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], _856)
   Unify: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], [(_842, frankfurt), (start, valmont)])
   Call: (12) byCar(valmont, frankfurt)
   Fail: (12) byCar(valmont, frankfurt)
   Redo: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], [(_842, frankfurt), (start, valmont)])
   Call: (12) byTrain(valmont, frankfurt)
   Fail: (12) byTrain(valmont, frankfurt)
   Redo: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], [(_842, frankfurt), (start, valmont)])
   Call: (12) byPlane(valmont, frankfurt)
   Fail: (12) byPlane(valmont, frankfurt)
   Redo: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], _856)
   Unify: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], _856)
   Call: (12) byCar(valmont, _852)
   Unify: (12) byCar(valmont, saarbruecken)
   Exit: (12) byCar(valmont, saarbruecken)
   Call: (12) _850=car
   Exit: (12) car=car
   Call: (12) travel_01_helper(saarbruecken, frankfurt, [(car, saarbruecken), (start, valmont)], _868)
   Unify: (12) travel_01_helper(saarbruecken, frankfurt, [(car, saarbruecken), (start, valmont)], [(_854, frankfurt), (car, saarbruecken), (start, valmont)])
   Call: (13) byCar(saarbruecken, frankfurt)
   Fail: (13) byCar(saarbruecken, frankfurt)
   Redo: (12) travel_01_helper(saarbruecken, frankfurt, [(car, saarbruecken), (start, valmont)], [(_854, frankfurt), (car, saarbruecken), (start, valmont)])
   Call: (13) byTrain(saarbruecken, frankfurt)
   Unify: (13) byTrain(saarbruecken, frankfurt)
   Exit: (13) byTrain(saarbruecken, frankfurt)
   Call: (13) _854=train
   Exit: (13) train=train
   Call: (13) lists:member((_860, frankfurt), [(car, saarbruecken), (start, valmont)])
   Unify: (13) lists:member((_860, frankfurt), [(car, saarbruecken), (start, valmont)])
   Fail: (13) lists:member((_860, frankfurt), [(car, saarbruecken), (start, valmont)])
   Redo: (12) travel_01_helper(saarbruecken, frankfurt, [(car, saarbruecken), (start, valmont)], [(train, frankfurt), (car, saarbruecken), (start, valmont)])
   Exit: (12) travel_01_helper(saarbruecken, frankfurt, [(car, saarbruecken), (start, valmont)], [(train, frankfurt), (car, saarbruecken), (start, valmont)])
   Exit: (11) travel_01_helper(valmont, frankfurt, [(start, valmont)], [(train, frankfurt), (car, saarbruecken), (start, valmont)])
   Call: (11) lists:reverse([(train, frankfurt), (car, saarbruecken), (start, valmont)], _596)
   Unify: (11) lists:reverse([(train, frankfurt), (car, saarbruecken), (start, valmont)], _596)
   Exit: (11) lists:reverse([(train, frankfurt), (car, saarbruecken), (start, valmont)], [(start, valmont), (car, saarbruecken), (train, frankfurt)])
   Exit: (10) travel_01(valmont, frankfurt, [(start, valmont), (car, saarbruecken), (train, frankfurt)])
Path = [(start, valmont), (car, saarbruecken), (train, frankfurt)] .

[trace] ?- nodebug.
true.

?- noprotocol.
true.

?- 

```

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 19, 2019, 10:58am UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/20 "2019-09-19T10:58:37Z")

</div>

> [@DaJa](#):
>
> When/how is transportation mode added to Path?
> 
> ```prolog
> travel_01_helper(X,Y,Path0,[(Mode,Y)|Path0]) :-
> (
> (byCar(X,Y),Mode = car)
> ;
> (byTrain(X,Y),Mode = train)
> ;
> (byPlane(X,Y),Mode = plane)
> ),
> \+ member((_,Y),Path0).
> 
> ```

The details can be seen by using trace/0 with protocol/1 as noted in the earlier post. Here I will just explain the details without showing the code or the trace.

The predicate travel\_01\_helper/4 is entered on the first line with the first three arguments bound, so `[(Mode,Y)|Path0]` is not fully bound but, `Y` and `Path0` are bound because they were bound when the predicate was entered.

Next there are thee possibilities for the next statement because of the use of `;`. When one of the three predicates, e.g. `byCar(X,Y)` succeeds/returns true, then the next predicate is called, e.g. `Mode = car` and via unification [=/2](https://www.swi-prolog.org/pldoc/man?predicate=%3D/2), the unbound variable `Mode` is bound to the value.

In the example `Mode = car`, `=/2` is used as an infix operator as opposed to a prefix operator.

```prolog
?- Mode = car.
Mode = car.

?- =(Mode,car).
Mode = car.

```

* * *

If you want to look at other somewhat simple Prolog examples see [RosettaCode](http://rosettacode.org/wiki/Rosetta_Code) - [Prolog](http://rosettacode.org/wiki/Category:Prolog)

For other useful links see: [Useful Prolog references](https://swi-prolog.discourse.group/t/useful-prolog-references/1089)

---

<div class="post-metadata">

**Author:** ![DaJa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/daja/32/574_2.png) [@DaJa](https://swi-prolog.discourse.group/u/DaJa)\
**Post date:** [September 19, 2019, 5:56pm UTC](https://swi-prolog.discourse.group/t/recursive-travel/1281/21 "2019-09-19T17:56:08Z")

</div>

Hello again!

I still need time to process (= think about it).

You wrote:

> [@EricGT](#):
>
> `Y` is the `Location` , e.g. `valmont` , most recently added to the end of the list, so `member((_,Y),Path0)` reads the predicate is true when the the Location in Y is the same as any Location in Path0. Which means that if the last location added matches any in the current path then the result is true. **But `\+` is not so, when the last location added already exist in the list is found, then the line `\+ member((_,Y),Path0)` will return false and the entire clause will fail.**

Can you please elaborate (=explain more). Why would the whole close fail if we happened to already have traversed Valmont? Could we not have traversed Valmont by car to Amsterdam, and later in the list traversed Valmont again but by plane, to Hambourg?

Also, which English words am I supposed to explain? What is the rule of thumb?

[Next page](https://swi-prolog.discourse.group/t/recursive-travel/1281.md?page=2)
