5.2 The string type and its double quoted syntax
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • SWI-Prolog extensions
        • The string type and its double quoted syntax
          • Representing text: strings, atoms and code lists
          • Predicates that operate on strings
          • Why has the representation of double quoted text changed?
          • Adapting code for double quoted strings
          • Predicates to support adapting code for double quoted strings
    • Packages

5.2.4 Adapting code for double quoted strings

We observe that in many programs, most strings are only handled as a single unit during their lifetime. Examining real code tells us that double quoted strings typically appear in one of the following roles:

A DCG literal
Although represented as a list of codes is the correct representation for handling in DCGs, the DCG translator can recognise the literal and convert it to the proper representation. Such code need not be modified.
A format string
This is a typical example of text that is conceptually not a program identifier. Format is designed to deal with alternative representations of the format string. Such code need not be modified.
Getting a character code
The construct [X] = "a" is a commonly used template for getting the character code of the letter’a'. ISO Prolog defines the syntax 0'a for this purpose. Code using this must be modified. The modified code will run on any ISO compliant Prolog Processor.
As argument to list predicates to operate on strings
Here, we might see code similar to append("name:", Rest, Codes). Such code needs to be modified. In this particular example, the following is a good portable alternative: phrase("name:", Codes, Rest)
Checks for a character to be in a set
Such tests are often performed with code such as this: memberchk(C, "~!@#$"). This is a rather inefficient check in a traditional Prolog system because it pushes a list of character codes cell-by-cell onto the Prolog stack and then traverses this list cell-by-cell to see whether one of the cells unifies with C. If the test is successful, the string will eventually be subject to garbage collection. The best code for this is to write a predicate as below, which pushes nothing on the stack and performs an indexed lookup to see whether the character code is in‘my_class'.
my_class(0'~).
my_class(0'!).
...

An alternative to reach the same effect is to use term expansion to create the clauses:

term_expansion(my_class(_), Clauses) :-
        findall(my_class(C),
                string_code(_, "~!@#$", C),
                Clauses).

my_class(_).

Finally, the predicate string_code/3 can be exploited directly as a replacement for the memberchk/2 on a list of codes. Although the string is still pushed onto the stack, it is more compact and only a single entity.