Re: writeln the struct from the alis this Example from the home page
On Thursday, 18 November 2021 at 16:08:22 UTC, Paul Backus wrote: On Thursday, 18 November 2021 at 13:51:42 UTC, Martin Tschierschke wrote: [...] You can define a `toString` method, like this: ```d string toString() { import std.conv; return p.to!string; } ``` You can find more information about `toString` in the documentation here: https://dlang.org/phobos/std_format_write.html By the way, the reason your original version does not work is that `p` is `private`, so `writeln` cannot access it. If you change `p` to be `public`, it will work without a `toString` method. Thank you, just removing ``private `` and it worked!
Nice example for operator overload resulting in readable linear algebra expressions
I just want to share a view lines of code. The availability of operator overloading can result in very short and precise code for linear algebra. To test/explore it a little I just modified the alias this example: ``` #!/usr/bin/env rdmd struct Point { double[2] p; // Forward all undefined symbols to p alias p this; auto opBinary(string op)(Point rhs) { static if (op == "+") { Point ret; ret[0] = p[0] + rhs.p[0]; ret[1] = p[1] + rhs.p[1]; return ret; } else static if (op == "-") { Point ret; ret[0] = p[0] - rhs.p[0]; ret[1] = p[1] - rhs.p[1]; return ret; } else static if (op == "*") return p[0] * rhs.p[0] + p[1] * rhs.p[1]; else static assert(0, "Operator " ~ op ~ " not implemented"); } } void main() { import std.stdio;// : writefln,write; // Point behaves like a `double[2]` ... Point p1, p2; p1 = [2, 1], p2 = [1, 1]; // ... but with extended functionality writef("p1*(p1 + p2) = %s*(%s + %s) =", p1, p1, p2); write(p1 * (p1 + p2)); // compare this to code without operator overload: } ``` Compare: ``p1 * (p1 + p2)`` to something with a structure like ``dot(p1,(add(p1,p2)).`` (With the Dlangs UFCS it might become: ``p1.dot(p1.add(p2))`` )
Re: Are templated functions always re-constructed?
On Wednesday, 17 November 2021 at 17:02:45 UTC, H. S. Teoh wrote: Regular (non-recursive) templates generally will not cause a noticeable change in compilation times. The trouble usually only starts when you start using recursive templates. Or when your templates are nested unreasonably deep (though this also usually only happens when there's recursive instantiation somewhere). T That's awesome! Thanks!
Why does this call the copy constructor 2 times and the assigment constructor once?
Hi! I'm trying to make my own string type for my library. Anyway, I'm not very experienced with structs/classes so I don't understand what's going one here. I will not post the full code because I don't think that anyone would like it so I will just post the important parts that play a role (tho in any case feel free to ask for the full code). Code: ``` import core.memory; import core.stdc.stdio; import core.stdc.string; import core.stdc.stdlib; struct str { private: char* _val; uint* _count; ulong _cap, _len; public: // Constructors this(const char* val) { printf("Debug: Called this(const char* val)\n"); this._val = cast(char*)val; this._count = cast(uint*)pureMalloc(4); *this._count = 0; this._cap = 0; this._len = strlen(val); } // Copy constructor this(ref return scope str rhs) { printf("Debug: Copy constructor called!!! (strig rhs)\n"); this._cap = rhs.length; this._len = this._cap; this._val = cast(char*)pureMalloc(this._len); strcpy(this._val, rhs.ptr); this._count = cast(uint*)pureMalloc(4); *this._count = 1; } // Assigment constructors str opAssign(str rhs) { printf("Debug: Assigment constructor called!!! (str rhs)\n"); if (*this._count == 1) { free(this._val); } else if (*this._count > 1) { (*this._count)--; } else *this._count = 1; this._val = cast(char*)pureMalloc(rhs.length); if (!this._val) { fprintf(stderr, "Could not allocate memory for the str object"); exit(1); } strcpy(this._val, rhs.ptr); this._cap = rhs.length; this._len = rhs.length; return this; } @property char* ptr() { return _val; } @property ulong length() { return _len; } } extern (C) int main() { str name = "Mike"; str other_name = "Anna"; other_name = name; return 0; } ``` So, when I assign the value of the variable "name" in the "other_name", first it will call the copy constructor, then it will call the assignment constructor and then it will call the copy constructor again. Why is this happening? I was expecting only the assignment constructor to get called.
Re: Why does this call the copy constructor 2 times and the assigment constructor once?
On Friday, 19 November 2021 at 14:05:40 UTC, rempas wrote: So, when I assign the value of the variable "name" in the "other_name", first it will call the copy constructor, then it will call the assignment constructor and then it will call the copy constructor again. Why is this happening? I was expecting only the assignment constructor to get called. When you pass a struct instance to a function by value, or return a struct instance from a function by value, a copy is made, and the copy constructor is called. Your `opAssign` takes `rhs` by value, and returns a `str` by value: ```d // Returned by value // | // v str opAssign(str rhs) { // ^ // | // Passed by value ``` So, every call to it will result in two calls to `str`'s copy constructor. If you want to avoid this, you can change `opAssign` to have the following signature: ```d // Returned by referece // | // v ref str opAssign()(auto ref str rhs) // ^ // | // Passed by reference (if possible) ``` Since `auto ref` is only allowed for template functions, I have added an empty template argument list (the `()`) to make `opAssign` into a function template. You can read more about [`ref` functions][1] and [`auto ref` parameters][2] in the D language specification. [1]: https://dlang.org/spec/function.html#ref-functions [2]: https://dlang.org/spec/template.html#auto-ref-parameters
Re: Why does this call the copy constructor 2 times and the assigment constructor once?
On Friday, 19 November 2021 at 14:22:07 UTC, Paul Backus wrote: When you pass a struct instance to a function by value, or return a struct instance from a function by value, a copy is made, and the copy constructor is called. Your `opAssign` takes `rhs` by value, and returns a `str` by [...] Since `auto ref` is only allowed for template functions, I have added an empty template argument list (the `()`) to make `opAssign` into a function template. [...] Interesting! It's weird that it works like that and explicitly calls a constructor but it indeed works as expected now. Thanks a lot and have an amazing day!
Null pointer in __vptr
Got a suspicious interface instance in the debugger and question myself: Is a null pointer entry in the __vptr[] valid or always a sign for corruption/wrong cast somewhere? thx
Re: Null pointer in __vptr
On Friday, 19 November 2021 at 15:37:59 UTC, frame wrote: Is a null pointer entry in the __vptr[] valid or always a sign for corruption/wrong cast somewhere? thx The `destroy` function (as well as other class destruction) will null out the whole vtable to help make use-after-free an obvious error. Possible that happened to you.
How to read a single character in D language?
Let's say I want to write a simple program that asks for an input of a single character. After pressing a single key on a keyboard, the character is printed out and the program should stop.
Efficient way to create/copy immutable struct instance with modified data
Hi all, I'm trying to figure out the most efficient way to create modified instances of immutable structs. Currently, I'm doing the following: ```d immutable struct Node { string label; Node parentNode; NetworkPort port; auto withLabel(string newLabel) { return Node(newLabel, this.parentNode, this.port); } auto withParentNode(Node newParentNode) { return Node(this.label, newParentNode, this.port); } auto withNetworkPort(NetworkPort newPort) { return Node(this.label, this.parentNode, newPort); } } ``` Coming from a scripting language the above makes the most sense. In D, this an efficient way to do it? Are there any best practices around this? Thanks in advance Merlin
Re: How to read a single character in D language?
On Friday, 19 November 2021 at 17:36:55 UTC, BoQsc wrote: Let's say I want to write a simple program that asks for an input of a single character. After pressing a single key on a keyboard, the character is printed out and the program should stop. This is platform specific. About 10 lines of code for a minimum implementation per OS, but if you don't wanna do it that way my library has a function for it with a prepackaged sample: http://arsd-official.dpldocs.info/arsd.terminal.html#single-key that's arsd-official:terminal on dub or you can grab the file from my github repo. I guess you could view my source to see the impl but I don't feel like pulling it out right now.
Re: Null pointer in __vptr
On Friday, 19 November 2021 at 15:46:41 UTC, Adam D Ruppe wrote: The `destroy` function (as well as other class destruction) will null out the whole vtable to help make use-after-free an obvious error. Possible that happened to you. So, a partial nulled table shouldn't exist, right? like this: __vptr[0]: address __vptr[1]: 000 __vptr[2]: address __vptr[3]: address __vptr[4]: address __vptr[5]: address ... Because 0 should point to the object instance and next offsets are pointers to the member functions, correct?
Re: Efficient way to create/copy immutable struct instance with modified data
On Friday, 19 November 2021 at 17:38:53 UTC, Merlin Diavova wrote: I'm trying to figure out the most efficient way to create modified instances of immutable structs. This might not be the best way but it is a kinda cool trick anyway: structs have a `tupleof` property you can slice. So you can do things like: Node(old_node.tupleof[0 .. argIndex], replacement, old_node.tupleof[argIndex + 1 .. $]); Where argIndex can be like 0 to replace the first item in the struct, or 1 to replace the second. It is possible to look this up using reflection and kinda automate this if you wanted. ``` mixin template Replaceable() { // returns a replaced thing when you use it as `with_someField` typeof(this) opDispatch(string s, T)(T replacement) if(s.length > 5 && s[0 .. 5] == "with_") { static foreach(idx, member; typeof(this).tupleof) { static if(__traits(identifier, member) == s[5 .. $]) enum argIndex = idx; } // if the arg is not found you will get an ugly error message here about undefined // argIndex meh. return typeof(this)(this.tupleof[0 .. argIndex], replacement, this.tupleof[argIndex + 1 .. $]); } } immutable struct Node { string label; Node* parentNode; int port; mixin Replaceable; // add the ugly generic code from the top } void main() { Node i = Node("one", null, 4); Node i2 = i.with_port(6); // and now use it like this assert(i2.label == "one"); assert(i2.port == 6); } ``` I did `with_` instead of camelCase to avoid having to mess with case comparisons on the name.
Re: Null pointer in __vptr
On Friday, 19 November 2021 at 18:04:17 UTC, frame wrote: So, a partial nulled table shouldn't exist, right? like this: Indeed. I've gotten that before as a result of a compiler bug... I had an abstract method that wasn't implemented but the compile time error got swallowed by a bug and thus the null method made its way to the binary. I think that bug was fixed but still you might want to check your code for the `abstract` keyword and ensure they are legit implemented in your cases.
Re: Null pointer in __vptr
On Friday, 19 November 2021 at 18:14:03 UTC, Adam D Ruppe wrote: I've gotten that before as a result of a compiler bug... I had an abstract method that wasn't implemented but the compile time error got swallowed by a bug and thus the null method made its way to the binary. You got it! It was an abstract class involved and the method signature was just wrong, but no compile error. Thanks!
Re: How to read a single character in D language?
On Friday, 19 November 2021 at 18:01:57 UTC, Adam D Ruppe wrote: On Friday, 19 November 2021 at 17:36:55 UTC, BoQsc wrote: Let's say I want to write a simple program that asks for an input of a single character. After pressing a single key on a keyboard, the character is printed out and the program should stop. This is platform specific. About 10 lines of code for a minimum implementation per OS, but if you don't wanna do it that way my library has a function for it with a prepackaged sample: http://arsd-official.dpldocs.info/arsd.terminal.html#single-key that's arsd-official:terminal on dub or you can grab the file from my github repo. I guess you could view my source to see the impl but I don't feel like pulling it out right now. Thanks Adam. I've tested and it does work on Windows 10. mkdir "read_character_project" cd "read_character_project" dub init dub add arsd-official:terminal notepad ./source/app.d import arsd.terminal; void main() { auto terminal = Terminal(ConsoleOutputType.linear); auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw); terminal.writeln("Press any key to continue..."); auto ch = input.getch(); terminal.writeln("You pressed ", ch); } dub run Performing "debug" build using C:\Program Files\LDC 1.28\bin\ldc2.exe for x86_64. arsd-official:terminal 10.3.10: target for configuration "normal" is up to date. arsd ~master: target for configuration "application" is up to date. To force a rebuild of up-to-date targets, run again with --force. Running arsd.exe Press any key to continue... You pressed u ___ Of interest, I also tried to look up getch() inside http://arsd-official.dpldocs.info/source/arsd.terminal.d.html#L2867 But the source file overwhelmed me by its size. For now I'm still interested in a more simple standalone implementation that would be more learning friendly, or at least with little explanation of basic things behind the code and how it is interfacing with the operating system, the native library.
Re: Null pointer in __vptr
On 11/19/21 10:04 AM, frame wrote: > On Friday, 19 November 2021 at 15:46:41 UTC, Adam D Ruppe wrote: > >> The `destroy` function (as well as other class destruction) will null >> out the whole vtable to help make use-after-free an obvious error. >> Possible that happened to you. > > So, a partial nulled table shouldn't exist, right? like this: > > __vptr[0]: address > __vptr[1]: 000 > __vptr[2]: address > __vptr[3]: address > __vptr[4]: address > __vptr[5]: address > > > Because 0 should point to the object instance I am not sure that's correct. The way I picture it, the code reaches the __vptr by following a pointer; so it's already known. Additionally, I am under the impression that there is only one __vptr for a given type, which all class objects of that type point to. > and next offsets are pointers to the member functions, correct? My understanding is that all entries are that. Ali
Re: How to read a single character in D language?
On Friday, 19 November 2021 at 20:51:09 UTC, BoQsc wrote: But the source file overwhelmed me by its size. Yeah, the getch function in there builds on the rest of the events the library offers, so it won't be that useful outside. The OS functions for getch alone though are actually pretty simple: 1) change the terminal to "raw" mode. the default is to buffer lines, which means your application doesn't get anything until a line is complete. You need to turn that off. The RealTimeConsoleInput constructor does this in the lib: http://arsd-official.dpldocs.info/v10.3.8/source/arsd.terminal.d.html#L2487 On Windows, you basically just call `SetConsoleMode`, but since the console is a shared resource, you also need to save the old mode to set it back later (that's what I do in the destructor of the struct). On Linux, you call `tcsetattr`. The function for mine is here: http://arsd-official.dpldocs.info/v10.3.8/source/arsd.terminal.d.html#L2620 Again, the terminal is a shared resource (this is actually even more true on linux systems!) so it is important to save the old one and set it back when you're done. There's a lot of ways this can happen so you should handle them all - that's why there's a bunch of signal handler blocks there. Other things the library initialize is if you want echo, mouse input, paste events, resize notifications, etc. But if you only care about getch you can ignore most that stuff. 2) Read the terminal's event stream. On Windows, you call `ReadConsoleInput` and process the struct it sends you for a keyevent. See: http://arsd-official.dpldocs.info/v10.3.8/source/arsd.terminal.d.html#L3122 On Linux, you call the system `read` function on the stdin stream (file number 0). Basic keys will come as a single byte read on there. Others get extremely complicated. http://arsd-official.dpldocs.info/v10.3.8/source/arsd.terminal.d.html#L3369 And it goes on for about 400 lines! And it depends on some of that other initialization we skipped over before and uses a database of terminal quirks found elsewhere in the file. Windows' API is far, far easier to use. But the Linux one isn't bad if you only want basic alphanumeric and enter keys. You can read those as a single ascii byte off the read function, so for that you can do it in just a few lines. 3) Again, remember to set it back how you found it before you exit by callling the SetConsoleMode/tcsetattr again before you exit.
Re: Any additions for write-to-file short program
On Thursday, 18 November 2021 at 23:09:28 UTC, H. S. Teoh wrote: On Thu, Nov 18, 2021 at 10:20:48PM +, pascal111 via Digitalmars-d-learn wrote: In next program that rewrites original written texts into new files, I see that it may need some additions or we can accept it like this because it's just a simple program that achieve its task and doesn't need any philosophical additions. I assume there's a reason you're reading the input file by line instead of just copying it using larger fixed-size blocks? Perhaps you have in mind some kind of line-based filtering or processing eventually? Because for copying a file, using a large, fixed-size block will work much faster. Not to mention the code will be simpler. For example: auto inputFile = File(inputFilename, "r"); auto outputFile = File(outputFilename, "w"); enum bufferSize = 8194; inputFile.byChunk(bufferSize) // read input in blocks of 8194 bytes .copy(outputFile.lockingBinaryWriter); // copy each block into output file T When I compiled the code after adding yours, I found this error message: "untitled20.d:24:8: error: no property 'copy' for type 'ByChunk' 24 |.copy(outputFile.lockingBinaryWriter); // copy each block into output file |^ "
Re: How to read a single character in D language?
On Friday, 19 November 2021 at 17:36:55 UTC, BoQsc wrote: Let's say I want to write a simple program that asks for an input of a single character. After pressing a single key on a keyboard, the character is printed out and the program should stop. If you want to test on Windows you can do this: ```d // conio.h extern (C) int _getch(); ``` Like for demonstration purposes: ```d writeln("Press a button..."); int a = _getch(); writeln("You pressed ", a); ``` That should be unbuffered.
Re: Any additions for write-to-file short program
On Friday, 19 November 2021 at 22:21:52 UTC, pascal111 wrote: On Thursday, 18 November 2021 at 23:09:28 UTC, H. S. Teoh wrote: [...] When I compiled the code after adding yours, I found this error message: "untitled20.d:24:8: error: no property 'copy' for type 'ByChunk' 24 |.copy(outputFile.lockingBinaryWriter); // copy each block into output file |^ " Did you import std.algorithm?
Re: How to read a single character in D language?
On Fri, Nov 19, 2021 at 10:21:42PM +, Adam Ruppe via Digitalmars-d-learn wrote: [...] > The OS functions for getch alone though are actually pretty simple: > > 1) change the terminal to "raw" mode. the default is to buffer lines, > which means your application doesn't get anything until a line is > complete. You need to turn that off. [...] > 2) Read the terminal's event stream. [...] > 3) Again, remember to set it back how you found it before you exit by > callling the SetConsoleMode/tcsetattr again before you exit. And *this* is why you want to use a library for this. Doing this by hand is certainly possible, but very tedious, error-prone, and requires a lot of knowledge about OS system calls. Why bother when you could just drop arsd.terminal into your workspace and call it a day? :-) (Of course, learning how things work under the hood for the sake of educating yourself is definitely worthwhile. Just don't do that when you need to get stuff done.) T -- Let's not fight disease by killing the patient. -- Sean 'Shaleh' Perry
Re: Any additions for write-to-file short program
On Fri, Nov 19, 2021 at 10:21:52PM +, pascal111 via Digitalmars-d-learn wrote: [...] > When I compiled the code after adding yours, I found this error message: > > "untitled20.d:24:8: error: no property 'copy' for type 'ByChunk' >24 |.copy(outputFile.lockingBinaryWriter); // copy each block > into output file > |^ > " import std.algorithm; T -- It is impossible to make anything foolproof because fools are so ingenious. -- Sammy
Re: Any additions for write-to-file short program
On Friday, 19 November 2021 at 23:05:03 UTC, H. S. Teoh wrote: On Fri, Nov 19, 2021 at 10:21:52PM +, pascal111 via Digitalmars-d-learn wrote: [...] When I compiled the code after adding yours, I found this error message: "untitled20.d:24:8: error: no property 'copy' for type 'ByChunk' 24 |.copy(outputFile.lockingBinaryWriter); // copy each block into output file |^ " import std.algorithm; T Thanks! it works now. code: // D programming language import std.stdio; import std.string; import std.algorithm; int main() { string s; char[] f; try{ write("Enter file name and path: "); readln(f); f=strip(f); File inputFile = File(f, "r"); File outputFile = File("output_x", "w"); enum bufferSize = 8194; inputFile.byChunk(bufferSize) // read input in blocks of 8194 bytes .copy(outputFile.lockingBinaryWriter); // copy each block into output file inputFile.close(); outputFile.close(); } catch(Exception err){ stderr.writefln!"Warning! %s"(err.msg); return 1; } return 0; }
Re: Dub says that there is an invalid semVer format, but I don't see how.
On Friday, 12 November 2021 at 21:22:32 UTC, Ruby The Roobster wrote: On Thursday, 11 November 2021 at 01:57:10 UTC, rikki cattermole wrote: On 11/11/2021 2:13 PM, Ruby The Roobster wrote: Branch ~master: Invalid SemVer format: testing.0.0 Branch ~testing: Invalid SemVer format: testing.0.0 Version 0.1.2: Invalid SemVer format: testing.0.0 testing is a branch. You are using ~>testing for it. To use a branch in the SEMVER is ~branch. https://dub.pm/package-format-json.html#version-specs This was not causing me issues before. It worked until I added the v0.1.2 tag. This seems to be a dead thread, but I always get these errors: Branch ~master: Invalid SemVer format: testing.0.0 Branch ~stable: Invalid SemVer format: stable.0.0
Re: Dub says that there is an invalid semVer format, but I don't see how.
Don't use ~> for branches. alpha@DESKTOP-RB97SA4 /tmp/dutils $ dub build Invalid SemVer format: stable.0.0 alpha@DESKTOP-RB97SA4 /tmp/dutils $ nano dub.json alpha@DESKTOP-RB97SA4 /tmp/dutils $ dub build Performing "debug" build using C:\Tools\D\dmd_2.097.2\windows\bin\dmd.exe for x86_64. dutils 0.1.2-beta.2+commit.9.g359c59d: building configuration "library"... Error: module `package` is in file 'package.d' which cannot be read import path[0] = source import path[1] = C:\Tools\D\dmd_2.097.2\windows\bin\..\..\src\phobos import path[2] = C:\Tools\D\dmd_2.097.2\windows\bin\..\..\src\druntime\import C:\Tools\D\dmd_2.097.2\windows\bin\dmd.exe failed with exit code 1. alpha@DESKTOP-RB97SA4 /tmp/dutils $ cat dub.json { "authors": [ "Ruby The Roobster" ], "copyright": "Copyright © 2021, Ruby The Roobster", "description": "A collection of modules in the D Programming Language that people may find useful.", "license": "GLP-3.0", "name": "dutils", "importPaths": ["./source"], "sourceFiles": ["package.d"], "targetType": "library", "subPackages": [ { "name": "sprite", "description": ".spr file format for images because I'm to lazy to use a preexisting one for sprites.", "targetType": "library", "importPaths": ["./source"], "sourceFiles": ["sprite.d"], "dependencies": { "dutils:skeleton": "~stable" } }, { "name": "binom", "description": "Module for doing some bionomial work in the D Programming Language(why did I make this).", "targetType": "library", "importPaths": ["./source"], "sourceFiles": ["binom.d"] }, { "name": "skeleton", "description": "Module for implementing skeletons, e.g. a cube with criss-crossing beams to better detect collision.", "targetType": "library", "importPaths": ["./source"], "sourceFiles": ["skeleton.d"] }, { "name": "physics", "description": "A very simple and basic physics library.", "targetType": "library", "importPaths": ["./source"], "sourceFiles": ["physics.d"], "dependencies": { "dutils:skeleton": "~stable" } } ] }