Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
December 13, 2012 bringToFront() and arrays of char | ||||
---|---|---|---|---|
| ||||
Why doesn't the below code compile? How to rewrite it so that it does? Using: DMD64 D Compiler v2.060. Thank you. Code: ---------------- import std.algorithm, std.ascii, std.stdio; void main() { char[] rot13 = lowercase.dup; bringToFront(rot13[0 .. 13], rot13[13 .. $]); writeln(rot13); } ---------------- Errors: /usr/include/dmd/phobos/std/algorithm.d(1762): Error: front(r1) is not an lvalue /usr/include/dmd/phobos/std/algorithm.d(1763): Error: r2.front is not an lvalue /usr/include/dmd/phobos/std/algorithm.d(5944): Error: template instance std.algorithm.swapFront!(char[],char[]) error instantiating rot13_test.d(7): instantiated from here: bringToFront!(char[],char[]) /usr/include/dmd/phobos/std/algorithm.d(1762): Error: not a property r1.front /usr/include/dmd/phobos/std/algorithm.d(1763): Error: r2.front is not an lvalue /usr/include/dmd/phobos/std/algorithm.d(5944): Error: template instance std.algorithm.swapFront!(Take!(char[]),char[]) error instantiating /usr/include/dmd/phobos/std/algorithm.d(5973): instantiated from here: bringToFront!(Take!(char[]),char[]) rot13_test.d(7): instantiated from here: bringToFront!(char[],char[]) /usr/include/dmd/phobos/std/algorithm.d(5973): Error: template instance std.algorithm.bringToFront!(Take!(char[]),char[]) error instantiating rot13_test.d(7): instantiated from here: bringToFront!(char[],char[]) rot13_test.d(7): Error: template instance std.algorithm.bringToFront!(char[],char[]) error instantiating |
December 13, 2012 Re: bringToFront() and arrays of char | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mu | On 12/12/2012 05:18 PM, Mu wrote: > Why doesn't the below code compile? > How to rewrite it so that it does? > Using: DMD64 D Compiler v2.060. > Thank you. > > Code: > ---------------- > > import std.algorithm, std.ascii, std.stdio; > > void main() > { > char[] rot13 = lowercase.dup; > > bringToFront(rot13[0 .. 13], rot13[13 .. $]); > writeln(rot13); > } > > ---------------- > > Errors: > > /usr/include/dmd/phobos/std/algorithm.d(1762): Error: front(r1) > is not an lvalue This is a common pitfall of using char[] with range functions. Range functions like bringToFront() use the .front property. .front unintuitively returns dchar for a char[] range. That dchar is decoded from the UTF-8 code units of the char[]. You can use std.conv.to: import std.algorithm, std.ascii, std.stdio; import std.conv; void main() { dchar[] rot13 = lowercase.to!(dchar[]); bringToFront(rot13[0 .. 13], rot13[13 .. $]); writeln(rot13); } By dtext: dchar[] rot13 = lowercase.dtext.dup; If you are dealing with ASCII, you may want to use ubyte instead. The following is one way of achieving that: import std.array; // ... ubyte[] rot13 = lowercase.map!(a => cast(ubyte)a).array; (There must be an easier way of doing that. :)) Ali |
December 13, 2012 Re: bringToFront() and arrays of char | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, December 12, 2012 17:34:53 Ali Çehreli wrote:
> (There must be an easier way of doing that. :))
If you have a string that's really ASCII and you're _sure_ that it's only ASCII, then I'd suggest simply casting it to immutable(ubyte)[] and operating on that with all range based functions. That way, no decoding occurs, and you don't have to dup the string. If you want, you could also easily create a funtion called something like assumeASCII that did that cast in order to make it more idiomatic (similar to std.exception.assumeUnique).
- Jonathan M Davis
|
December 13, 2012 Re: bringToFront() and arrays of char | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 12/12/2012 07:22 PM, Jonathan M Davis wrote: > On Wednesday, December 12, 2012 17:34:53 Ali Çehreli wrote: >> (There must be an easier way of doing that. :)) > > If you have a string that's really ASCII and you're _sure_ that it's only > ASCII, then I'd suggest simply casting it to immutable(ubyte)[] and operating > on that with all range based functions. That way, no decoding occurs, and you > don't have to dup the string. If you want, you could also easily create a > funtion called something like assumeASCII that did that cast in order to make > it more idiomatic (similar to std.exception.assumeUnique). > > - Jonathan M Davis I like that. :) Potentially, the function can check in debug compilation that a random selection of characters are really ASCII. Similar to what the constructor of std.range.SortedRange (used as assumeSorted) does: https://github.com/D-Programming-Language/phobos/blob/master/std/range.d#L7015 struct SortedRange(Range, alias pred = "a < b") if (isRandomAccessRange!Range) { // ... // Undocummented because a clearer way to invoke is by calling // assumeSorted. this(Range input) { this._input = input; if(!__ctfe) debug { import std.random; // Check the sortedness of the input if (this._input.length < 2) return; immutable size_t msb = bsr(this._input.length) + 1; assert(msb > 0 && msb <= this._input.length); immutable step = this._input.length / msb; static MinstdRand gen; immutable start = uniform(0, step, gen); auto st = stride(this._input, step); assert(isSorted!pred(st), text(st)); } } // ... } Ali |
December 13, 2012 Re: bringToFront() and arrays of char | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 12/13/2012 7:22 AM, Jonathan M Davis пишет: > On Wednesday, December 12, 2012 17:34:53 Ali Çehreli wrote: >> (There must be an easier way of doing that. :)) > > If you have a string that's really ASCII and you're _sure_ that it's only > ASCII, then I'd suggest simply casting it to immutable(ubyte)[] and operating > on that with all range based functions. That way, no decoding occurs, and you > don't have to dup the string. If you want, you could also easily create a > funtion called something like assumeASCII that did that cast in order to make > it more idiomatic (similar to std.exception.assumeUnique). > Yup. Plus there is a not commonly known 'representation' function that does just that for (w|d|)string: auto repro = lowercase.representation; //typeof(repro) should be immutable(ubyte)[] -- Dmitry Olshansky |
December 13, 2012 Re: bringToFront() and arrays of char | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | On Friday, December 14, 2012 00:27:39 Dmitry Olshansky wrote:
> 12/13/2012 7:22 AM, Jonathan M Davis пишет:
> > On Wednesday, December 12, 2012 17:34:53 Ali Çehreli wrote:
> >> (There must be an easier way of doing that. :))
> >
> > If you have a string that's really ASCII and you're _sure_ that it's only ASCII, then I'd suggest simply casting it to immutable(ubyte)[] and operating on that with all range based functions. That way, no decoding occurs, and you don't have to dup the string. If you want, you could also easily create a funtion called something like assumeASCII that did that cast in order to make it more idiomatic (similar to std.exception.assumeUnique).
>
> Yup. Plus there is a not commonly known 'representation' function that does just that for (w|d|)string:
>
> auto repro = lowercase.representation;
> //typeof(repro) should be immutable(ubyte)[]
Wow. Good to know about that one. I feel kind of stupid for not realizing that it was there given how much I've worked in std.string. And here I was doing that cast manually in some of my code recently and having to put comments to indicate why I was doing it. std.string.representation is much better.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation