Re: Strange closure behaviour
On 15.06.19 18:29, Rémy Mouëza wrote: On Saturday, 15 June 2019 at 01:21:46 UTC, Emmanuelle wrote: On Saturday, 15 June 2019 at 00:30:43 UTC, Adam D. Ruppe wrote: On Saturday, 15 June 2019 at 00:24:52 UTC, Emmanuelle wrote: Is it a compiler bug? Yup, a very longstanding bug. You can work around it by wrapping it all in another layer of function which you immediately call (which is fairly common in javascript): funcs ~= ((x) => (int i) { nums[x] ~= i; })(x); Or maybe less confusingly written long form: funcs ~= (delegate(x) { return (int i) { nums[x] ~= i; }; })(x); You write a function that returns your actual function, and immediately calls it with the loop variable, which will explicitly make a copy of it. Oh, I see. Unfortunate that it's a longstanding compiler bug, but at least the rather awkward workaround will do. Thank you! I don't know if we can tell this is a compiler bug. It's a bug. It's memory corruption. Different objects with overlapping lifetimes use the same memory location. The same behavior happens in Python. No, it's not the same. Python has no sensible notion of variable scope. >>> for i in range(3): pass ... >>> print(i) 2 Yuck. The logic being variable `x` is captured by the closure. That closure's context will contain a pointer/reference to x. Whenever x is updated outside of the closure, the context still points to the modified x. Hence the seemingly strange behavior. ... It's not the same instance of the variable. Foreach loop variables are local to the loop body. They may both be called `x`, but they are not the same. It's most obvious with `immutable` variables. Adam's workaround ensures that the closure captures a temporary `x` variable on the stack: a copy will be made instead of taking a reference, since a pointer to `x` would be dangling once the `delegate(x){...}` returns. Most of the time, we want a pointer/reference to the enclosed variables in our closures. Note that C++ 17 allows one to select the capture mode: the following link lists 8 of them: https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture. ... No, this is not an issue of by value vs by reference. All captures in D are by reference, yet the behavior is wrong. D offers a convenient default that works most of the time. The trade-off is having to deal with the creation of several closures referencing a variable being modified in a single scope, like the incremented `x` of the for loop. ... By reference capturing may be a convenient default, but even capturing by reference the behavior is wrong.
Re: Using scanw Ncurses in D lang
On 15.06.19 23:20, Gabol wrote: example: scanw("% i", & number); // The compiler accuses error. Error: function deimos.ncurses.curses.scanw(char* fmt, ...) is not callable using argument types (string, int*) source/app.d(8,14): cannot pass argument "0" of type string to parameter char* fmt /usr/bin/dmd failed with exit code 1. Off topic: The string literal in the error message is wrong. It's "0" when it should be "% i". I've made a PR to fix it: https://github.com/dlang/dmd/pull/10040
Using scanw Ncurses in D lang
how can I use the scanw() function; of the ncurses of the deimos.ncurses project since the conventional mode does not work example: scanw("% i", & number); // The compiler accuses error. Error: function deimos.ncurses.curses.scanw(char* fmt, ...) is not callable using argument types (string, int*) source/app.d(8,14):cannot pass argument "0" of type string to parameter char* fmt /usr/bin/dmd failed with exit code 1.
Re: Delegate / Error: cannot implicitly convert expression...
On Saturday, 15 June 2019 at 17:42:04 UTC, ag0aep6g wrote: On Saturday, 15 June 2019 at 17:24:45 UTC, user1234 wrote: --- void foo(){writeln(__PRETTY_FUNCTION__);} void main(string[] args) { void delegate() dg; dg.funcptr = dg.ptr = null; // usually a "this" or a frame address dg(); } --- because dg.ptr would be used to retrieve the offset of the locals variable used in the parent stack or the address of a class instance (the this). But this is not required at all here. The opposite way would lead to various access violation. That only works because foo doesn't have any parameters. When you add even just one, things will go wrong. True if was forgetting that the context is a hidden parameter... Maybe it depends on the calling convention too ?
Re: Strange closure behaviour
On Saturday, 15 June 2019 at 16:29:29 UTC, Rémy Mouëza wrote: I don't know if we can tell this is a compiler bug. The same behavior happens in Python. The logic being variable `x` is captured by the closure. That closure's context will contain a pointer/reference to x. Whenever x is updated outside of the closure, the context still points to the modified x. Hence the seemingly strange behavior. I come from Ruby, where it works as I expected, so I assumed all languages would work like that; but then, D surprised me, and now, Python too, and apparently a whole bunch of other languages (which is honestly kinda disheartening since I like throwing lambdas everywhere.)
Re: Delegate / Error: cannot implicitly convert expression...
On Saturday, 15 June 2019 at 17:24:45 UTC, user1234 wrote: --- void foo(){writeln(__PRETTY_FUNCTION__);} void main(string[] args) { void delegate() dg; dg.funcptr = dg.ptr = null; // usually a "this" or a frame address dg(); } --- because dg.ptr would be used to retrieve the offset of the locals variable used in the parent stack or the address of a class instance (the this). But this is not required at all here. The opposite way would lead to various access violation. That only works because foo doesn't have any parameters. When you add even just one, things will go wrong.
Re: Delegate / Error: cannot implicitly convert expression...
On Saturday, 15 June 2019 at 16:34:22 UTC, Robert M. Münch wrote: On 2019-06-15 16:19:23 +, Anonymouse said: By design, I think: "delegate and function objects cannot be mixed. But the standard function std.functional.toDelegate converts a function to a delegate." Your example compiles if the assignment is changed to dg = toDelegate(); (given appropriate imports). https://tour.dlang.org/tour/en/basics/delegates https://dlang.org/phobos/std_functional.html#.toDelegate Hmm... but this here compiles: void main() { import std.stdio: write, writeln, writef, writefln; void foo(int a) {return; } void test() { void delegate(int) dg; dg = } } See: https://run.dlang.io/is/U7uhAX Is it because inside main() there is a stack frame? And with a global function there is none? I'm a bit confused... yes. delegate is a function pointer + its context. At the global scope there's no context. Actually the following works fine: --- void foo(){writeln(__PRETTY_FUNCTION__);} void main(string[] args) { void delegate() dg; dg.funcptr = dg.ptr = null; // usually a "this" or a frame address dg(); } --- because dg.ptr would be used to retrieve the offset of the locals variable used in the parent stack or the address of a class instance (the this). But this is not required at all here. The opposite way would lead to various access violation.
Re: Strange closure behaviour
On Saturday, 15 June 2019 at 16:29:29 UTC, Rémy Mouëza wrote: I don't know if we can tell this is a compiler bug. I can't remember where the key fact was, but I used to agree with you (several languages work this same way, and it makes a lot of sense for ease of the implementation), but someone convinced me otherwise by pointing to the language of the D spec. I just can't find that reference right now... It is worth noting too that the current behavior also opens up a whole in the immutable promises; the loop variable can be passed as immutable to the outside via a delegate, but then modified afterward, which is unambiguously a bug. Regardless of bug vs spec, it isn't implemented and I wouldn't expect that to change any time soon, so it is good to just learn the wrapper function technique :) (and it is useful in those other languages too)
Re: Delegate / Error: cannot implicitly convert expression...
On Saturday, 15 June 2019 at 16:34:22 UTC, Robert M. Münch wrote: On 2019-06-15 16:19:23 +, Anonymouse said: By design, I think: "delegate and function objects cannot be mixed. But the standard function std.functional.toDelegate converts a function to a delegate." Your example compiles if the assignment is changed to dg = toDelegate(); (given appropriate imports). https://tour.dlang.org/tour/en/basics/delegates https://dlang.org/phobos/std_functional.html#.toDelegate Hmm... but this here compiles: void main() { import std.stdio: write, writeln, writef, writefln; void foo(int a) {return; } void test() { void delegate(int) dg; dg = } } See: https://run.dlang.io/is/U7uhAX Is it because inside main() there is a stack frame? And with a global function there is none? I'm a bit confused... Correct. Inside main, foo is a delegate. https://dlang.org/spec/function.html#nested
Re: Delegate / Error: cannot implicitly convert expression...
On 2019-06-15 16:19:23 +, Anonymouse said: By design, I think: "delegate and function objects cannot be mixed. But the standard function std.functional.toDelegate converts a function to a delegate." Your example compiles if the assignment is changed to dg = toDelegate(); (given appropriate imports). https://tour.dlang.org/tour/en/basics/delegates https://dlang.org/phobos/std_functional.html#.toDelegate Hmm... but this here compiles: void main() { import std.stdio: write, writeln, writef, writefln; void foo(int a) {return; } void test() { void delegate(int) dg; dg = } } See: https://run.dlang.io/is/U7uhAX Is it because inside main() there is a stack frame? And with a global function there is none? I'm a bit confused... -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: Strange closure behaviour
On Saturday, 15 June 2019 at 01:21:46 UTC, Emmanuelle wrote: On Saturday, 15 June 2019 at 00:30:43 UTC, Adam D. Ruppe wrote: On Saturday, 15 June 2019 at 00:24:52 UTC, Emmanuelle wrote: Is it a compiler bug? Yup, a very longstanding bug. You can work around it by wrapping it all in another layer of function which you immediately call (which is fairly common in javascript): funcs ~= ((x) => (int i) { nums[x] ~= i; })(x); Or maybe less confusingly written long form: funcs ~= (delegate(x) { return (int i) { nums[x] ~= i; }; })(x); You write a function that returns your actual function, and immediately calls it with the loop variable, which will explicitly make a copy of it. Oh, I see. Unfortunate that it's a longstanding compiler bug, but at least the rather awkward workaround will do. Thank you! I don't know if we can tell this is a compiler bug. The same behavior happens in Python. The logic being variable `x` is captured by the closure. That closure's context will contain a pointer/reference to x. Whenever x is updated outside of the closure, the context still points to the modified x. Hence the seemingly strange behavior. Adam's workaround ensures that the closure captures a temporary `x` variable on the stack: a copy will be made instead of taking a reference, since a pointer to `x` would be dangling once the `delegate(x){...}` returns. Most of the time, we want a pointer/reference to the enclosed variables in our closures. Note that C++ 17 allows one to select the capture mode: the following link lists 8 of them: https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture. D offers a convenient default that works most of the time. The trade-off is having to deal with the creation of several closures referencing a variable being modified in a single scope, like the incremented `x` of the for loop. That said, I wouldn't mind having the compiler dealing with that case: detecting that `x` is within a for loop and making copies of it in the closures contexts.
Re: Delegate / Error: cannot implicitly convert expression...
On Saturday, 15 June 2019 at 15:54:00 UTC, Robert M. Münch wrote: Why does the follwing code give: Error: cannot implicitly convert expression & myFunc of type void function(int a) to void delegate(int) void myFunc(int a){return;} void main() { void delegate(int) dg; dg = } See: https://run.dlang.io/is/iTYo2L By design, I think. "delegate and function objects cannot be mixed. But the standard function std.functional.toDelegate converts a function to a delegate." Your example compiles if the assignment is changed to dg = toDelegate(); (given appropriate imports). https://tour.dlang.org/tour/en/basics/delegates https://dlang.org/phobos/std_functional.html#.toDelegate
Delegate / Error: cannot implicitly convert expression...
Why does the follwing code give: Error: cannot implicitly convert expression & myFunc of type void function(int a) to void delegate(int) void myFunc(int a){return;} void main() { void delegate(int) dg; dg = } See: https://run.dlang.io/is/iTYo2L -- Robert M. Münch http://www.saphirion.com smarter | better | faster