Re: DConf 2019 Day 3 Livestream
On Friday, 10 May 2019 at 13:29:51 UTC, Les De Ridder wrote: Did anyone make a local copy of today's livestream by any chance? YouTube seems to only allow you to go back 2 hours into the stream. Check that link again in a day or two, the livestream archive for day 2 was only the last few hours for a while after it was streamed too but if you check it now you'll see it's got the full day. I'm guessing the same will be true for this one too. Some quirk on youtube's end I'm guessing
Re: alloca without runtime?
On Wednesday, 10 May 2017 at 20:25:45 UTC, aberba wrote: On Thursday, 4 May 2017 at 14:54:58 UTC, 岩倉 澪 wrote: On Thursday, 4 May 2017 at 12:50:02 UTC, Kagamin wrote: You can try ldc and llvm intrinsics http://llvm.org/docs/LangRef.html#alloca-instruction http://llvm.org/docs/LangRef.html#llvm-stacksave-intrinsic Ah, yep! pragma(LDC_alloca) void* alloca(size_t); This appears to work with ldc. It would be nice if there was a way to do this with dmd/other compilers as well though. If it were up to me I'd have alloca defined by the language standard and every compiler would have to provide an implementation like this. At the very least I'd like to have an alloca that works with dmd, as I want to do debug builds with dmd and release builds with ldc. embedded platform? An embedded platform would be a good use-case for this, but I'm just trying to do this on Linux x86_64 personally. It's a fun experiment to see how far I can push D to give me low-level control without dependencies
Re: alloca without runtime?
On Thursday, 4 May 2017 at 12:50:02 UTC, Kagamin wrote: You can try ldc and llvm intrinsics http://llvm.org/docs/LangRef.html#alloca-instruction http://llvm.org/docs/LangRef.html#llvm-stacksave-intrinsic Ah, yep! pragma(LDC_alloca) void* alloca(size_t); This appears to work with ldc. It would be nice if there was a way to do this with dmd/other compilers as well though. If it were up to me I'd have alloca defined by the language standard and every compiler would have to provide an implementation like this. At the very least I'd like to have an alloca that works with dmd, as I want to do debug builds with dmd and release builds with ldc.
Re: alloca without runtime?
On Sunday, 30 April 2017 at 05:07:31 UTC, 岩倉 澪 wrote: I've been playing around with using D with no runtime on Linux, but recently I was thinking it would be nice to have an alloca implementation. I was thinking I could just bump the stack pointer (with alignment considerations) but from what I understand compilers sometimes generate code that references variables relative to RSP instead of RBP? I've seen people saying that a proper alloca can't be implemented without help from the compiler... I took a peek in druntime and found rt.alloca which has __alloca implemented with inline asm. I tried throwing that in my project and calling it but it segfaults on rep movsq. The comments in the code suggest it is trying to copy temps on the stack but I seem to get a really large garbage RCX, I don't fully follow what is going on yet. Is there any way I can get a working alloca without using druntime, c runtime, etc? As a follow-up, here is a simple example of what I mean: first, let's create a main.d, we'll define our own entry point and make a call to alloca in main: extern (C): void _start() { asm nothrow @nogc { naked; xor RBP, RBP; pop RDI; mov RSI, RSP; and RSP, -16; call main; mov RDI, RAX; mov RAX, 60; syscall; ret; } } pragma(startaddress, _start); int main(int argc, char** argv) { import rt.alloca; void* a = __alloca(42); return 0; } Next, let's make an rt directory and copy the source of druntime's rt.alloca into rt/alloca.d Now let's compile these: dmd -betterC -debuglib= -defaultlib= -boundscheck=off -vgc -vtls -c -gc main.d rt/alloca.d Great, now we need to strip symbols out to make this work, like so: objcopy -R '.data.*[0-9]TypeInfo_*' -R '.[cd]tors.*' -R .eh_frame -R minfo -R .group.d_dso -R .data.d_dso_rec -R .text.d_dso_init -R .dtors.d_dso_dtor -R .ctors.d_dso_ctor -N __start_minfo -N __stop_minfo main.o objcopy -R '.data.*[0-9]TypeInfo_*' -R '.[cd]tors.*' -R .eh_frame -R minfo -R .group.d_dso -R .data.d_dso_rec -R .text.d_dso_init -R .dtors.d_dso_dtor -R .ctors.d_dso_ctor -N __start_minfo -N __stop_minfo alloca.o With that out of the way, we are ready to link: ld main.o alloca.o And when we try to run ./a.out we get a segfault. What I want is a way to allocate on the stack (size of allocation not necessarily known at compile-time) and for the compiler to be aware that it can't generate code that refers to variables on the stack relative to rsp, or anything else that might break the naive implementation of alloca as simply bumping rsp with inline asm. Apparently this "magic" __alloca can't be used outside of the compiler, or is there a way to make it work?
alloca without runtime?
I've been playing around with using D with no runtime on Linux, but recently I was thinking it would be nice to have an alloca implementation. I was thinking I could just bump the stack pointer (with alignment considerations) but from what I understand compilers sometimes generate code that references variables relative to RSP instead of RBP? I've seen people saying that a proper alloca can't be implemented without help from the compiler... I took a peek in druntime and found rt.alloca which has __alloca implemented with inline asm. I tried throwing that in my project and calling it but it segfaults on rep movsq. The comments in the code suggest it is trying to copy temps on the stack but I seem to get a really large garbage RCX, I don't fully follow what is going on yet. Is there any way I can get a working alloca without using druntime, c runtime, etc?
Re: D for scripting?
On Friday, 20 January 2017 at 15:05:51 UTC, Edwin van Leeuwen wrote: FYI dub also has a script option, which would allow you to include any dub projects in your script, e.g.: https://github.com/Abscissa/scriptlike/blob/master/USAGE.md#a-basic-script-in-d Of course then you'd have to turn the included .d files into a dub project. Wow, I had no idea dub has a script option. I'll take a look at that. Thanks for the tip.
Re: D for scripting?
On Friday, 20 January 2017 at 12:06:32 UTC, Kagamin wrote: You can symlink ~/scripts to /usr/local/bin/scripts and -I/usr/local/bin/scripts and keep all files with .d extensions there, create only symlinks in bin without extensions. Excellent idea; makes the shebang line a bit more wordy but perhaps this is better than changing the behaviour of rdmd.
Re: D for scripting?
On Friday, 20 January 2017 at 07:54:10 UTC, Jacob Carlborg wrote: It does. It's been fixed, for exactly this reason. This has already been fixed? Is this fix in a stable release yet? I might not be on the latest version...
D for scripting?
Last weekend I tried porting some old shell scripts to D, as I think D is actually extremely well suited as a shell script replacement. My scripts are so much more robust now and do things like rolling back on errors and having debug mode, all with roughly the same amount of lines as the flimsy old shell scripts. I have two points of feedback regarding rdmd: * If you name your script without a .d extension, rdmd fails saying the module is in script.d which cannot be read * rdmd doesn't seem to play nice with symlinks I keep my scripts in ~/scripts so that I can just pull them from github and go on my merry way, with symlinks in /usr/local/bin, but rdmd doesn't -I the real directory, it does -I/usr/local/bin, and if I symlink a script.d as /usr/local/bin/script, it can't find the module. I can pass -I/home/mio/scripts on the shebang line at least... Furthermore, if I -J a folder with string imports I would have to type out the fully qualified path just like with -I. It would be so much more convenient if rdmd would follow the symlink to the scripts directory, change the working directory, and then compile, or something like that. Is anyone else using D for scripting? I feel like the shebang is totally worth it if I could name my file without .d and symlink to it. Would it be reasonable to change rdmd to allow these features? I'd be happy to look into writing a patch for it if it wouldn't be a waste of time.
Re: The Mystery of the Misbehaved Malloc
On Saturday, 30 July 2016 at 05:21:26 UTC, ag0aep6g wrote: On 07/30/2016 07:00 AM, 岩倉 澪 wrote: auto mem = malloc(2^^31); 2^^31 is negative. 2^^31-1 is the maximum positive value of an int, so 2^^31 wraps around to int.min. Try 2u^^31. bah, I'm an idiot! CASE CLOSED. Thanks for the help :P
The Mystery of the Misbehaved Malloc
So I ran into a problem earlier - trying to allocate 2GB or more on Windows would fail even if there was enough room. Mentioned it in the D irc channel and a few fine folks pointed out that Windows only allows 2GB for 32-bit applications unless you pass a special flag which may or may not be a good idea. I think to myself, "Easy solution, I'll just compile as 64-bit!" But alas, my 64-bit executable suffers the same problem. I boiled it down to a simple test: void main() { import core.stdc.stdlib : malloc; auto mem = malloc(2^^31); assert(mem); import core.stdc.stdio : getchar; getchar(); } I wrote this test with the C functions so that I can do a direct comparison with a C program compiled with VS 2015: #include #include #include #include int main(int argc, char *argv[]) { void *ptr = malloc((size_t)pow(2, 31)); assert(ptr); getchar(); return 0; } I compile the D test with: `ldc2 -m64 -test.d` I compile the C test with: `CL test.c` `file` reports "PE32+ executable (console) x86-64, for MS Windows" for both executables. When the C executable runs, I see the allocation under "commit change" in the Resource Monitor. When the D executable runs, the assertion fails! The D program is able to allocate up to 2^31 - 1 before failing. And yes, I do have enough available memory to make a larger allocation. Can you help me solve this mystery?
Re: Create Windows "shortcut" (.lnk) with D?
On Sunday, 6 March 2016 at 11:00:35 UTC, John wrote: On Sunday, 6 March 2016 at 03:13:23 UTC, 岩倉 澪 wrote: IShellLinkA* shellLink; IPersistFile* linkFile; Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong! In D, interfaces are references, so it should be: IShellLinkA shellLink; IPersistFile linkFile; That's exactly what the problem was, thank you!!
Re: Create Windows "shortcut" (.lnk) with D?
On Sunday, 6 March 2016 at 05:00:55 UTC, BBasile wrote: If you don't want to mess with the Windows API then you can dynamically create a script (I do this in CE installer): This might be an option but I'd prefer to use the Windows API directly. I don't know vb script and maintaining such a script inline would just add cognitive overhead I think. If I can't get it working with the Windows API; I'll probably have to do it this way though. Thanks for the suggestion!
Create Windows "shortcut" (.lnk) with D?
I'm creating a small installation script in D, but I've been having trouble getting shortcut creation to work! I'm a linux guy, so I don't know much about Windows programming... Here are the relevant bits of code I have: import core.sys.windows.basetyps, core.sys.windows.com, core.sys.windows.objbase, core.sys.windows.objidl, core.sys.windows.shlobj, core.sys.windows.windef; import std.conv, std.exception, std.file, std.format, std.path, std.stdio, std.string, std.utf, std.zip; //Couldn't find these in core.sys.windows extern(C) const GUID CLSID_ShellLink = {0x00021401, 0x, 0x, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; extern(C) const IID IID_IShellLinkA = {0x000214EE, 0x, 0x, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; extern(C) const IID IID_IPersistFile = {0x010B, 0x, 0x, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; void main() { string programFolder, dataFolder, desktopFolder; { char[MAX_PATH] _programFolder, _dataFolder, _desktopFolder; SHGetFolderPathA(null, CSIDL_PROGRAM_FILESX86, null, 0, _programFolder.ptr); SHGetFolderPathA(null, CSIDL_LOCAL_APPDATA, null, 0, _dataFolder.ptr); SHGetFolderPathA(null, CSIDL_DESKTOPDIRECTORY, null, 0, _desktopFolder.ptr); programFolder = _programFolder.assumeUnique().ptr.fromStringz(); dataFolder = _dataFolder.assumeUnique().ptr.fromStringz(); desktopFolder = _desktopFolder.assumeUnique().ptr.fromStringz(); } auto inputFolder = buildNormalizedPath(dataFolder, "Aker/agtoolbox/input"); auto outputFolder = buildNormalizedPath(dataFolder, "Aker/agtoolbox/output"); CoInitialize(null); scope(exit) CoUninitialize(); IShellLinkA* shellLink; IPersistFile* linkFile; CoCreateInstance(_ShellLink, null, CLSCTX_INPROC_SERVER, _IShellLinkA, cast(void**)); auto exePath = buildNormalizedPath(programFolder, "Aker/agtoolbox/agtoolbox.exe").toStringz(); shellLink.SetPath(exePath); auto arguments = format("-i %s -o %s", inputFolder, outputFolder).toStringz(); shellLink.SetArguments(arguments); auto workingDirectory = programFolder.toStringz(); shellLink.SetWorkingDirectory(workingDirectory); shellLink.QueryInterface(_IPersistFile, cast(void**)); auto linkPath = buildNormalizedPath(desktopFolder, "agtoolbox.lnk").toUTF16z(); linkFile.Save(linkPath, TRUE); } I tried sprinkling it with print statements and it crashes on shellLink.setPath(exePath); This is the full script: https://gist.github.com/miotatsu/1cc55fe29d8a8dcccab5 I found the values for the missing windows api bits from this: http://www.dsource.org/projects/tutorials/wiki/CreateLinkUsingCom I compile with: dmd agtoolbox-installer.d ole32.lib I got the ole32.lib from the dmd install Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong!
Re: Concurrency Confusion
On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote: Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911 actually this no longer appears to be true? Passing -1.msecs as the duration gives me an assertion failure: core.exception.AssertError@std/concurrency.d(1902): Assertion failure Took a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904 If you look at the implementation of receiveTimeout, you'll see that it no longer has these lines from the stack overflow answer: if( period.isNegative || !m_putMsg.wait( period ) ) return false; https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L824
Re: Concurrency Confusion
On Monday, 10 August 2015 at 22:50:15 UTC, sigod wrote: On Monday, 10 August 2015 at 22:21:18 UTC, 岩倉 澪 wrote: Took a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904 It looks like you're trying to use `receiveTimeout` like this: bool value; receiveTimeout(-1.msecs, value); Ah, nope I just assumed the closest assert to the line mentioned in the assertion failure was the culprit without thinking about it much. You are correct that the assertion your pull requests removes is the one that gave me trouble. I'll leave it as 0.msecs until your pull request is merged and a new release made, thanks for the help!
Re: Concurrency Confusion
On Sunday, 9 August 2015 at 21:06:10 UTC, anonymous wrote: On Sunday, 9 August 2015 at 17:43:59 UTC, 岩倉 澪 wrote: Afaict it is the best way to do what I'm trying to do, and since the data is mutable and cast to immutable with assumeUnique, casting it back to mutable shouldn't be a problem. Technically casting away immutable might be undefined behaviour and it might be an ugly hack, but I don't see a more idiomatic solution. I think casting to shared and back would be better. Unfortunately, it looks like std.concurrency.send doesn't like shared arrays. I filed an issue: https://issues.dlang.org/show_bug.cgi?id=14893 I agree! I initially tried to cast to shared and back, but when I encountered that compiler error I decided to go with immutable. I assumed that there was a good reason it didn't work, rather than a deficiency in the language. Hopefully the issue can be resolved, leading to a nicer solution. :)
Re: Concurrency Confusion
On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote: Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911 On Saturday, 8 August 2015 at 13:34:24 UTC, Chris wrote: Note aside: if you only import what you need (say `import std.concurrency : receiveTimeout; std.datetime : msecs`), you can reduce the size of the executable considerably as your program grows. Thanks for the tips!
Re: Concurrency Confusion
On Saturday, 8 August 2015 at 05:14:20 UTC, Meta wrote: I'm not completely sure that it's bad in this case, but you really shouldn't be casting away immutable. It's undefined behaviour in D. Afaict it is the best way to do what I'm trying to do, and since the data is mutable and cast to immutable with assumeUnique, casting it back to mutable shouldn't be a problem. Technically casting away immutable might be undefined behaviour and it might be an ugly hack, but I don't see a more idiomatic solution.
Re: Concurrency Confusion
On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote: To stop threads immediately, I've found that the best way is to use a shared variable, typically a bool, that is changed only in one place. ... Unfortunately, sending an abort message to a thread as in `send(thread, true)` takes too long. Setting a global flag like ABORT is instantaneous. Beware of data races though. You might want to have a look at: http://ddili.org/ders/d.en/concurrency_shared.html Especially `synchronized` and atomicOp. Ah, I already had a variable like ABORT in my application for signaling the main thread to close, so this was a surprisingly painless change! I made that variable shared and then did the following: instead of ABORT = true; I now do import core.atomic; atomicStore!(MemoryOrder.rel)(ABORT, true); and instead of if(ABORT) break; I now do import core.atomic; if(atomicLoad!(MemoryOrder.acq)(ABORT)) break; This works great, and with the memory ordering specified I do not see a noticeable difference in performance, whereas with the default memory ordering my ~36 second processing takes ~38 seconds. One concern I had was that `break` might be a bad idea inside of a parallel foreach. Luckily, it seems that the author(s) of std.parallelism thought of this - according to the documentation break inside of a parallel foreach throws an exception and some clever exception handling is done under the hood. I don't see an uncaught exception when I close my application, but it is now able to close without having to wait for the worker thread to complete, so everything seems fine and dandy! Thanks for the help! On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote: receiveTimeout can be used like this: ... My problem is that when you do this: received = receiveTimeout(600.msecs, (string message) { // === Receiving a value writeln(received: , message); }); message is local to the delegate that receiveTimeout takes. I want to use message outside of the delegate in the receiving thread. However, if you send an immutable value from the worker thread, afaict there would be no way to assign it to a global/outer variable without making a mutable copy (expensive!) I haven't really spent much time trying to pass my message as mutable via shared yet, but hopefully that could work...
Re: Concurrency Confusion
On Friday, 7 August 2015 at 22:13:35 UTC, 岩倉 澪 wrote: message is local to the delegate that receiveTimeout takes. I want to use message outside of the delegate in the receiving thread. However, if you send an immutable value from the worker thread, afaict there would be no way to assign it to a global/outer variable without making a mutable copy (expensive!) I haven't really spent much time trying to pass my message as mutable via shared yet, but hopefully that could work... Found the answer to this :) http://forum.dlang.org/post/mailman.1706.1340318206.24740.digitalmars-d-le...@puremagic.com I send the results from my worker thread with assumeUnique, and then simply cast away immutable in the receiving thread like so: (in module scope) Bar[] baz; (in application loop) import std.array if(baz.empty) { import std.concurrency, std.datetime; receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; }); }
Re: Concurrency Confusion
On Saturday, 8 August 2015 at 00:39:57 UTC, 岩倉 澪 wrote: receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; }); Whoops, that should be: receiveTimeout(0.msecs, (immutable(Bar)[] bar){ baz = cast(Bar[])bar; });
Re: Concurrency Confusion
On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote: // in real app use `receiveTimeout` to do useful stuff until // result message is received auto output = receiveOnly!(immutable(Bar)[]); New question: how would I receive a immutable value with receiveTimeout? I need the results from my worker thread outside of the delegate that receiveTimeout takes. Also: what is the best way to kill off the worker thread when I close the application, without having to wait for the worker thread to complete? My first thought was to use receiveTimeout in the worker thread, but the work is being done in a parallel foreach loop, and I am not sure if there is a way to safely use receiveTimeout in a parallel situation... I also found Thread.isDaemon in core.thread. I tried doing auto thread = Thread.getThis(); thread.isDaemon = true; at the start of the worker thread, but it still seems to wait for it to complete before closing. Thanks again!
Re: Thread communication
On Wednesday, 5 August 2015 at 14:31:20 UTC, Marc Schütz wrote: It was a conscious decision not to provide a kill method for threads, because it is impossible to guarantee that your program is still consistent afterwards. What about the situation where we want to kill worker threads off when closing a program? For example, I have a program with a thread that does some heavy computation in the background. When the application is closed, I want it to abort that computation, however I can't just slap a receiveTimeout in the worker thread because it is doing its work in a parallel foreach loop.
Re: Concurrency Confusion
On Tuesday, 4 August 2015 at 08:36:26 UTC, John Colvin wrote: Do you mean this instead? spawn(fooPtrToBarArr, foo, bar); Yep, that was a typo when writing up the post! Anyway, you need to use shared, not __gshared, then it should work. I have been wary of shared because of: https://p0nce.github.io/d-idioms/#The-truth-about-shared
Re: Concurrency Confusion
On Tuesday, 4 August 2015 at 10:37:39 UTC, Dicebot wrote: std.concurrency does by-value message passing (in this case just ptr+length), it never deep copies automatically I assumed that it would deep copy (in the case of mutable data) since the data being sent is thread-local (unless I am misunderstanding something)
Concurrency Confusion
Hi all, I'm a bit confused today (as usual, haha). I have a pointer to a struct (let's call it Foo) allocated via a C library. I need to do some expensive computation with the Foo* to create a Bar[], but I would like to do that computation in the background, because the Bar[] is not needed right away. I definitely do not want there to be a copy of all elements of the Bar[] between threads, because it is very large. I tried to implement it like this: void fooPtrToBarArr(in shared Foo* f, out shared Bar[] b){ /*do work*/ } __gshared Foo* foo; foo = allocateFoo(); __gshared Bar[] bar; spawn(foo, bar); To my dismay, it results in a cryptic compiler error: template std.concurrency.spawn cannot deduce function from argument types !()(void function(shared(const(Foo*)) f, out shared(Bar[]) b), Foo*, Bar[]), candidates are: /usr/include/dlang/dmd/std/concurrency.d(466): std.concurrency.spawn(F, T...)(F fn, T args) if (isSpawnable!(F, T)) Any help would be greatly appreciated :)
Re: Concurrency Confusion
On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote: auto output = receiveOnly!(immutable(Bar)[]); Won't message passing like this result in an expensive copy, or does the cast to immutable via assumeUnique avoid that?
Re: Concurrency Confusion
On Tuesday, 4 August 2015 at 11:42:54 UTC, Dicebot wrote: On Tuesday, 4 August 2015 at 11:33:11 UTC, 岩倉 澪 wrote: On Tuesday, 4 August 2015 at 10:37:39 UTC, Dicebot wrote: std.concurrency does by-value message passing (in this case just ptr+length), it never deep copies automatically I assumed that it would deep copy (in the case of mutable data) since the data being sent is thread-local (unless I am misunderstanding something) It is heap-allocated and in there is no thread-local heap currently in D - only globals and static variables. std.concurrency never deep copies - if you are trying to send data which contains indirections (pointers/arrays) _and_ is not marked either immutable or shared, it will simply not compile. Ahh, thanks for the clarification! That makes a lot of sense
Re: Why aren't you using D at work?
On Thursday, 28 May 2015 at 14:38:51 UTC, Manu wrote: I've been using D in all my personal projects for years now, but I lament coding C at work every day, and I pine for salvation. I'm pretty lucky, I work at a small startup that does drones for agriculture and have had the freedom to pick whatever language I think is best for the tasks at hand. As such, we now have some image analysis software in the works that is 100% D (save for the C libraries it uses and a bit of shell script). That said though, it sounds like we're getting ENVI cheap, and I have an opportunity to take a training course on extending it with IDL, so that might end up being a better fit for the project in the long run. The other major project I've worked on there is a web app which I did in JS as there's hardly any choice in that domain.
Re: Do strings with enum allocate at usage point?
On Tuesday, 17 March 2015 at 18:25:00 UTC, Ali Çehreli wrote: Strings are fine and fortunately it is very easy to test: enum arr = [ 1, 2 ]; enum s = hello; void main() { assert(arr.ptr !is arr.ptr); assert(s.ptris s.ptr); } Ali Ah, that is good to know. Thanks!
Do strings with enum allocate at usage point?
I often hear it advised to avoid using enum with arrays because they will allocate at the usage point, but does this also apply to strings? strings are arrays, so naively it seems that they would, but that seems odd to me. I would imagine string literals end up in the data segment as they are immutable. As a continuation of this question, I know that string literals have an implicit null delimiter, so it should be correct to pass a literal.ptr to a function taking a C-string, and presumably this still applies when using enum. However, if enum implies allocation at the usage point for strings, one would be better served with static, meaning one would need to be explicit: static foo = bar\0?
Re: Difference between concatenation and appendation
On Monday, 26 January 2015 at 01:17:17 UTC, WhatMeWorry wrote: Ok, I just made up that word. But what is the difference between appending and concatenating? Page 100 of TPDL says The result of the concatenation is a new array... and the section on appending talks about possibly needing expansion and reallocation of memory. But I still don't feel like I have a grasp on the subtleties between them. Can someone give a short and sweet rule of thumb? It might be so obvious that I'll regret posting this. Thanks. I'm no expert, so take what I say with a grain of salt. That said, here is my understanding: When you append to an array with ~=, it attempts to reallocate the array in-place, meaning it allocates on top of the already used space, but grabs some more space past the end of the array. If there isn't enough space after the array then obviously it can't do that, so it allocates memory somewhere else that it can fit and then it copies the contents of the array to the new location. If you were to do myArray = myArray ~ moreStuff; I assume this is no different from ~=. Conceptually ~= is just syntactic sugar in the same way that += or -= is, you are just doing a concatenation and then updating the array to point to the new result. The fact that it can reallocate in place if there is enough space is just like an optimization, in my mind.
Re: Will D ever get optional named parameters?
Slightly off-topic, but I'm learning the constructed (human) language lojban, and the FA and zo'e constructs remind me of named parameters and _. In lojban there are constructs called selbri that are kind of like a programming languages functions: vecnu = x1 sells x2 to x3 for price x4 x1, x2, x3, x4 representing positional parameters If you don't want to specify one you pass zo'e which is like the word something. If you leave off some sumti (args), it is equivilant to passing zo'e. Five selbri parameters have names, fa, fe, fi, fo, fu. So you can pass them in any order if you put those tags in front. More on-topic: I don't really think named parameters are a worthwhile feature, but I really hope D gets __. That seems like it wouldn't have any major conflicts with implementing, and would give functions a bit of a boost in terms of expressiveness.
Re: Will D ever get optional named parameters?
On Wednesday, 15 October 2014 at 11:52:13 UTC, bearophile wrote: ketmar: besides, nested foreach with '_' is not working. but __ can generate unique temporary variable each time. The point is to introduce a little breaking change in D and use _ as don't care, so you can reuse it for nested scoped and for tuple unpacking, and for other similar future purposes. Bye, bearophile I agree that _ would be the ideal syntax, but why make a breaking change when it is unnecessary? __ would serve just as well and it is only one extra character. It is already reserved so it would be reasonable to put it to good use.
Re: Will D ever get optional named parameters?
On Tuesday, 14 October 2014 at 03:34:06 UTC, Ary Borenszweig wrote: One simple thing we did in Crystal is to allow invoking a function with named arguments only for arguments that have a default value. For example: void foo(int x, int y = 2, int z = 3) { ... } foo(x, y: 10); foo(x, y: 10, z: 20); foo(x, z: 30) But not this: foo(x: 10) The logic behind this is that named arguments are usually wanted when you want to replace one of the default values while keeping the others' defaults. You could specify names for arguments that don't have a default value, but that only gives a small readability aid. Changing a default value in the middle is a new feature. This greatly simplifies the logic, since parameter reordering can only happen for names that have default values and you can always fill the gaps. Also, default values can also appear last in a function signature. Another thought I had is that an alternative could be to have some special syntax to say use the default for this parameter. I do not have experience implementing languages so perhaps I am wrong, but it seems like it should be possible for the compiler to get the default value and replace some placeholder with it. Something like: void foo(int a = 42, int b = 0){} foo(@default, 7); //rewritten to foo(42, 7);
Will D ever get optional named parameters?
From what I've found, there was some work on this in the past (http://forum.dlang.org/thread/wokfqqbexazcguffw...@forum.dlang.org?page=6#post-thclpgdlfxxhhfklwsoj:40forum.dlang.org), but a pull request was never made/I don't seem to find discussion about adding it as a feature anywhere. I think optional named parameters would be a nice addition, either to the core language, or something like the monadic solution from that old thread in phobos. Are there good reasons not to add something like this to the language, or is it simply a matter of doing the work? Has it been discussed much?
Re: Will D ever get optional named parameters?
On Monday, 13 October 2014 at 08:48:11 UTC, Walter Bright wrote: Named parameters interact badly with overloading. Good point, I hadn't thought of that!
Re: Will D ever get optional named parameters?
On Monday, 13 October 2014 at 10:53:50 UTC, ketmar via Digitalmars-d wrote: if we'll add proper AA literals, they can be used instead. methinks. I think this would be a decent alternative. On Monday, 13 October 2014 at 16:08:08 UTC, ponce wrote: Work-around I see a lot in C++: --- bool filled = true; drawCircle(filled); --- instead of: --- drawCircle(true); --- This doesn't provide all the benefit of named parameters (in particular, their use in combination with default arguments Other workarounds include associative arrays, and the so-called Named Parameter Idiom http://www.parashift.com/c++-faq-lite/named-parameter-idiom.html
Re: How to pass a member function/delegate into a mixin template?
On Monday, 15 September 2014 at 21:37:50 UTC, John Colvin wrote: would this work for you? alias is the usual way of taking a function as a template parameter. mixin template EventListener(alias slot) Ah, thanks for the help! That works great. :)
How to pass a member function/delegate into a mixin template?
Hi all, I've been reading D Cookbook, in which the author recommends the use of mixin templates to essentially hold boilerplate code for classes (page 28). Referencing TDPL reaffirms this strategy. With this design choice in mind, I would like to be able to use a mixin template that creates a slot for me (as in signals slots) and provides a constructor that connects it to the signal. The closest I have come is in the simplified example given below: EventHandler event_handler; class EventHandler{ ... mixin std.signals.Signal!Event; ... } mixin template EventListener(void delegate(Event) slot){ private this() in{ assert(event_handler); } body{ event_handler.connect(eventListener); } private void eventListener(Event e){ slot(e); } } class Foo{ mixin EventListener!((e){ ... }); } Sadly, this code does not compile. My understanding (and correct me if I'm wrong) is that this does not compile because I cannot create such a delegate, as the scope that it would be in is not available at compile time (it would be objects instantiated from class Foo in this example). One strategy that works is to not pass anything to the mixin template, and have the mixin template use a function that is presumed to exist. It is then the duty of the class writer to make sure a function of the correct name and signature exists if they use this mixin. However, I worry that this is poor/brittle design. What is the best approach to achieve this? Thanks, Mio
GC can collect object allocated in function, despite a pointer to the object living on?
Hello, I've been interested in the D language for a few years now, but only dabble. I have read TDPL and recently started reading D Cookbook. On the side, I started to write a small game in D, but ran into a problem. I would greatly appreciate any help! My design is a simple state machine. I have a module game.states, which includes: interface IState{ void handleEvents(); void renderFrame(); } IState *currentState; string nextState; void changeState(){ if(nextState != WaitState nextState != ExitState){ auto newState = cast(IState) Object.factory(game.states.~nextState); import std.exception; enforce(newState); currentState = newState; nextState = WaitState; } } class TitleState : IState{ void handleEvents(){ ... } void renderFrame(){ ... } } ... } and the game loop is of the following form: //init state nextState = TitleState; changeState(); //game loop while(nextState != ExitState){ currentState.handleEvents(); currentState.renderFrame(); changeState(); } However, it appears that the changeState function has a bug. I believe the problem is that when changeState returns, newState gets garbage collected, despite currentState pointing to it. I come from a C++ background, so I am not used to garbage collection. Normally the changeState function would explicitly free the old state, and allocate the new one. Am I correct that newState is liable to be collected after changeState returns? Is there an easy fix? Is my design fundamentally flawed within the context of garbage collection? If so, what kind of design would you recommend instead?
Re: GC can collect object allocated in function, despite a pointer to the object living on?
Thank you for the help! I just removed the unnecessary indirection and it is working great! I was aware that interface and object variables are reference types, but it slipped my mind. I'm too used to the C++ way of things still :p On Saturday, 16 August 2014 at 22:41:45 UTC, Sean Kelly wrote: Interface and object variables are reference types--you don't need the '*' to make them so. By adding the extra layer of indirection you're losing the only reference the GC can decipher to the currentState instance.
Re: GC can collect object allocated in function, despite a pointer to the object living on?
I see now, makes sense. :) On Saturday, 16 August 2014 at 22:43:21 UTC, Chris Cain wrote: This is actually not garbage collection. newState is making a pointer to a reference that is located on the stack (that is, when you return from that function you now have a pointer that may at any time become overwritten and made invalid.)