Erlang "ping pong" concurrent programming example translated into SWI Prolog

Here’s the code with the thread PIDs doubling as message queue PIDs to save a few lines and arguments:

ping(0, Pong_PID) :-
    thread_send_message(Pong_PID, 'finished'),
    format("Ping finished~n", []), !.

ping(N, Pong_PID) :-
    thread_self(Ping_PID),
    thread_send_message(Pong_PID, msg('Ping', Ping_PID)),
    thread_get_message(Ping_PID, Msg),
    format("Ping received ~w~n", [Msg]),
    succ(M, N),
    ping(M, Pong_PID).

pong :-
    repeat,
    thread_get_message(Msg),
    (    Msg \== 'finished'
    ->   msg(Ping, Ping_PID) = Msg,
         format("Pong received ~w~n", [Ping]),
         thread_send_message(Ping_PID, 'Pong'),
         fail
    ;    format("Pong finished~n", []),
         !
    ). 

start :-
    thread_create(pong, Pong_PID),
    thread_create(ping(3, Pong_PID), Ping_PID),
    thread_join(Pong_PID),
    thread_join(Ping_PID).

A reason I prefer the original, more verbose version comes from watching some Youtube lectures given by Joe Armstrong, Alan Kay, Carl Hewitt etc who stressed that message queues were originally a core part of object oriented programming as well as parallel programming – a key idea which somehow got lost in modern, popular programming.

I also prefer placing anything resembling a stream within setup_call_cleanup/3 which this more terse version doesn’t lend itself to.