tags:

views:

100

answers:

4

I'd like to do something equivalent to Python's repr:

>>> x = "a\nb\nc"

>>> print x
a
b
c
>>> repr(x)
"'a\\nb\\nc'"

>>> print repr(x)
'a\nb\nc'

How can I do that in D? Is there a format directive similar to Python's %r?

EDIT: I want to be able to print strings in their escaped form for debugging purposes (I've just started to learn D and I am writing silly text processing functions).

+2  A: 

In D strings are not objects and when you use escape characters you are actually storing the character and not the escape itself (which I would expect Python was doing too). So if you want to convert a string into its escaped form you would need to modify the output yourself (I don't know of any library function for this).

Otherwise Objects can override the toString() function which should produce a string representation of the object.

Update: Here is an example of repr in D. But note, since the original text is not stored anywhere in the executable it will convert literal representations too. There shouldn't be an issue with Unicode as the normal integrity of string is intact.

import std.stdio;
import std.exception;

void main() {
    writeln(repr("This\nis\n\t*My\v Test"));
}

string repr(string s) {
    char[] p;
    for (size_t i; i < s.length; i++)
    {
        switch(s[i]) {
            case '\'':
            case '\"':
            case '\?':
            case '\\':
                p ~= "\\";
                p ~= s[i];
                break;
            case '\a':
                p ~= "\\a";
                break;
            case '\b':
                p ~= "\\b";
                break;
            case '\f':
                p ~= "\\f";
                break;
            case '\n':
                p ~= "\\n";
                break;
            case '\r':
                p ~= "\\r";
                break;
            case '\t':
                p ~= "\\t";
                break;
            case '\v':
                p ~= "\\v";
                break;
            default:
                p ~= s[i];
                break;
        }
    }

    return assumeUnique(p);
}
he_the_great
A: 

D has two ways to declare WYSIWYG strings:

r"thestring"
`thestring`

So, the following program

import std.stdio;

void main()
{
    auto a = r"hello\nworld";
    auto b = `hello\nworld`;

    writeln(a);
    writeln(b);
}

prints

hello\nworld
hello\nworld

However, if you have an arbitrary string rather than a string literal, and you want to be able to print it with the newlines and whatnot being printed as their escape sequences, you're going to have to do some string processing - likely using std.string.replace() to replace each character with its escape sequence with the extra backslashes. For instance, to escape the newlines, you'd do this:

str.replace("\n", "\\n");

But you'd have to do that individually for '\t', '\r', '\', etc. I'm not aware of any way to do it automatically. The WYSIWYG strings just let you avoid having to using all of the extra backslashes when constructing the string.

Jonathan M Davis
A: 

Strings are processed and escape senquences are replaced at compile time. At runtime the information is lost and you would need to undo the escaping yourself (maybe there is already some standard escaping function) but it's not built in.

If you control the source you can use raw strings. Just put an r in front of your string.

"a\tb" => "a    b"
r"a\tb" => "a\tb"
Mafi
+1  A: 

The D's standard library doesn't contain such a function, but it should be trivial to write one. Just go through the string and replace every occurrence of "\n" with "\\n" and so on.

Peter Alexander