Re: Trying to alias this a grapheme range + making it a forward range
On 08.07.19 23:55, aliak wrote: struct ustring { string data; this(string data) { this.data = data; } auto get() { static struct Range { typeof(string.init.byGrapheme) source; bool empty() { return source.empty; } void popFront() { source.popFront; } auto front() { return source.front[]; } auto save() { return this; }; } return Range(this.data.byGrapheme); } alias get this; } But I keep on ending up with a UTFException: "Encoding an invalid code point in UTF-8" with code like: writeln("hello".ustring); `source.front` is a temporary `Grapheme` and you're calling `opSlice` on it. The documentation for `Grapheme.opSlice` warns: "Invalidates when this Grapheme leaves the scope, attempts to use it then would lead to memory corruption." [1] So you can't return `source.front[]` from your `front`. You'll have to store the current `front` in your struct, I guess. Also, returning a fresh range on every `alias this` call is asking for trouble. This is an infinite loop: auto u = "hello".ustring; while (!u.empty) u.popFront(); because `u.empty` and `u.popFront` are called on fresh, non-empty, independent ranges. Problem 2: How can I get the aliased ustring type to behave as a ForwardRange? If I add the save method to the voldermort range type, the isForwardRange!ustring fails because the requirement on isForwardRange checks to see if save returns the same type it's called on. Which is not the case here since typeof(ustring.save) == ustring.get.Range). But nontheless does have a save method. You must provide a `save` that returns a `ustring`. There's no way around it. Maybe make `ustring` itself the range. In the code you've shown, the `alias this` only seems to make everything more complicated. But you might have good reasons for it, of course. By the way, your're not calling `source.save` in `Range.save`. You're just copying `source`. I don't know if that's effectively the same, and even if it is, I'd advise to call `.save` explicitly. Better safe than sorry. [1] https://dlang.org/phobos/std_uni.html#.Grapheme.opSlice
Trying to alias this a grapheme range + making it a forward range
Problem 1: I'm trying to get a string to behave as a .byGrapheme range by default, but I can't figure out Grapheme. I'm trying to replicate this behavior: foreach (g; "hello".byGrapheme) { write(g[]); } In a custom type: struct ustring { string data; this(string data) { this.data = data; } auto get() { static struct Range { typeof(string.init.byGrapheme) source; bool empty() { return source.empty; } void popFront() { source.popFront; } auto front() { return source.front[]; } auto save() { return this; }; } return Range(this.data.byGrapheme); } alias get this; } But I keep on ending up with a UTFException: "Encoding an invalid code point in UTF-8" with code like: writeln("hello".ustring); Problem 2: How can I get the aliased ustring type to behave as a ForwardRange? If I add the save method to the voldermort range type, the isForwardRange!ustring fails because the requirement on isForwardRange checks to see if save returns the same type it's called on. Which is not the case here since typeof(ustring.save) == ustring.get.Range). But nontheless does have a save method. Cheers, - Ali
Re: Using output-range overloads of SysTime.toISO{Ext}String with formatting code
08.07.2019 13:38, Joseph Rushton Wakeling пишет: Thanks for taking the time to answer, but I don't think this really addresses my question. Your example shows a struct with `toString` overloads. However, SysTime.toISOExtString does not work like this: it is a method with two explicit overloads, one of which just returns a newly allocated `string`, the other of which returns nothing but accepts an output range as input: https://dlang.org/phobos/std_datetime_systime.html#.SysTime.toISOExtString I want to know if there's an easy way to work with that in `format` and `writefln` statements. Note that while SysTime does also have `toString` methods, these give no control over the kind of datetime string that results: https://dlang.org/phobos/std_datetime_systime.html#.SysTime.toString Since I explicitly need the extended ISO format, I need to use `toISOExtString` directly. Sorry that my answer wasn't thoughtful. I guess that there is no way to have `writeln` automatically use the output range overload instead of allocating one. You need somehow to provide the output range to `toISOExtString` explicitly because `writeln` outputs the return of `toISOExtString` and have no ability to use specific overload. That is compiler calls `toISOExtString` and then passes its return to `writeln`. Probably library solution isn't possible in this case. Workaround is using own wrapper to provide output range to `toISOExtString`.
Re: Using output-range overloads of SysTime.toISO{Ext}String with formatting code
On Sunday, 7 July 2019 at 20:12:30 UTC, drug wrote: 07.07.2019 17:49, Joseph Rushton Wakeling пишет: it's possible to do something like `writefln!"%s"(now.toISOExtString)` and have it automatically use the output range overload rather than allocating a new string instance. This is exactly how it is intended to work: https://run.dlang.io/is/ATjAkx Thanks for taking the time to answer, but I don't think this really addresses my question. Your example shows a struct with `toString` overloads. However, SysTime.toISOExtString does not work like this: it is a method with two explicit overloads, one of which just returns a newly allocated `string`, the other of which returns nothing but accepts an output range as input: https://dlang.org/phobos/std_datetime_systime.html#.SysTime.toISOExtString I want to know if there's an easy way to work with that in `format` and `writefln` statements. Note that while SysTime does also have `toString` methods, these give no control over the kind of datetime string that results: https://dlang.org/phobos/std_datetime_systime.html#.SysTime.toString Since I explicitly need the extended ISO format, I need to use `toISOExtString` directly.