
Brexit: call for collaboration - matchilling
https://www.matchilling.com/brexit-call-for-collaboration/
======
zmonx
Thank you for sharing this! It's nice to see Prolog used for such tasks, which
are a good fit for a logic programming language.

I have one small suggestion that I hope you find useful: Currently, the code
is rather _imperative_ : It contains lots of side-effects that have immediate
consequences which cannot be easily reasoned about. You can use Prolog this
way. However, you forfeit its most interesting advantages if you use it as an
imperative language instead of a declarative one.

A major attraction of Prolog is that it allows you to _declaratively_ describe
what holds. Therefore, I recommend to aim for _declarative_ descriptions of
situations, and limit side-effects to a few isolated areas of your program.

Here is an example: In brexit.pl, you currently have the following:

    
    
        notice_persons_at(Place) :-
                person_at(X, Place),
                write('Apparently '),
                write(X),
                writeln(' is here, that is your'),
                writeln('chance for a quick chat. Type "\e[1mtalk.\e[0m" to start'),
                writeln('start the conversation').
    

Consider formulating this declaratively, for example as follows:

    
    
        notice_persons_at(Place) -->
                { person_at(X, Place) },
                ['Apparently ',X,' is here, that is your ',
                 'chance for a quick chat. Type ', bold(talk), 'to start',
                 ' the conversation'].
    

I am using a Prolog definite clause grammar (DCG) to _describe_ the output
that is expected to occur at this place. Since I am decoupling this
description from the actual side-effect of _emitting_ the output, I have won a
lot of convenience, flexibility and versatility. You see that this description
is shorter and can be used not only for actually emitting the output, but also
to easily _test_ whether the program (still) behaves as intended.

In addition, it allows you to later switch to a different way of outputting
this text altogether. For example, at one point, you may want to convert this
into a web-based application: In that case, the output should no longer be
emitted on the system terminal, but sent as HTML snippets to the client.

Thus, I recommend to first focus on a clear _declarative_ description of
everything that should occur in your program, formulated as a DCG or via a
domain-specific language you may want to design for this specific task of
implementing a text-based game. Later, you can flexibly _interpret_ this
language in any way you want!

The same goes for the uses of assert/1 and rectract/1 that are currently
sprinkled through your code: This imperative style prevents you from using the
predicates in all directions. If you use a more declarative formulation, you
will be able to use the code in much more flexible ways. A declarative way to
express state changes is to think in terms of _relations_ between states.
Think about it this way: There is an initial state, and a user's actions
relate any given state to a new state. Thus, state changes can be modeled as
relations between states, and you will be able to use such predicates _in
reverse_ and also in the _most general_ way!

