As a learning exercise and to create simple examples for myself, I worked through different ways to translate an input list into an output list, and to look at their efficiency using the time clause.
Here’s what I came up with for anyone interested.
:- module(translate, [translate_td/2,
translate_maplist/2,
translate_dcg/2,
translate_acc/2,
translate_q/2,
translate_dl/2
]).
english_spanish("One", "Uno").
english_spanish("Two", "Dos").
english_spanish("Three", "Tres").
english_spanish("Four", "Cuatro").
english_spanish("Five", "Cinco").
english_spanish("Six", "Seis").
english_spanish("Seven", "Siete").
english_spanish("Eight", "Ocho").
english_spanish("Nine", "Nueve").
english_spanish("Ten", "Diez").
%% translate_td(?EnglishList, ?SpanishList) is det
% The traditional, top-down method of iteration in Prolog
translate_td([], []).
translate_td([English|EnglishList], [Spanish|SpanishList]) :-
english_spanish(English, Spanish),
translate_td(EnglishList, SpanishList).
/*
?- time(translate_td(["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], S)).
% 21 inferences, 0.000 CPU in 0.000 seconds (92% CPU, 1561803 Lips)
S = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diaz"].
*/
%% translate_acc(+EnglishList, -SpanishList) is det
% Traditional bottom-up method of iteration, reverses output and is not bidirectional
translate_acc(EnglishList, SpanishList) :-
translate_acc(EnglishList, [], SpanishList).
translate_acc([English|EnglishList], Acc, SpanishList) :-
english_spanish(English, Spanish),
translate_acc(EnglishList, [Spanish|Acc], SpanishList).
translate_acc([], SpanishList, SpanishList).
/*
?- time(translate_acc(["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], S)).
% 22 inferences, 0.000 CPU in 0.000 seconds (93% CPU, 1597792 Lips)
S = ["Diez", "Nueve", "Ocho", "Siete", "Seis", "Cinco", "Cuatro", "Tres", "Dos", "Uno"].
*/
%% translate_dl(+EnglishList, -SpanishList) is det
% Using a difference list.
translate_dl(EnglishList, SpanishList) :-
translate_dl(EnglishList, Q-Q, SpanishList1),
SpanishList-[] = SpanishList1.
translate_dl([], SpanishList, SpanishList).
translate_dl([English|EnglishList], Acc, SpanishList) :-
english_spanish(English, Spanish),
enqueue(Spanish, Acc, Acc1),
translate_dl(EnglishList, Acc1, SpanishList).
enqueue(X, Qh-[X|Qt], Qh-Qt).
/*
?- time(translate_dl(["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], S)).
% 32 inferences, 0.000 CPU in 0.000 seconds (95% CPU, 2000125 Lips)
S = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez"].
*/
%% translate_dcg(+EnglishList, -SpanishList) is det (thanks to cut)
% A simple definite clause grammar example
spanish([Spanish|SpanishList]) --> [English], spanish(SpanishList), { english_spanish(English, Spanish) }.
spanish([]) --> [].
translate_dcg(EnglishList, SpanishList) :-
phrase(spanish(SpanishList), EnglishList), !.
/*
?- time(translate_dcg(["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], S)).
% 31 inferences, 0.000 CPU in 0.000 seconds (95% CPU, 1707519 Lips)
S = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez"].
*/
%% translate_q(+EnglishList, -SpanishList) is det
% using append instead of a difference list is included to show why it's a bad idea
translate_q(EnglishList, SpanishList) :-
translate_q(EnglishList, [], SpanishList).
translate_q([], SpanishList, SpanishList).
translate_q([English|EnglishList], Acc, SpanishList) :-
english_spanish(English, Spanish),
append(Acc, [Spanish], Acc1),
translate_q(EnglishList, Acc1, SpanishList).
/*
?- time(translate_q(["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], S)).
% 77 inferences, 0.000 CPU in 0.000 seconds (95% CPU, 3830465 Lips)
S = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez"].
*/
%% translate_maplist(?EnglishList, ?SpanishList)
% maplist falls under second order programming
translate_maplist(EnglishList, SpanishList) :-
maplist(english_spanish, EnglishList, SpanishList).
/*
?- time(translate_maplist(["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"], S)).
% 23 inferences, 0.000 CPU in 0.000 seconds (93% CPU, 1453948 Lips)
S = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez"].
*/
Also a SWISH notebook.