On Thursday, 19 April 2012 at 16:19:05 UTC, Brad Anderson wrote:
On Thu, Apr 19, 2012 at 7:25 AM, Christophe
<[email protected]>wrote:
"Brad Anderson" , dans le message (digitalmars.D.learn:34902),
a écrit :
> Perhaps I'm just misunderstanding something about closures
> but
> the following code seems to behave oddly:
>
> import std.stdio, std.range, std.algorithm, std.string;
>
> void main()
> {
> auto lst = ["a", "b"];
> auto rng = range_gen(lst);
> writeln(rng.take(5));
> }
> auto range_gen(string[] lst)
> {
> auto a = sequence!"n+1"().map!(a=>format("%s%d",
> lst[0],
> a))();
> return chain(lst, a); // access violation
> //return a; // works
> }
My guess is that chain takes lst by reference, just like the
delegates
for map, wo both are working on the same slice instance. The
chain first
pops elements from lst, and then calls the mapped sequence. At
that
time, lst is empty.
You can just copy lst before you give it to chain (or to map's
delegate)
to solve this bug:
auto range_gen(string[] lst)
{
auto a = sequence!"n+1"().map!(a=>format("%s%d", lst[0],
a))();
string[] lst2 = lst;
return chain(lst2, a); // access violation
}
Ah, that would make sense. I'll test and make sure when I get
home. Range
consumption tricks me more often than I wish. I'll eventually
learn to
look out for it more actively.
Regards,
Brad Anderson
Ok, so this wasn't the problem. I have no idea what the problem
is. Using string[] lst = list; doesn't help nor does lst.save.
I can get some really weird behavior messing around with this.
Access violations that appear or disappear when symbolic debug
info is enabled. Here's an example of a weird one:
import std.stdio, std.range, std.algorithm, std.string;
void main()
{
writeln(gen(["a", "b"]).take(5));
}
auto gen(string[] lst)
{
auto prefix = lst[0];
auto a = iota(10).map!(a=>format("%s%d", prefix, a))();
//auto a = sequence!"n+1"().map!(a=>format("%s%d",
prefix, a))();
return chain(lst.save, a);
}
Compiling that using DMD 2.059 without -g results in a UTF
exception (memory corruption?) after outputting ["a", "b",.
Compiling with -g produces no exception but the output is
incorrect (["a", "b", "0", "1", "2"] should be ["a", "b", "a0",
"a1", "a2"]). Now, if you replace the iota line with with the
commented out sequence line it works the other way. Without -g
gives no exception (but correct output this time), with -g
results in a UTF exception. It's a bit unsettling that adding
debug info can change the behavior of the program.
I suppose this makes this a bug but I'm not sure what I'd call
it. Is it a bug with chain() or with closures? Is the symbolic
debug information differences a different bug?
Regards,
Brad Anderson