Discussions related to Visual Prolog
Peter Muraya
VIP Member
Posts: 147
Joined: 5 Dec 2012 7:29

string::concat vs string::write

Unread post by Peter Muraya »

Hi,
I often need to concatenate a number of strings, say, X,Y and Z. Which is the better practice than the other. And why?

Code: Select all

string::concat(X,Y,Z)
or

Code: Select all

string::write(X,Y,Z)  
Mutall Data Management Technical Support
User avatar
Ferenc Nagy
VIP Member
Posts: 215
Joined: 24 Apr 2007 12:26

Unread post by Ferenc Nagy »

Peter,
string::write(X,Y,Z) works even if one of X, Y or Z is not string but a number.
The limit of count of X,Y,Z parameters is smaller than the allowed count of parameters for string::concat.
string::concat(X,Y,Z) works only for strings.
The result will be the same strange "eksvaluewayvaluezedvalue".
I do not recommend you any of the above.
I prefer
1) string::concatwithdelimiter([X,Y,Z]," ") which gives
"eksvalue wayvalue zedvalue".
2) string::format("X=%, Y=%, Z=%.",X,Y,Z).
3) If you add field widths and define monospace font for your output window then you get nice columns:

Code: Select all

string::format("X=%-20.20s, Y=%-20.20s, Z=%-20.20s.",X,Y,Z).
TIA, Regards,
Frank Nagy
Peter Muraya
VIP Member
Posts: 147
Joined: 5 Dec 2012 7:29

Unread post by Peter Muraya »

Thank you Frank. You have added 2 other options that I also use occasionally. Is there any memory-use/execution-speed advantage of any one over the others? Or are all they based on a similar internal coding model?
Mutall Data Management Technical Support
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

There is no significant performance difference between the two approaches.

Both these methods can however give a quite significant overhead if used extensively. The problem is that both these approaches will copy all the strings into a new string.

This simple program:

Code: Select all

clauses     run() :-         N = 1000,         S = list1(N),         stdio::write(S).   class predicates     list1 : (unsigned N) -> string Tree. clauses     list1(0) = "0" :-         !.       list1(N) = T2 :-         T1 = list1(N-1),         T2 = string::format("%, %", T1, N).
It creates a string of the form "0, 1, 2, ..., 1000". But doing so it creates 1000 strings of increasing length each time copying to previous string into the new one. As result the algorithm is O(N^2).

The "right" way to do this is by using a stream instead of creating strings on the fly:

Code: Select all

class predicates     list2 : (unsigned N) -> string Tree. clauses     list2(N) = S:getString() :-         S = outputStream_string::new(),         list2b(S, N).   class predicates     list2b : (outputStream S, unsigned N). clauses     list2b(S, 0) :-         !,         S:write("0").       list2b(S, N) :-         list2b(S, N - 1),         S:writef(", %", N).
To see that this really matters I have run the following little test:

Code: Select all

clauses     run() :-         profileTime::init(),         foreach N in [100, 1000, 10000] do             C1 = convert(profileTime::costName, string::format("list1(%)", N)),             profileTime::start_pr(C1),             _S1 = list1(N),             profileTime::stop_pr(C1),             C2 = convert(profileTime::costName, string::format("list2(%)", N)),             profileTime::start_pr(C2),             _S2 = list2(N),             profileTime::stop_pr(C2)         end foreach,         profileTime::printAndReset().
Which gives results as shown in the image. I guess it is obvious that list1 have a problem compared to list2.
Attachments
profiling
profiling
listProfile.png (6.03 KiB) Viewed 10644 times
Regards Thomas Linder Puls
PDC
Peter Muraya
VIP Member
Posts: 147
Joined: 5 Dec 2012 7:29

Unread post by Peter Muraya »

Thomas,
Thanks. The message is that for intensive string work, of the following 5 string joining functions, the last one is better than all the others in terms of performance because it does not make and keep string copies. For less intensive work, the other alternatives may be much neater to use than the outputstream_str library. Is this a correct summary?

Code: Select all

string::concat string::write string::format sting::concatWithDelimeter outputstream_str::write, writef
Mutall Data Management Technical Support
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

Yes, that sounds fine.
Regards Thomas Linder Puls
PDC
Post Reply