# Term\_expansion/2 to make Prolog syntax look more like classical FOL

**URL:** <https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389>\
**Category:** Help!\
**Created:** [March 13, 2019, 11:30am UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389 "2019-03-13T11:30:19Z")\
**Posts on this page:** 14\
**Page:** 1

<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:** [March 13, 2019, 11:30am UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/1 "2019-03-13T11:30:19Z")

</div>

Hi!

I am trying to get Prolog code look more like FOL, and I used op/3 and term\_expansion/2 to do this.

```auto
:- op(1200, xfx, ==>).
:- op(1000, xfy, /\).
:- op(1100, xfy, \/).

term_expansion(A ==> B, B:- A).
term_expansion(A /\ B, A, B).
term_expansion(A \/ B, A; B).

man(X) /\ unmarried(X) ==> bachelor(X).

man(john).
man(peter).
unmarried(john).

main:-bachelor(X), writeln(X), nl, fail.

```

But i get the error ERROR: bachelor/1: Undefined procedure: (/)/2  
Exception: (5) man(\_1740)/\unmarried(\_1740) ?

Can anyone help? Thanks!

---

<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:** [March 13, 2019, 12:00pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/2 "2019-03-13T12:00:20Z")

</div>

It is great that are making use of both StackOverflow and this site. It might help others if you included links to your previous [questions](https://stackoverflow.com/users/3170496/jcr) so they can see the history. 🙂

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [March 13, 2019, 1:06pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/3 "2019-03-13T13:06:38Z")

</div>

Note you’re missing parenthesis in your term\_expansion clauses.  
After I corrected them, still /\ and \/ weren’t expanded, so maybe…

```auto
:- module(fol, [main/0]).

:- op(1200, xfx, ==>).
:- op(1000, xfy, /\).
:- op(1100, xfy, \/).

term_expansion(A ==> B, B:- A).
goal_expansion(A /\ B, (A, B)).
goal_expansion(A \/ B, (A; B)).

man(X) /\ unmarried(X) ==> bachelor(X).

man(john).
man(peter).
unmarried(john).

main:-bachelor(X), writeln(X), nl, fail.

```

It yields an answer now:

```auto
?- main.
john

```

---

<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:** [March 13, 2019, 2:00pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/4 "2019-03-13T14:00:59Z")

</div>

Thanks, perfect.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 13, 2019, 2:17pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/5 "2019-03-13T14:17:09Z")

</div>

> [@JCR](#):
>
> :- op(1200, xfx, ==\>). :- op(1000, xfy, /). :- op(1100, xfy, /).

If do it nice you do of course like this 🙂

```prolog
:- op(1200, xfx, ⇒).
:- op(1000, xfy, ∧).
:- op(1100, xfy, ∨).

```

---

<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:** [March 13, 2019, 4:01pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/6 "2019-03-13T16:01:50Z")

</div>

@jan Even better 🙂 But i got the error “Illegal character” using ⇒, ∧, and ∨.

By they way, thank you very much for making SWI!

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 13, 2019, 4:15pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/7 "2019-03-13T16:15:53Z")

</div>

You need Unicode support. The above works fine on my Ubuntu machine which since long defaults to using UTF-8. SWI-Prolog picks up the default locale, at least on most Unix-like systems. So, what is your setup? OS? Locale settings? Editor? It may all matter. You get a reliable result on any system if you can use an editor that can add a Unicode BOM marker at the start of the file.

You can find Prolog’s idea of the encoding using

```
?- current_prolog_flag(encoding, E).

```

That is either some encoding name or `text`, meaning it doesn’t understand what the encoding is, but it relies on the C library to translate the input and output to Unicode.

---

<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:** [March 13, 2019, 4:18pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/8 "2019-03-13T16:18:33Z")

</div>

> [@jan](#):
>
> ?- current\_prolog\_flag(encoding, E).

Aha, OK. I get E = text. in response to the current\_prolog\_flag query. I have MacOs 10.13.6 and use Sublime text as an editor (and to run code).

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 13, 2019, 4:29pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/9 "2019-03-13T16:29:40Z")

</div>

Now things get complicated ☹ It differs whether using the window app from the binary distribution or the `swipl` console app. Otherwise I just hope someone has the answer. I only have a 12 year old Mac on which I (very slowly) compile SWI-Prolog …

---

<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:** [March 13, 2019, 5:54pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/10 "2019-03-13T17:54:43Z")

</div>

I’ll probably find some solution, thanks for your help!

---

<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:** [August 29, 2019, 8:12pm UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/11 "2019-08-29T20:12:01Z")

</div>

For the sake of completeness, here is an example that brings together your suggestions:

```
:- op(1200, xfx, ⇒).
:- op(1000, xfy, ∧).
:- op(1100, xfy, ∨).
:- op(900, fy, ¬).
term_expansion(A ⇒ B, B:- A).
goal_expansion(A ∧ B, (A, B)).
goal_expansion(A ∨ B, (A; B)).
goal_expansion(¬A, \+A).

man(john).
unmarried(mark).
unmarried(X) ∧ man(X) ⇒ bachelor(X).

main:-unmarried(X), writeln(X).

```

The solution to the Illegal character error in Sublime text is: using Save with Encoding -\> UTF-8 with BOM in Sublime text.

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [August 30, 2019, 4:18am UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/12 "2019-08-30T04:18:39Z")

</div>

On linked-in someone asked to provide examples of code for counting from one to twenty.

I decided to add the following code, while encouraging a declarative reading:

forall(between(1,20,X), writeln(X)).

However, someone then asked from where the order comes from.

Which actually showed how the procedural reading “lurks” behind the scene …

Dan

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [August 30, 2019, 5:25am UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/13 "2019-08-30T05:25:05Z")

</div>

> [@grossdan](#):
>
> someone then asked from where

I understand that person, by myself did the same question, and was amazed by the implementation 🙂 .

Then, library(aggregate) with foreach/2 come into play. Maybe that’s more an interesting showcase of a round trip into procedural programming.

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [August 30, 2019, 5:58am UTC](https://swi-prolog.discourse.group/t/term-expansion-2-to-make-prolog-syntax-look-more-like-classical-fol/389/14 "2019-08-30T05:58:30Z")

</div>

> [@CapelliC](#):
>
> Maybe that’s more an interesting showcase of a round trip into procedural programming.

Here is a trial without assuming order …

bagof(X, between(1,20,X), Xs), sort(Xs, SortedXs), maplist(writeln, SortedXs).

Although, it is declarative, somehow the declarative reading is lost … i like the use of forall hinting at the universal quantifier – the term sort is in imperative language – and maplist is also imperative in flavor …

Dan
