www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Reversing a string

reply AndreasDavour <andreas.davour protonmail.ch> writes:
Hi.

I've just started to learn some D, so maybe this question is 
extremely stupid, but please bear with me.

I have been trying to reverse a string, and through some googling 
found the std.algorithm.mutation.reverse method. But, when I try 
to use it I get some very verbose errors that just makes my eyes 
glaze over. What on earth do they mean? How do I reverse a 
string, really?

This is my code:
----------------------------
import std.stdio;
import std.algorithm;

void main() {
   auto test = "This is my text";
   string next_test = reverse(test);

   writeln(test);
   writeln(next_test);
}
----------------------------

This is my error:
----------------------------
[ante tiny ~/src/D/tutorial]$ rdmd string4.d
/usr/home/ante/src/dmd2/freebsd/bin64/../../src/phobos/std/algorit
m/mutation.d(2513): Error: template `std.algorithm.mutation.reverse` cannot
deduce function from argument types `!()(immutable(ubyte)[])`, candidates are:
/usr/home/ante/src/dmd2/freebsd/bin64/../../src/phobos/std/algorit
m/mutation.d(2485):        `std.algorithm.mutation.reverse(Range)(Range r) if
(isBidirectionalRange!Range && (hasSwappableElements!Range ||
hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range ||
isNarrowString!Range && isAssignable!(ElementType!Range)))`
/usr/home/ante/src/dmd2/freebsd/bin64/../../src/phobos/std/algorit
m/mutation.d(2521): Error: template `std.algorithm.mutation.reverse` cannot
deduce function from argument types `!()(immutable(ubyte)[])`, candidates are:
/usr/home/ante/src/dmd2/freebsd/bin64/../../src/phobos/std/algorit
m/mutation.d(2485):        `std.algorithm.mutation.reverse(Range)(Range r) if
(isBidirectionalRange!Range && (hasSwappableElements!Range ||
hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range ||
isNarrowString!Range && isAssignable!(ElementType!Range)))`
string4.d(6): Error: template instance 
`std.algorithm.mutation.reverse!string` error instantiating
Failed: ["/usr/home/ante/src/dmd2/freebsd/bin64/dmd", "-v", 
"-o-", "string4.d", "-I."]
------------------------------

Can some unpack that for me, please?

I might add that the most intuitive way to reverse a string, I 
think, would be to consider it a range and just do "newstring = 
oldstring[$ .. 0]" but that gives an error about being out of 
bounds, so I guess the compiler expect values to increase from 
left to right, and does not want to increment beyond $. Makes 
sense, but that syntax would be very neat.
Jan 11
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
So strings in D are Unicode. This is both a great thing and a horrible 
thing.
To reverse a Unicode string correctly you need to take into account BiDi 
and graphemes, in other words it gets rather complex. However I suspect 
that this isn't what you want.

Now a (w/d)string is defined as:

alias string  = immutable(char)[];
alias wstring = immutable(wchar)[];
alias dstring = immutable(dchar)[];

Note the immutable, it means you cannot modify individual values. Which 
is a problem for reverse because it modifies in place.

Which means:

writeln("Hello D".reverse);

Won't work, but:

writeln("Hello D".dup.reverse);

Will. A simple duplication (char[]) makes it work.

Finally, arrays in D are absolutely brilliant. They are what we call 
slices. A slice is a pointer + a length. That is it. Hence they cannot 
be reversed in place. Of course this is great for interacting with e.g. 
C, since its just a matter of slicing any data back to get your bounds 
checking ext.
Jan 11
parent reply JN <666total wp.pl> writes:
On Friday, 11 January 2019 at 08:15:01 UTC, rikki cattermole 
wrote:
 Note the immutable, it means you cannot modify individual 
 values. Which is a problem for reverse because it modifies in 
 place.
The error message is kind of unfortunate. This is a simple usecase and the error message is undecipherable already. It'd be cool if the compiler could try to strip immutability, and if the type matches then, throw an error something like "Cannot pass immutable char[] to reverse, did you mean char[]?".
Jan 11
parent AndreasDavour <andreas.davour protonmail.ch> writes:
On Friday, 11 January 2019 at 08:45:12 UTC, JN wrote:
 On Friday, 11 January 2019 at 08:15:01 UTC, rikki cattermole 
 wrote:
 Note the immutable, it means you cannot modify individual 
 values. Which is a problem for reverse because it modifies in 
 place.
The error message is kind of unfortunate. This is a simple usecase and the error message is undecipherable already. It'd be cool if the compiler could try to strip immutability, and if the type matches then, throw an error something like "Cannot pass immutable char[] to reverse, did you mean char[]?".
That would help a lot, as I got "rikki cattermole"'s answer at once, when my eyes were brought to the "immutable" part. I come from the lisp world, so I'm kind of familiar with the idea of copying and/or modifying in place to limit consing. I guess I should I have realised this would be a perfect example of that kind of situation.
Jan 11
prev sibling parent reply Seb <seb wilzba.ch> writes:
On Friday, 11 January 2019 at 08:05:39 UTC, AndreasDavour wrote:
 Hi.

 I've just started to learn some D, so maybe this question is 
 extremely stupid, but please bear with me.

 [...]
Use .retro - it is also lazy and won't allocate: https://run.dlang.io/is/A6bjrC
Jan 11
parent reply bauss <jj_1337 live.dk> writes:
On Friday, 11 January 2019 at 08:25:41 UTC, Seb wrote:
 On Friday, 11 January 2019 at 08:05:39 UTC, AndreasDavour wrote:
 Hi.

 I've just started to learn some D, so maybe this question is 
 extremely stupid, but please bear with me.

 [...]
