Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 19:31:56 UTC, Jon Degenhardt wrote: On Friday, 5 October 2018 at 16:34:32 UTC, Paul Backus wrote: You can thread multiple arguments through to `each` using `std.range.zip`: tenRandomNumbers .zip(repeat(output)) .each!(unpack!((n, output) => output.appendln(n.to!string))); Full code: https://run.dlang.io/is/Qe7uHt Very interesting, thanks. It's a clever way to avoid the delegate capture issue. (Aside: A nested function that accesses 'output' from lexical context has the same issue as delegates wrt to capturing the variable.) Note that this solution may do a lot of output and hence running of the destructor. Use: `.zip(repeat())` to avoid that.
Re: DMD release build being faster than debug!
On Friday, 5 October 2018 at 16:57:03 UTC, Seb wrote: Yeah BUILD more or less only defines in which folder the binaries will be stored as the default BUILD was RELEASE historically and the real release build can take a while and shouldn't be used by default (bad newcomer experience). We tried to change the default BUILD to debug but it was a mess with the CIs :/ Got it. Thanks, Seb.
Re: Alligned gc allocation of struct
On Friday, 5 October 2018 at 14:55:04 UTC, Dennis wrote: On Friday, 5 October 2018 at 10:03:35 UTC, Kagamin wrote: GC allocations are 16 bytes aligned. Is that an implementation detail or well-defined behavior? The GC_Allocator doesn't support alignedAllocate from the IAllocate interface, which is kinda unfortunate. So I'm a little worried that this might change in the future.
Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 16:34:32 UTC, Paul Backus wrote: On Friday, 5 October 2018 at 06:56:49 UTC, Nicholas Wilson wrote: On Friday, 5 October 2018 at 06:44:08 UTC, Nicholas Wilson wrote: Alas is does not because each does not accept additional argument other than the range. Shouldn't be hard to fix though. https://issues.dlang.org/show_bug.cgi?id=19287 You can thread multiple arguments through to `each` using `std.range.zip`: tenRandomNumbers .zip(repeat(output)) .each!(unpack!((n, output) => output.appendln(n.to!string))); Full code: https://run.dlang.io/is/Qe7uHt Very interesting, thanks. It's a clever way to avoid the delegate capture issue. (Aside: A nested function that accesses 'output' from lexical context has the same issue as delegates wrt to capturing the variable.)
Re: DMD release build being faster than debug!
On Friday, 5 October 2018 at 14:11:22 UTC, Per Nordlöw wrote: I just noticed that building DMD~master via make -f posix.mak BUILD=debug currently takes 3.2 secs while building it via make -f posix.mak BUILD=release takes only 3.0 secs on my Ubuntu 18.04 64-bit machine! Are there more DMD switches other than `BUILD=release` I need to activate to produce the fastest possible compiler binary? Apart for compiling it with LDC, that is. Yeah BUILD more or less only defines in which folder the binaries will be stored as the default BUILD was RELEASE historically and the real release build can take a while and shouldn't be used by default (bad newcomer experience). We tried to change the default BUILD to debug but it was a mess with the CIs :/
Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 06:56:49 UTC, Nicholas Wilson wrote: On Friday, 5 October 2018 at 06:44:08 UTC, Nicholas Wilson wrote: Alas is does not because each does not accept additional argument other than the range. Shouldn't be hard to fix though. https://issues.dlang.org/show_bug.cgi?id=19287 You can thread multiple arguments through to `each` using `std.range.zip`: tenRandomNumbers .zip(repeat(output)) .each!(unpack!((n, output) => output.appendln(n.to!string))); Full code: https://run.dlang.io/is/Qe7uHt
Re: Alligned gc allocation of struct
On Friday, 5 October 2018 at 10:03:35 UTC, Kagamin wrote: GC allocations are 16 bytes aligned. Is that an implementation detail or well-defined behavior?
Re: DMD release build being faster than debug!
On Friday, 5 October 2018 at 14:11:22 UTC, Per Nordlöw wrote: Are there more DMD switches other than `BUILD=release` I need to activate to produce the fastest possible compiler binary? Apart for compiling it with LDC, that is. Ahh, that wasn't so hard to find once I looked inside the correct posix.mak. I guess I should do make -f posix.mak BUILD=release ENABLE_RELEASE=1
DMD release build being faster than debug!
I just noticed that building DMD~master via make -f posix.mak BUILD=debug currently takes 3.2 secs while building it via make -f posix.mak BUILD=release takes only 3.0 secs on my Ubuntu 18.04 64-bit machine! Are there more DMD switches other than `BUILD=release` I need to activate to produce the fastest possible compiler binary? Apart for compiling it with LDC, that is.
Re: Template/mixin ideas?
On Thursday, 4 October 2018 at 01:12:04 UTC, Chris Katko wrote: What's the alternative to using strings... for strings? Since the purpose is terminal output, you could just make a custom formatter, something like this: https://run.dlang.io/is/F51UCZ
Re: Alligned gc allocation of struct
On Friday, 5 October 2018 at 10:03:35 UTC, Kagamin wrote: GC allocations are 16 bytes aligned. That's perfect. Thank you!
Re: Alligned gc allocation of struct
GC allocations are 16 bytes aligned.
Re: Template/mixin ideas?
On Wednesday, 3 October 2018 at 11:01:53 UTC, Chris Katko wrote: I've got this simple task but I'm trying to perfect it as best I can to learn something in the process. I have Linux terminal ASCII codes for coloring terminal output. string red(string) { /* ... */ } "Hello world".red => "\033[31mHello World\033[0m" which translates to "[red]Hello World[reset to normal text]". I have to do some slight trickery so I can chain them. But it all works fine. __The function is the same__ no matter what kind of color, bold, etc attribute I want. The only difference is the tag/prefix string. So I have a table (or enum): enum colors{ reset = "\033[0m", red = "\033[31m", bold = "\033[1m" //... } Absolute perfection would be some way to add a single line to that enum (or table) and magically get a new function. I add "blue" with its prefix code to the enum and immediately I can do: "hello world".blue Add yellow = "\033..." and I can do: "hello world".bold.yellow https://run.dlang.io/gist/run-dlang/e0d0bcebe6c4edcc3cd0c2858183357d?compiler=dmd https://issues.dlang.org/show_bug.cgi?id=19286 prevents us from using static foreaches to declare the aliases.
Alligned gc allocation of struct
I've got a `struct Foo{ubyte16 field1, field2 fieldn;}` for which I would like a heap allocation `Foo* foo = new Foo();` But the fields itsself must be 16 bytes aligned for SIMD instructions. Is there a neat way to do this in D? As far as I can tell the GC_allocator doesn't do aligned allocations by default.
Re: Template/mixin ideas?
On Thursday, 4 October 2018 at 01:12:04 UTC, Chris Katko wrote: The mixin part wouldn't be slowed by strings, right? So the "slowness" is the invokation part which changes strings and forces GC allocations, I guess? Yep, that is right. What's the alternative to using strings... for strings? During the concatenation phase you'll use an Appender. Afterwards you retrieve the resulting string from the appender. It is very similar to a StringBuilder in other languages. See std.array.appender
Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 06:44:08 UTC, Nicholas Wilson wrote: Alas is does not because each does not accept additional argument other than the range. Shouldn't be hard to fix though. https://issues.dlang.org/show_bug.cgi?id=19287
Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 06:44:08 UTC, Nicholas Wilson wrote: On Friday, 5 October 2018 at 06:22:57 UTC, Nicholas Wilson wrote: tenRandomNumbers.each!((n,o) => o.appendln(n.to!string))(output); or tenRandomNumbers.each!((n, ref o) => o.appendln(n.to!string))(output); should hopefully do the trick (run.dlang.io seems to be down atm). Alas is does not because each does not accept additional argument other than the range. Shouldn't be hard to fix though. Yeah, that's what I was seeing also. Thanks for taking a look. Is there perhaps a way to limit the scope of the delegate to the local function? Something that would tell the compiler the delegate has a lifetime shorter than the struct. One specific it points out is that this a place where the BufferedOutputRange I wrote cannot be used interchangeably with other output ranges. It's minor, but the intent was to be able to pass this anyplace an output range could be used.
Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 06:22:57 UTC, Nicholas Wilson wrote: tenRandomNumbers.each!((n,o) => o.appendln(n.to!string))(output); or tenRandomNumbers.each!((n, ref o) => o.appendln(n.to!string))(output); should hopefully do the trick (run.dlang.io seems to be down atm). Alas is does not because each does not accept additional argument other than the range. Shouldn't be hard to fix though.
Re: Error: variable 'xyz' has scoped destruction, cannot build closure
On Friday, 5 October 2018 at 03:27:17 UTC, Jon Degenhardt wrote: I got the compilation error in the subject line when trying to create a range via std.range.generate. Turns out this was caused by trying to create a closure for 'generate' where the closure was accessing a struct containing a destructor. The fix was easy enough: write out the loop by hand rather than using 'generate' with a closure. What I'm wondering/asking is if there alternate way to do this that would enable the 'generate' approach. This is more curiosity/learning at this point. Below is a stripped down version of what I was doing. I have a struct for output buffering. The destructor writes any data left in the buffer to the output stream. This gets passed to routines performing output. It was this context that I created a generator that wrote to it. example.d- struct BufferedStdout { import std.array : appender; private auto _outputBuffer = appender!(char[]); ~this() { import std.stdio : write; write(_outputBuffer.data); _outputBuffer.clear; } void appendln(T)(T stuff) { import std.range : put; put(_outputBuffer, stuff); put(_outputBuffer, "\n"); } } void foo(BufferedStdout output) { import std.algorithm : each; import std.conv : to; import std.range: generate, takeExactly; import std.random: Random, uniform, unpredictableSeed; auto randomGenerator = Random(unpredictableSeed); auto randomNumbers = generate!(() => uniform(0, 1000, randomGenerator)); auto tenRandomNumbers = randomNumbers.takeExactly(10); tenRandomNumbers.each!(n => output.appendln(n.to!string)); } void main(string[] args) { foo(BufferedStdout()); } End of example.d- Compiling the above results in: $ dmd example.d example.d(22): Error: variable `example.foo.output` has scoped destruction, cannot build closure As mentioned, using a loop rather than 'generate' works fine, but help with alternatives that would use generate would be appreciated. The actual buffered output struct has more behind it than shown above, but not too much. For anyone interested it's here: https://github.com/eBay/tsv-utils/blob/master/common/src/tsvutil.d#L358 tenRandomNumbers.each!((n,o) => o.appendln(n.to!string))(output); or tenRandomNumbers.each!((n, ref o) => o.appendln(n.to!string))(output); should hopefully do the trick (run.dlang.io seems to be down atm). The problem is that `output` is captured by the delegate and this somehow causes problems (idk what or why). If the (perviously captured) variables are instead passed as parameters then there is no need to create a closure for the variable, so no problem. This is also the way to ensure that lambdas are @nogc if you ever need that.