Re: Trying to alias this a grapheme range + making it a forward range

2019-07-08 Thread ag0aep6g via Digitalmars-d-learn

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

2019-07-08 Thread aliak via Digitalmars-d-learn

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

2019-07-08 Thread Digital Mars via Digitalmars-d-learn

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

2019-07-08 Thread Joseph Rushton Wakeling via Digitalmars-d-learn

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.