Use .retro - it is also lazy and won't allocate: https://run.dlang.io/is/A6bjrC
What a terrible name.
Jan 11
next sibling parent AndreasDavour <andreas.davour protonmail.ch> writes:
On Friday, 11 January 2019 at 09:41:30 UTC, bauss wrote:
 On Friday, 11 January 2019 at 08:25:41 UTC, Seb wrote:
 On Friday, 11 January 2019 at 08:05:39 UTC, AndreasDavour 
 wrote:
 Hi.

 I've just started to learn some D, so maybe this question is 
 extremely stupid, but please bear with me.

 [...]
Use .retro - it is also lazy and won't allocate: https://run.dlang.io/is/A6bjrC
What a terrible name.
Well, it was not the first one I would have searched for, no. Good to know it exists as well, though. Thanks!
Jan 11
prev sibling parent reply Mike James <foo bar.com> writes:
On Friday, 11 January 2019 at 09:41:30 UTC, bauss wrote:
 On Friday, 11 January 2019 at 08:25:41 UTC, Seb wrote:
 On Friday, 11 January 2019 at 08:05:39 UTC, AndreasDavour 
 wrote:
 Hi.

 I've just started to learn some D, so maybe this question is 
 extremely stupid, but please bear with me.

 [...]
Use .retro - it is also lazy and won't allocate: https://run.dlang.io/is/A6bjrC
What a terrible name.
Check out the origin :-) https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1 -=mike=-
Jan 11
next sibling parent bauss <jj_1337 live.dk> writes:
On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 On Friday, 11 January 2019 at 09:41:30 UTC, bauss wrote:
 On Friday, 11 January 2019 at 08:25:41 UTC, Seb wrote:
 On Friday, 11 January 2019 at 08:05:39 UTC, AndreasDavour 
 wrote:
 Hi.

 I've just started to learn some D, so maybe this question is 
 extremely stupid, but please bear with me.

 [...]
Use .retro - it is also lazy and won't allocate: https://run.dlang.io/is/A6bjrC
What a terrible name.
Check out the origin :-) https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1 -=mike=-
I wish I could live my life peacefully, but apparently not.
Jan 11
prev sibling next sibling parent AndreasDavour <andreas.davour protonmail.ch> writes:
On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 On Friday, 11 January 2019 at 09:41:30 UTC, bauss wrote:
 On Friday, 11 January 2019 at 08:25:41 UTC, Seb wrote:
 On Friday, 11 January 2019 at 08:05:39 UTC, AndreasDavour 
 wrote:
 Hi.

 I've just started to learn some D, so maybe this question is 
 extremely stupid, but please bear with me.

 [...]
Use .retro - it is also lazy and won't allocate: https://run.dlang.io/is/A6bjrC
What a terrible name.
Check out the origin :-) https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1 -=mike=-
Look at that. Incidentally, I kind of like "foreach(i; 99 .. 0 : -1)".
Jan 11
prev sibling next sibling parent reply JN <666total wp.pl> writes:
On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 Check out the origin :-)

 https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1
I guess something like iterReverse, reverseIter, backIterator would be too simple...
Jan 11
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 11 January 2019 at 13:51:04 UTC, JN wrote:
 I guess something like iterReverse, reverseIter, backIterator 
 would be too simple...
or foreach_reverse, which never actually was removed! lol
Jan 11
prev sibling parent reply 0xEAB <desisma heidel.beer> writes:
On Friday, 11 January 2019 at 13:51:04 UTC, JN wrote:
 On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 Check out the origin :-)

 https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1
I guess something like iterReverse, reverseIter, backIterator would be too simple...
Of course. I would protrude from all other functions with their weird names then. Just kidding. Although... I have to admit it happened more than just once that I thought, "oh... another function that's named exactly different from what I'd have gone with."
Jan 11
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/11/19 1:25 PM, 0xEAB wrote:
 On Friday, 11 January 2019 at 13:51:04 UTC, JN wrote:
 On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 Check out the origin :-)

 https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1
I guess something like iterReverse, reverseIter, backIterator would be too simple...
Of course. I would protrude from all other functions with their weird names then. Just kidding. Although... I have to admit it happened more than just once that I thought, "oh... another function that's named exactly different from what I'd have gone with."
Part of the problem is that arr.reverse already was defined a long time ago. The thing about retro, is that even though it's not what I would think of for this operation, I have never forgotten the name since ;) -Steve
Jan 11
prev sibling parent reply AlCaponeJr <al gmail.com> writes:
On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 Check out the origin :-)

 https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1
Indeed a terrible name, please don't tell me this was chosen by vote. By the way currently is there any vote system for naming these things? Al.
Jan 11
parent Seb <seb wilzba.ch> writes:
On Friday, 11 January 2019 at 19:16:05 UTC, AlCaponeJr wrote:
 On Friday, 11 January 2019 at 11:15:05 UTC, Mike James wrote:
 Check out the origin :-)

 https://forum.dlang.org/thread/hl8345$2b1q$1 digitalmars.com?page=1
Indeed a terrible name, please don't tell me this was chosen by vote. By the way currently is there any vote system for naming these things? Al.
No. There are zero plans to break a ton of code by changing the name of a symbol in the standard library. It's more likely that someone comes along with a new general purpose library which hasn't seen much usage and thus can define slightly better names.
Jan 12