Using the DCG Prolog to Find and Replace - Code Overview

I came to the following code to replace all Find w / Replace occurrences in Request and put the answer in Result . It uses DCG, therefore they are all lists of character codes. The predicate that will use the client code will be substitute .

 findReplace(_, _, [], []) --> []. % The end. findReplace(Find, Replace, Result, ResultRest) --> Find, % Found Find. { append(Replace, Intermediate, Result) }, % Put in Replace in Find place. !, % Make sure we don't backtrack & interpret Find as the next case. findReplace(Find, Replace, Intermediate, ResultRest). findReplace(Find, Replace, [ C | Intermediate ], ResultRest) --> [ C ], % Any other character. findReplace(Find, Replace, Intermediate, ResultRest). substitute(Find, Replace, Request, Result):- phrase(findReplace(Find, Replace, Result, []), Request). 

This works in SWI-Prolog. Does anyone have any comments on how I could improve it? I am learning how to use DCG and difference lists. For example, I put it in a cut so that after finding Find prolog never backs off and interprets this as a regular character in the case of [ C ] . Is this necessary, or is there a more declarative way to do this?

Another question is whether there is already a predicate that does the same thing as a substitution, perhaps on atoms?

Thanks in advance.

+4
source share
2 answers

Consider the use of semi-contextual notation to replace subsequences in DCG:

 eos([], []). replace(_, _) --> call(eos), !. replace(Find, Replace), Replace --> Find, !, replace(Find, Replace). replace(Find, Replace), [C] --> [C], replace(Find, Replace). substitute(Find, Replace, Request, Result):- phrase(replace(Find, Replace), Request, Result). 

Example:

 ?- substitute("a", "b", "atesta", R), atom_codes(A, R). R = [98, 116, 101, 115, 116, 98], A = btestb. 

Also underscores_are_much_more_readable than MixedCaseNamesAsYouSee.

+10
source

About the second question, that is, working with atoms, I wrote this utility by looking at atomic_list_concat

 %% replace_word(+Old, +New, +Orig, -Replaced) %% is det. % % string replacement % doesn't fail if not found % replace_word(Old, New, Orig, Replaced) :- atomic_list_concat(Split, Old, Orig), atomic_list_concat(Split, New, Replaced). 

Example:

 ?- replace_word(a, b, atesta, X). X = btestb. 
+2
source

All Articles