Re: Creating immutable arrays in @safe code
On 17.07.21 00:27, H. S. Teoh wrote: Hmm, OK. Not sure why .array isn't being inferred as unique... but yeah, you probably have to resort to using @trusted with .assumeUnique. In addition to `pure`, you also need a const/immutable input and a mutable output, so that the output cannot be a slice of the input. For std.array.array it might be possible to carefully apply `Unqual` to the element type. I tried doing that, but `-preview=dip1000` causes trouble. This fails: int[] array(const int[] input) pure nothrow @safe { int[] output; foreach (element; input) output ~= element; return output; } void main() pure nothrow @safe { const int[] c = [1, 2, 3]; immutable int[] i = array(c); /* Without `-preview=dip1000`: works, because the result is unique. With `-preview=dip1000`: "Error: cannot implicitly convert". */ } I'm not sure what's going on. `pure` being involved makes me think of issue 20150. But it also fails with my fix for that issue. So maybe it's another bug.
Re: Hello world/Web server task on RosettaCode fails
On Friday, 16 July 2021 at 20:04:21 UTC, jfondren wrote: On Friday, 16 July 2021 at 19:25:32 UTC, btiffin wrote: Using gdc-11 and Seamonkey. https://rosettacode.org/wiki/Hello_world/Web_server#D does not compile. The `while` as you noted is wrong. The server also doesn't turn REUSEADDR on for the server socket, so this will be very annoying to test as you'll frequently get "address already in use" errors when you restart the server. The delimited string leads to your last problem: a blank space between the headers and the body of the response results in "\r\n \r\n" being sent rather than "\r\n\r\n", so the browser gives up on the invalid HTTP. Ahh, thanks. The spaces. And turning on REUSEADDR made playing with the code a fair bit more fun. But, I mainly made the note to motivate a D aficionado to update and fix the Rosetta entry so that it at least compiles. Perhaps the whole *be bold* thing, and make the sources as idiomatic and correctly concise as D deserves. As a for instance, task description calls for Goodbye as the text in the solution. This works if you're careful to not re-add any stray whitespace in the response: ... But this *still violates HTTP* by not receiving the client's request, so it's still not a good answer for the task. A vibe hello world would make a lot more sense: https://github.com/vibe-d/vibe.d/blob/master/examples/http_server/source/app.d If this is the wrong place for this kind of info note, I'll gladly move to or redo the post in a more appropriate spot. You're in the right place. Cool. It's a nice place. :-) Cheers
Re: Creating immutable arrays in @safe code
On 7/16/21 3:21 PM, Dennis wrote: > But `pure` is no silver bullet: Agreed. I occasionally struggle with these issues as well. Here is a related one: import std; void foo(const int[] a) { auto b = a.array; b.front = 42; // Error: cannot modify `const` expression `front(b)` } I think that is a Phobos usability issue with array() because the freshly *copied* int elements are const. Really? So just because the programmer promised not to modify the parameter, now he/she is penalized to be *safe* with own data. I am not sure whether array() is the only culprit with this problem. (I think array() can be improved to pick mutable type for element types that have no indirections.) > ```D > import std; > > pure: @safe: > > struct Expression > { > immutable(Expression)[] children; > int value; > } > > Expression withSortedChildren(Expression exp) > { > return Expression(expr.children.dup.sort!((a, b) => a.value < > b.value).release); > } > ``` > >> Error: cannot implicitly convert expression >> `sort(dup(cast(const(Expression)[])expr.children)).release()` of type >> `Expression[]` to `immutable(Expression)[]` > > I've tried structuring it in a way that makes the compiler allow the > conversion to immutable, but had no luck so far. I don't have a solution and you have more experience with this. :/ Ali
Re: Creating immutable arrays in @safe code
On Fri, Jul 16, 2021 at 10:23:31PM +, Dennis via Digitalmars-d-learn wrote: > On Friday, 16 July 2021 at 20:45:11 UTC, H. S. Teoh wrote: > > Have you tried `pure`? > > The code in question is all `@safe pure nothrow`. Hmm, OK. Not sure why .array isn't being inferred as unique... but yeah, you probably have to resort to using @trusted with .assumeUnique. T -- Тише едешь, дальше будешь.
Re: Creating immutable arrays in @safe code
On Friday, 16 July 2021 at 20:45:11 UTC, H. S. Teoh wrote: Have you tried `pure`? The code in question is all `@safe pure nothrow`.
Re: Creating immutable arrays in @safe code
On Friday, 16 July 2021 at 20:39:41 UTC, Ali Çehreli wrote: So to me, newly created data should be mutable for the most usability. It's clear that I stripped away too much context with the toy examples, so let me try to add some back. I don't like forcing the use of `immutable` in general, but it's useful for transforming reference types into value types (inspired by [invariant strings](https://www.digitalmars.com/articles/b01.html) and `std.bigint`). The actual data structure I'm working with is a tree that looks like: ```D struct Expression { immutable(Expression)[] children; int value; } ``` Now the function is 'pure' and the caller's data is 'immutable' because the caller decided it had to be immutable. I've encountered the use of `pure` for creating immutable data before, e.g: [Function Purity and Immutable Data Structure Construction](https://www.digitalmars.com/articles/b92.html). But `pure` is no silver bullet: ```D import std; pure: @safe: struct Expression { immutable(Expression)[] children; int value; } Expression withSortedChildren(Expression exp) { return Expression(expr.children.dup.sort!((a, b) => a.value < b.value).release); } ``` Error: cannot implicitly convert expression `sort(dup(cast(const(Expression)[])expr.children)).release()` of type `Expression[]` to `immutable(Expression)[]` I've tried structuring it in a way that makes the compiler allow the conversion to immutable, but had no luck so far.
Re: Creating immutable arrays in @safe code
On Fri, Jul 16, 2021 at 08:19:32PM +, Dennis via Digitalmars-d-learn wrote: [...] > ```D > immutable(int)[] positive(int[] input) @safe > { > return input.filter!(x => x > 0).array; > } > ``` [...] > I could make another primitive (`iarraySort`), but I wonder if there > are more convenient ways to create immutable data in general? Have you tried `pure`? T -- They say that "guns don't kill people, people kill people." Well I think the gun helps. If you just stood there and yelled BANG, I don't think you'd kill too many people. -- Eddie Izzard, Dressed to Kill
Re: Creating immutable arrays in @safe code
On 7/16/21 1:19 PM, Dennis wrote: > I like passing around immutable data I think the D community needs to talk more about guidelines around 'immutable'. We don't... And I lack a complete understanding myself. :) To me, 'immutable' is a demand of the user from the provider that the data will not mutate. So, I don't agree with the sentiment "I like passing around immutable data" because 'immutable' limits usability without a user to demand it to begin with. To me, 'immutable' must be used when really needed. > , but I don't like creating it. I think making newly-created data 'immutable' renders it less useful. (The caller cannot mutate it.) So to me, newly created data should be mutable for the most usability. 'immutable' should be decided by the caller. Luckily, we have 'pure' allows the caller to make it 'immutable' effortlessly: import std; pure int[] positive(int[] input) @safe { return input.filter!(x => x > 0).array; } void main() { immutable p = positive([1, 2]); } Now the function is 'pure' and the caller's data is 'immutable' because the caller decided it had to be immutable. On the other hand, the function is happier because it is useful to callers that may mutate the data. :) Ali
Creating immutable arrays in @safe code
I like passing around immutable data, but I don't like creating it. Here are some toy examples to illustrate: ```D immutable(int)[] positive(int[] input) @safe { return input.filter!(x => x > 0).array; } ``` Error: cannot implicitly convert expression `array(filter(input))` of type `int[]` to `immutable(int)[]` So we need to tell the compiler the data is unique, but that's not `@safe`: ```D immutable(int)[] positive(int[] input) @safe { return input.filter!(x => x > 0).array.assumeUnique(); } ``` Error: `@safe` function `positive` cannot call `@system` function `assumeUnique` I can use `.idup` instead of `assumeUnique()` in `@safe` code, but that makes a redundant copy. We could mark the function `@trusted`, but I don't want `@trusted` functions all over my code, so I thought I'd make a little helper function: ```D auto iarray(R)(R range) { auto result = range.array; return (() @trusted => result.assumeUnique)(); } ``` And I got plenty of use out of it so far. Maybe something like that already exists in Phobos, but I couldn't find it. It has its limits however: ```D immutable(int)[] sortedPositive(int[] input) @safe { return input.filter!(x => x > 0).iarray.sort.release; } ``` That doesn't work because you can't sort an immutable array, so we're back to: ```D immutable(int)[] sortedPositive(int[] input) @trusted { return input.filter!(x => x > 0).array.sort.release.assumeUnique(); } ``` I could make another primitive (`iarraySort`), but I wonder if there are more convenient ways to create immutable data in general?
Re: Hello world/Web server task on RosettaCode fails
On Friday, 16 July 2021 at 20:04:21 UTC, jfondren wrote: static const greeting = q"EOF Or just `immutable greeting = ...`
Re: Hello world/Web server task on RosettaCode fails
On Friday, 16 July 2021 at 19:25:32 UTC, btiffin wrote: Using gdc-11 and Seamonkey. https://rosettacode.org/wiki/Hello_world/Web_server#D does not compile. The `while` as you noted is wrong. The server also doesn't turn REUSEADDR on for the server socket, so this will be very annoying to test as you'll frequently get "address already in use" errors when you restart the server. The delimited string leads to your last problem: a blank space between the headers and the body of the response results in "\r\n \r\n" being sent rather than "\r\n\r\n", so the browser gives up on the invalid HTTP. This works if you're careful to not re-add any stray whitespace in the response: ```d import std.socket, std.array; ushort port = 8080; void main() { Socket listener = new TcpSocket; listener.bind(new InternetAddress(port)); listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1); listener.listen(10); Socket currSock; while (null !is (currSock = listener.accept())) { currSock.sendTo(replace(q"EOF HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Hello, world! Hello, world! EOF", "\n", "\r\n")); currSock.close(); } } ``` Personally I'd prefer something more like: ```d import std.socket : Socket, TcpSocket, SocketOption, SocketOptionLevel, InternetAddress; import std.array : replace, array; import std.algorithm : map, joiner; import std.string : splitLines, strip; import std.conv : to; ushort port = 8080; // dfmt off static const greeting = q"EOF HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Hello, world! Hello, world! EOF" .splitLines .map!strip .joiner("\r\n") .to!string; // dfmt on void main() { import std.stdio : writefln; Socket listener = new TcpSocket; listener.bind(new InternetAddress(port)); listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1); listener.listen(10); writefln!"Listening on port %d."(port); while (true) { scope client = listener.accept; writefln!"Received connection from %s."(client.remoteAddress.toString); client.send(greeting); client.close; } } ``` But this *still violates HTTP* by not receiving the client's request, so it's still not a good answer for the task. A vibe hello world would make a lot more sense: https://github.com/vibe-d/vibe.d/blob/master/examples/http_server/source/app.d If this is the wrong place for this kind of info note, I'll gladly move to or redo the post in a more appropriate spot. You're in the right place.
Hello world/Web server task on RosettaCode fails
Using gdc-11 and Seamonkey. https://rosettacode.org/wiki/Hello_world/Web_server#D does not compile. ```d prompt$ gdc-11 helloServer.d helloServer.d:12:29: error: cannot cast expression currSock = listener.accept() of type std.socket.Socket to bool 12 | while(cast(bool)(currSock = listener.accept())) { | ^ ``` Then, tweaking the while loop to not cast but just run forever, `while (true) ...`, the code runs, but no data is shipped to browser. Ctrl-U shows empty page after the accept and sendTo calls. If this is the wrong place for this kind of info note, I'll gladly move to or redo the post in a more appropriate spot. Have good, make well
Re: Module import failing after $ dub add mypackage
On Fri, Jul 16, 2021 at 04:54:18PM +, Scotpip via Digitalmars-d-learn wrote: [...] > I simply need a fast binary serialisation lib to read and write a > large list of structs to local disk - it's not for inter-app > communication. The struct is simple and only contains primitive D data > types. If you are aware of any package that would be a better bet I'd > appreciate your advice. Or is there a more direct way to dump a list > from memory to disk and read it back again? This is the kind of > low-level stuff that's rather new to me... If your struct contains only POD types (no indirections), and you do not need to share it across machines, then you could just write the raw bytes to disk and read them back: struct Data { ... } // To write: File myFile = ...; // write number of items to disk somewhere foreach (Data item; myList) { myFile.rawWrite(()[0 .. 1]); } // To read: File myFile = ...; int numItems = /* read number of items from disk somewhere */; foreach (i; 0 .. numItems) { Data item; myFile.rawRead(()[0 .. 1]); appendToList(item); } If your data is in an array, it's even easier: Data[] myData; // write myData.length to disk somewhere myFile.rawWrite(myData); myData.length = /* read number of items from disk */; myFile.rawRead(myData); Note that the above only works if your data contains no indirections. (Beware that strings *do* contain indirection unless you're using fixed-length buffers.) If there are indirections you'll need to do something smarter. T -- The irony is that Bill Gates claims to be making a stable operating system and Linus Torvalds claims to be trying to take over the world. -- Anonymous
Re: Module import failing after $ dub add mypackage
On Friday, 16 July 2021 at 17:14:12 UTC, Mike Parker wrote: I haven't had occasion to make use of any serialization libraries myself, but you can start here: https://wiki.dlang.org/Serialization_Libraries Also: https://code.dlang.org/search?q=serialization
Re: Module import failing after $ dub add mypackage
On Friday, 16 July 2021 at 16:54:18 UTC, Scotpip wrote: Yup - I have it running now but the code does seem to be a bit neglected and I'm seeing a depreciation warning too. I chose it because it's much the most downloaded serialisation package and is used in a couple of other popular packages. But it seems to be moribund... The deprecation message is from the most recent dmd release: https://dlang.org/changelog/2.097.0.html#body-deprecation It's been a year since the last commit (which actually involved linking with winsock...), but I wouldn't write it off as near death just yet. I simply need a fast binary serialisation lib to read and write a large list of structs to local disk - it's not for inter-app communication. The struct is simple and only contains primitive D data types. If you are aware of any package that would be a better bet I'd appreciate your advice. Or is there a more direct way to dump a list from memory to disk and read it back again? This is the kind of low-level stuff that's rather new to me... I haven't had occasion to make use of any serialization libraries myself, but you can start here: https://wiki.dlang.org/Serialization_Libraries
Re: Module import failing after $ dub add mypackage
On Friday, 16 July 2021 at 16:44:31 UTC, Scotpip wrote: Again, if this helps anyone my current setup is to have a single main() in app.d. I changed the main() in my sandboxes to runSandbox(), and I import and run from app.d rather than directly. Or with a couple of keystrokes I can switch to running the full app. This seems to be a practical workflow that plays properly with the build system. If anyone has a better suggestion, I'd appreciate your tips. You might look into dub configurations. The first configuration that matches the current platform is the default, and other can be specified on the command line with `dub -cConfigName` (or `--config=ConfigName`). Here's are two configurations in SDLang format from one of my projects: // Default library config. configuration "dolce" { targetType "staticLibrary" targetPath "lib" targetName "dolce" excludedSourceFiles "source/dolce/dev/*" } // Development config for testing/experimenting. configuration "dolceDev" { targetType "executable" targetPath "bin" targetName "dolceDev" } Files for the executable are in `source/dolce/dev`, so I just exclude them from the library builds. In your case, you might have two mains and do something like this: targetType "executable" configuration "default" { excludedSourceFiles "source/sandbox/*" } configuration "sandbox" { exludedSourceFiles "source/app.d" } Or maybe the sandbox config could just add a version: configuration "sandbox" { versions "Sandbox" } Then you can conditionally compile as needed: void main() { version(Sandbox) { import sandbox : runSandbox; runSandbox(); } else { // Normal main stuff here } }
Re: Module import failing after $ dub add mypackage
On Friday, 16 July 2021 at 16:42:50 UTC, Mike Parker wrote: I did encounter some missing symbols, though (`ntohl` and `ntohs`) as msgpack-d isn't linking with Ws2-32.lib. I added `pragma(lib, "Ws2_32")` to the top of the file to resolve it. (And I filed an issue: https://github.com/msgpack/msgpack-d/issues/120). Once the linker issues were resolved, all was well. Yup - I have it running now but the code does seem to be a bit neglected and I'm seeing a depreciation warning too. I chose it because it's much the most downloaded serialisation package and is used in a couple of other popular packages. But it seems to be moribund... I simply need a fast binary serialisation lib to read and write a large list of structs to local disk - it's not for inter-app communication. The struct is simple and only contains primitive D data types. If you are aware of any package that would be a better bet I'd appreciate your advice. Or is there a more direct way to dump a list from memory to disk and read it back again? This is the kind of low-level stuff that's rather new to me...
Re: Module import failing after $ dub add mypackage
On Friday, 16 July 2021 at 15:42:32 UTC, rikki cattermole wrote: ``$ dub build`` inside of ``myproject`` should work. Thanks - that was helpful. For anyone else with this issue I've figured out what went wrong. I had more than one main() function in the project - I was using the others as sandboxes to play with code. I was building with ```dub .\source\myfile.d```. But you need to run dub without a filepath to build the whole project, including any 3rd party packages. No doubt this is blindingly obvious to people used to working with compilers, but it would be helpful to newbies if this was a bit more explicit in the dub docs. Again, if this helps anyone my current setup is to have a single main() in app.d. I changed the main() in my sandboxes to runSandbox(), and I import and run from app.d rather than directly. Or with a couple of keystrokes I can switch to running the full app. This seems to be a practical workflow that plays properly with the build system. If anyone has a better suggestion, I'd appreciate your tips.
Re: Module import failing after $ dub add mypackage
On Friday, 16 July 2021 at 15:31:49 UTC, Scotpip wrote: I'm completely stuck till I can get this fixed, so any help would be very much appreciated! I used the example from the readme at: https://code.dlang.org/packages/msgpack-d which I pasted into the generated `app.d`. And all the command lines were: ``` dub init myproject cd myproject dub add msgpack-d dub ``` Compiled fine. I did encounter some missing symbols, though (`ntohl` and `ntohs`) as msgpack-d isn't linking with Ws2-32.lib. I added `pragma(lib, "Ws2_32")` to the top of the file to resolve it. (And I filed an issue: https://github.com/msgpack/msgpack-d/issues/120). Once the linker issues were resolved, all was well.
Re: Module import failing after $ dub add mypackage
On 17/07/2021 3:31 AM, Scotpip wrote: In dub.sdl I see: ```dependency "msgpack-d" version="~>1.0.3"``` In dub.selections.json I see: ``` { "fileVersion": 1, "versions": { "msgpack-d": "1.0.3" } } ``` Okay, its been added to your dub project. So far so good. When I try to import the msgpack into my app.d main file, I get the error: ``` $ Error: module `msgpack` is in file 'msgpack.d' which cannot be read import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos import path[1] = C:\D\dmd2\windows\bin64\..\..\src\druntime\import ``` This should be in source/app.d I get similar errors whether I build with dub, dmd or rdmd. dmd and rdmd do not understand dub packages or anything else. They are the compiler. Only use dub and if you want to change compiler you tell dub this. The file msgpack.d which the build is searching for doesn't appear to be on my system. msgpack-d doesn't have a file named msgpack.d. It does have a package.d file inside its msgpack directory which functions as this. You should find it under %APPDATA%/dub ``$ dub build`` inside of ``myproject`` should work.
Module import failing after $ dub add mypackage
Another newbie question I'm afraid. Trying to import and use my first package from the registry. I installed D from the Windows dmd-2.097.0.exe I created the project with ```$ dub init myproject``` In the project root I've run: ``` $ dub add msgpack-d Adding dependency msgpack-d ~>1.0.3 ``` In dub.sdl I see: ```dependency "msgpack-d" version="~>1.0.3"``` In dub.selections.json I see: ``` { "fileVersion": 1, "versions": { "msgpack-d": "1.0.3" } } ``` When I try to import the msgpack into my app.d main file, I get the error: ``` $ Error: module `msgpack` is in file 'msgpack.d' which cannot be read import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos import path[1] = C:\D\dmd2\windows\bin64\..\..\src\druntime\import ``` I get similar errors whether I build with dub, dmd or rdmd. The file msgpack.d which the build is searching for doesn't appear to be on my system. I'm on Windows 10 Pro, if that's relevant. Importing my own local modules and modules from std is working fine. I've looked at the docs and a couple of books but there's nothing to suggest how I can fix this. The official dub docs are sparse, to say the least and don't say anything about how dub works or where it stores its resources... I've used many package managers without running into a roadblock like this. Am I doing something stupid? I'm completely stuck till I can get this fixed, so any help would be very much appreciated!
Re: No rdmd.exe in /bin64 on Windows - is this an issue?
On Friday, 16 July 2021 at 08:22:14 UTC, RazvanN wrote: On Monday, 12 July 2021 at 23:57:37 UTC, Scotpip wrote: Hi guys Just installed the DMD 2.097.0 .exe download for Windows on my 64 bit Win 10 workstation. [...] PR: https://github.com/dlang/installer/pull/484 Good work!
Re: opIndexUnary post in-/decrement how to ?
On Thursday, 15 July 2021 at 15:39:59 UTC, Tejas wrote: On Thursday, 15 July 2021 at 13:28:19 UTC, wjoe wrote: On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote: [...] The only way, for me, to explain the error message ```opIndex isn't an lvalue and can't be modified.``` for ```i[1]++``` is that the compiler rewrites to ```D (auto e = i.opIndex(1), i.opIndex(1).opUnary!"++"()/*1) note: not opIndexUnary*/, return e;) ``` If it were using ```opIndexUnary``` at 1) it would work. [...] Sucks :( I really can't spend more time on this, hope things work out for you somehow. Best of luck Regards Tejas No worries. Your time is very much appreciated.
Re: No rdmd.exe in /bin64 on Windows - is this an issue?
On Monday, 12 July 2021 at 23:57:37 UTC, Scotpip wrote: Hi guys Just installed the DMD 2.097.0 .exe download for Windows on my 64 bit Win 10 workstation. [...] PR: https://github.com/dlang/installer/pull/484