Re: Allocator Part of Type
On 3/15/18 6:30 PM, jmh530 wrote: On Thursday, 15 March 2018 at 21:43:41 UTC, Steven Schveighoffer wrote: [snip] I don't know if I've heard Andrei talk about that, but I definitely have made it part of the type for types that need to allocate. The only other possibility is to accept and use an Allocator object (i.e. the interface). I suppose the main reason you may want to not make it part of the type is if you want to compare/assign two types built with different allocators. But then I don't know why you would want to do that. But I just thought of this too -- maybe he said you should make it a part of the struct itself? That is, you shouldn't make the allocator a member, but the allocator itself can be part of the type? Not sure. I first remember him saying it with respect to C++'s allocators [1]. The C++ containers in std include the allocator as part of the type. I don't really recall what the reasoning was. I also recall him saying it with respect to automem [2]. Automem includes the allocator among the template variables and then puts the allocator in an enum (Atila says it only takes up space in certain situations). I think the containers library does something similar, but with an alias if state size is 0 and as a member otherwise. [1] https://github.com/CppCon/CppCon2015/blob/master/Presentations/allocator%20Is%20to%20Allocation%20what%20vector%20Is%20to%20Vexation/allocator%20Is%20to%20Allocation%20what%20vector%20Is%20to%20Vexation%20-%20Andrei%20Alexandrescu%20-%20CppCon%202015.pdf Looks like what he means is that the allocator in C++ includes the type as part of it's makeup. That's not the same thing. But it's hard to tell from just a bunch of slides. [2] https://forum.dlang.org/post/ocden9$11s6$1...@digitalmars.com This does seem to suggest he thinks the idea is not good. I can't think of an alternative that doesn't store the allocator as a member (if you intend to use different allocators with different variables). However, there is some further conversation on that from Martin Nowak that may shed some light on the "anti-pattern" and what it really means. Personally, I think you HAVE to have some sort of reference to an allocator if you want custom allocation support in a container type. The only other alternative is making the user of the type remember which allocator the type needs to dealloacte and pass the allocator along when doing memory management tasks. Seems horrible. -Steve
Re: Efficient way to pass struct as parameter
On Thursday, 15 March 2018 at 23:15:47 UTC, Cecil Ward wrote: On Thursday, 15 March 2018 at 23:14:14 UTC, Cecil Ward wrote: On Tuesday, 2 January 2018 at 18:21:13 UTC, Tim Hsu wrote: [...] U or even 'I' will be delighted to take a look. Also link time optimisation and whole program optimisation might be your friends if you are having problems because module boundaries mean that the compiler cannot expand the source code of the constructor implementation to inline it and fully optimise it away to nothing. You certainly should have no problems if the code that uses the struct can see the struct definition's actual source text directly.
Re: Efficient way to pass struct as parameter
On Thursday, 15 March 2018 at 23:14:14 UTC, Cecil Ward wrote: On Tuesday, 2 January 2018 at 18:21:13 UTC, Tim Hsu wrote: [...] U or even 'I' will be delighted to take a look.
Re: Efficient way to pass struct as parameter
On Tuesday, 2 January 2018 at 18:21:13 UTC, Tim Hsu wrote: I am creating Vector3 structure. I use struct to avoid GC. However, struct will be copied when passed as parameter to function struct Ray { Vector3f origin; Vector3f dir; @nogc @system this(Vector3f *origin, Vector3f *dir) { this.origin = *origin; this.dir = *dir; } } How can I pass struct more efficiently? This isn't a question for you. it's a question for the compiler, let the compiler do its thing. Stick in a -O3 if you are using GCC or LDC and build in release more not debug mode. Make sure that the compiler can see the source code of the implementation of the constructor wherever it is used and it should just be inclined away to nonexistence. Your constructor should not even exist, if it is then you are looking at a false picture or a mistake where optimisation has been turned off for the sake of easy source-level debugging. Post up the assembler language output for a routine where this code is used in some critical situation, and then we can help make sure that the code _generation_ is optimal. I reiterate, unless something is badly wrong or you are seeing a red herring, no 'call' to the constructor code should even exist in the cases where it is actually 'called'. You may well see a useless copy of the constructor code because the compilers seem to generate such even though it is never called ans so is a waste of space. The compiler will analyse the constructor's instructions and just copy-and-paste them as assignment statements with that then getting thoroughly optimised down into something which may just be a memory write or a register-register copy that costs zero. If you post up snippets of generated asm then U will be delighted to take a look.
Re: signbit question
Miguel L wrote: as the calculations on f guarantee it cannot be 0 at all. than `f` will become zero very soon. something that "cannot happen" is the most probable thing to happen. otherwise, LGTM.
Re: Readonly field for class type
On 03/15/2018 03:16 AM, Andrey wrote: Hello, is there way to declare read only field for class type with ability to call inner non constant methods? i.e.: class A { int value = 12; void updateValue() { value = 13; } } class B { const A a; this() { a = new A(); a.updateValue(); // error: mutable method is not callable using const object } } Another option is assigning a pre-made A to the member: class A { int value = 12; void updateValue() { value = 13; } } // Magic recipe is moved here: A makeA() { auto a = new A(); a.updateValue(); return a; } class B { const A a; this() { a = makeA(); } } void main() { auto b = new B(); } Which can be compressed into a lambda in the constructor: this() { a = { // This 'a' is a local variable inside the lambda: auto a = new A(); a.updateValue(); return a; }(); } Ali
Re: Allocator Part of Type
On Thursday, 15 March 2018 at 21:43:41 UTC, Steven Schveighoffer wrote: [snip] I don't know if I've heard Andrei talk about that, but I definitely have made it part of the type for types that need to allocate. The only other possibility is to accept and use an Allocator object (i.e. the interface). I suppose the main reason you may want to not make it part of the type is if you want to compare/assign two types built with different allocators. But then I don't know why you would want to do that. But I just thought of this too -- maybe he said you should make it a part of the struct itself? That is, you shouldn't make the allocator a member, but the allocator itself can be part of the type? Not sure. -Steve I first remember him saying it with respect to C++'s allocators [1]. The C++ containers in std include the allocator as part of the type. I don't really recall what the reasoning was. I also recall him saying it with respect to automem [2]. Automem includes the allocator among the template variables and then puts the allocator in an enum (Atila says it only takes up space in certain situations). I think the containers library does something similar, but with an alias if state size is 0 and as a member otherwise. [1] https://github.com/CppCon/CppCon2015/blob/master/Presentations/allocator%20Is%20to%20Allocation%20what%20vector%20Is%20to%20Vexation/allocator%20Is%20to%20Allocation%20what%20vector%20Is%20to%20Vexation%20-%20Andrei%20Alexandrescu%20-%20CppCon%202015.pdf [2] https://forum.dlang.org/post/ocden9$11s6$1...@digitalmars.com
Re: Function argument that is a pointer to memory which the function is not allowed to modify, as in C const
On Wednesday, 14 March 2018 at 22:23:47 UTC, Cecil Ward wrote: say in C I have a function with a pointer argument foo( const sometype_t * p ) [...] That's the secret - I didn't know about the const (T) * thing - I would never have discovered that ! Many thanks, the missing piece to the puzzle. Many generous replies, thanks to all for their extremely helpful contributions. There is a wealth of precious explanation in them, and apologies for not thanking the contributors individually.
Re: Allocator Part of Type
On 3/15/18 3:36 PM, jmh530 wrote: I recall some talk Andrei did where he said it was a bad idea to make the allocator part of the type. However, the container library in dlang-community(says it is backed with std.experimental.allocator) contains allocator as part of the type. Automem does too. Honestly, I would think you would really be hobbled if you didn't. For instance, if you want to expand a DynamicArray using the built-in ~= operator, then you really need to know what the allocator is. Without ~= you'd have to rely on functions (maybe member functions, maybe not). So I suppose I'm wondering why is it a bad thing to include the allocator as part of the type and why is it that it seems like in practice that's how it is done anyway. I don't know if I've heard Andrei talk about that, but I definitely have made it part of the type for types that need to allocate. The only other possibility is to accept and use an Allocator object (i.e. the interface). I suppose the main reason you may want to not make it part of the type is if you want to compare/assign two types built with different allocators. But then I don't know why you would want to do that. But I just thought of this too -- maybe he said you should make it a part of the struct itself? That is, you shouldn't make the allocator a member, but the allocator itself can be part of the type? Not sure. -Steve
Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]
On Thursday, 15 March 2018 at 15:41:54 UTC, Robert-D wrote: Why something like this doesn't compile (with or without the cast on bb.dup)? struct S { string[string] aa; S dup() inout pure { return S(cast(string[string]) aa.dup); } } struct SS { S[] bb; SS dup() inout pure { return SS(cast(S[]) bb.dup); } } Or: const(S)[] ss = [S(["": ""])]; S[] d = ss.dup; For this to work, the standard .dup function would need to call .dup on each element of the array. Since this may or may not be what the programmer wants, the standard library doesn't do it for you. Generally, this is called deep-duping, or deep cloning. We can implement our own deepdup function: struct S { string[string] aa; S dup() const { return S(aa.deepDup); } } struct SS { S[] bb; SS dup() const { return SS(cast(S[])bb.deepDup); } } import std.traits : Unqual, isArray, isAssociativeArray; auto deepDup(T)(T obj) if (!isArray!T && !isAssociativeArray!T) { static if (is(typeof(obj.deepDup))) { return obj.deepDup; } else static if (is(typeof(obj.dup))) { return obj.dup; } else static if (is(typeof({ Unqual!T tmp = obj; }))) { return obj; } else { static assert(false, "Can't deepDup a "~T.stringof); } } auto deepDup(T)(T[] arr) { Unqual!T[] result; result.reserve(arr.length); foreach (e; arr) { result ~= e.deepDup; } return result; } auto deepDup(T : V[K], K, V)(T aa) { alias UV = Unqual!V; alias UK = Unqual!K; UV[UK] result; foreach (k, v; aa) { UK kdup = k.deepDup; UV vdup = v.deepDup; result[kdup] = vdup; } return result; } -- Simen
Allocator Part of Type
I recall some talk Andrei did where he said it was a bad idea to make the allocator part of the type. However, the container library in dlang-community(says it is backed with std.experimental.allocator) contains allocator as part of the type. Automem does too. Honestly, I would think you would really be hobbled if you didn't. For instance, if you want to expand a DynamicArray using the built-in ~= operator, then you really need to know what the allocator is. Without ~= you'd have to rely on functions (maybe member functions, maybe not). So I suppose I'm wondering why is it a bad thing to include the allocator as part of the type and why is it that it seems like in practice that's how it is done anyway.
Re: Networking library
On Thursday, 15 March 2018 at 00:06:49 UTC, Cecil Ward wrote: Can anyone point me in the direction of a library that provides very very lightweight (minimum overhead) asynchronous i/o routines for - shopping list 1. sending and receiving IPv4 / IPv6 packets, 2. sending receiving ICMP and 3, handling incoming outgoing TCP connections and 4. handling SCTP connections. Given the low-level nature of some of your requests, I’d suggest seriously look at DPDK. I don’t know if there is a ready-made D wrapper, but it should be stright-forward to bind to it. That covers all of your direct packet manipulation at extreme speeds.
Re: What is the "right" way to create a generic type getter (and setter) ?
On Thursday, 15 March 2018 at 15:48:52 UTC, James Blachly wrote: On Wednesday, 14 March 2018 at 22:58:25 UTC, ag0aep6g wrote: You can probably get around the (manually maintained?) `FIELDS` array with `.tupleof` or something similar: static foreach (i, f; S.tupleof) { case __traits(identifier, f): } Any pointers / design patterns on this particular type of problem class would be greatly appreciated. (Sidenote, I realize I could probably use the witchcraft library, but I am also using this as exercise to learn D beyond the basics). You simply cannot have a method that returns different types based on a run-time value. You could possibly return a std.variant.Variant. But if the goal is just to print the value to the screen, all you need is a string. So the signature would be `string get(string field)`. And for the implementation you could use `.tupleof` to iterate over all fields, and then return `f.to!string`. `set` can be done similarly. Take two `string`s: the field name, and the value. `static foreach` over all fields. On a match, convert the given value string to the type of the field that matched. Thanks - to!string certainly seems to be a good option in this case (CLI) and I was definitely overthinking this part, perhaps because I was trying to write everything as generically / extensibly as possible (for example, to use the same framework but with a GUI or web front end, for example). I would still think an AA mapping (string) field name to a type would be useful and will see if I can construct it as a mixin using typeof(Struct.member) somehow. If you're comming from python you may appreciate that you don't need getter/setters in D either. Just as you have @property in python which allows you to change at any time from a simple attribute to a method (be it reading or writing) you have a property syntax in D: struct S { int a; int _b; auto b() { return _b; } void b(int val) { _b = val; } } void main(string[] args) { S s; s.a = 24; writeln(s.a); s.b = 42; writeln(s.b); }
Re: signbit question
On 3/15/2018 12:39 PM, Miguel L wrote: On Thursday, 15 March 2018 at 17:31:38 UTC, rumbu wrote: On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote: On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote: On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: [...] integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment. Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; if((a<0)==signbit(f)) {} else {...} If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...} There are various in my code there are more than two variables, and i'd like to check when their signs differ.I am trying to avoid this, maybe there is no point in it: if(!((a>=0 && f>=0) || (a<0 && f<0))){ //signs are different } Thanks, anyway You could simplify that to this: if ((a < 0) != (f < 0)) { } Or if you have more than two variables you could do something like this: bool AllSameSign(double[] args ...) { //Only need to check if there are more than one of them if (args.length > 1) { //Compare arg[0] to all the other args. for (int i = 1; i < args.length; i++) { if ((args[0] < 0) != (args[i] < 0)) { return false; } } } return true; } Which you could call like this, with as many variables as you like: AllSameSign(a,f);
Re: signbit question
On Thursday, 15 March 2018 at 17:31:38 UTC, rumbu wrote: On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote: On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote: On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: [...] integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment. Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; if((a<0)==signbit(f)) {} else {...} If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...} There are various in my code there are more than two variables, and i'd like to check when their signs differ.I am trying to avoid this, maybe there is no point in it: if(!((a>=0 && f>=0) || (a<0 && f<0))){ //signs are different } Thanks, anyway
Re: signbit question
On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote: On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote: On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advance integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment. Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; if((a<0)==signbit(f)) {} else {...} If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}
Re: signbit question
On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote: On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advance integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment. They generate the same assembly: https://godbolt.org/g/4ohTJx
Re: signbit question
On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote: On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advance integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment. Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; if((a<0)==signbit(f)) {} else {...}
Re: signbit question
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advance integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Re: signbit question
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: Why does std.math.signbit only work for floating point types? Integers are stored in an entirely different way, twos-complement instead of having a sign bit. You probably shouldn't be using the sign bit function at all, it is for digging deeper into the float binary format. Instead, I'd just say if(f > 0 && i > 0) if(f < 0 && i < 0) if(f == 0 && i == 0) etc. in math stuff to see if they have the same sign. floats have weird things like +0 and -0 which doesn't exist at all in ints...
Re: signbit question
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote: Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? I guess because for integers you don't need to distinguish between +0.0 and -0.0, so no one bother until now to add it to std.math. That being said there are a few options for integer types: --- import std.math, std.stdio; void main() { foreach (a; -1 .. 2) { "a:".writeln(a); signbit(cast(double) a).writefln!"signbit: %2d"; (cast(uint) a >> a.sizeof * 8 - 1).writefln!"bitshift: %2d"; (a < 0).writefln!"< 0:\t %2d"; writeln; } } --- https://run.dlang.io/is/pts6dj The first option is a bit slower for integers and the second and third option generate equivalent assembly [1], so I would recommend `a < 0` for integer types. [1] https://godbolt.org/g/4ohTJx what is the best way to compare the sign of a float with the sign of an integer? Ideas: 1) Make a PR to signbit to add integer support 2) Create your own signsbit a la: --- auto signbit(A)(A a) { static import std.math; import std.traits : isIntegral; static if (isIntegral!A) return a < 0; else return std.math.signbit(a); } ---
Re: What is the "right" way to create a generic type getter (and setter) ?
On Wednesday, 14 March 2018 at 22:58:25 UTC, ag0aep6g wrote: You can probably get around the (manually maintained?) `FIELDS` array with `.tupleof` or something similar: static foreach (i, f; S.tupleof) { case __traits(identifier, f): } Any pointers / design patterns on this particular type of problem class would be greatly appreciated. (Sidenote, I realize I could probably use the witchcraft library, but I am also using this as exercise to learn D beyond the basics). You simply cannot have a method that returns different types based on a run-time value. You could possibly return a std.variant.Variant. But if the goal is just to print the value to the screen, all you need is a string. So the signature would be `string get(string field)`. And for the implementation you could use `.tupleof` to iterate over all fields, and then return `f.to!string`. `set` can be done similarly. Take two `string`s: the field name, and the value. `static foreach` over all fields. On a match, convert the given value string to the type of the field that matched. Thanks - to!string certainly seems to be a good option in this case (CLI) and I was definitely overthinking this part, perhaps because I was trying to write everything as generically / extensibly as possible (for example, to use the same framework but with a GUI or web front end, for example). I would still think an AA mapping (string) field name to a type would be useful and will see if I can construct it as a mixin using typeof(Struct.member) somehow.
Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]
On Thursday, 15 March 2018 at 13:18:38 UTC, Simen Kjærås wrote: On Thursday, 15 March 2018 at 12:00:08 UTC, Robert-D wrote: I want the function to create a mutable copy from a const or a imutable Like this: void main() { const S s = S(["": ""]); S b = s.dup(); } How can i do that? In that case, the problem is that you also have to .dup the aa: S dup() const pure { return S(aa.dup); } However, it seems aa.dup returns the wrong type - one would expect V[K] for inout(V[K]), but it returns inout(V)[K], or inout(string)[string], in your case. That's apparently a known bug: https://issues.dlang.org/show_bug.cgi?id=14148. The solution for now, then, is this: S dup() const pure { return S(cast(string[string])aa.dup); } -- Simen Why something like this doesn't compile (with or without the cast on bb.dup)? struct S { string[string] aa; S dup() inout pure { return S(cast(string[string]) aa.dup); } } struct SS { S[] bb; SS dup() inout pure { return SS(cast(S[]) bb.dup); } } Error: static assert: "Cannot implicitly convert type inout(S) to S in dup." Or: const(S)[] ss = [S(["": ""])]; S[] d = ss.dup; Error: template object.dup cannot deduce function from argument types !()(const(S)[]), candidates are: /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(2086): object.dup(T : V[K], K, V)(T aa) /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(2122): object.dup(T : V[K], K, V)(T* aa) /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4191): object.dup(T)(T[] a) if (!is(const(T) : T)) /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4207): object.dup(T)(const(T)[] a) if (is(const(T) : T))
signbit question
Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advance
Re: Readonly field for class type
On Thursday, 15 March 2018 at 13:44:20 UTC, Seb wrote: On Thursday, 15 March 2018 at 10:57:52 UTC, Mike Parker wrote: On Thursday, 15 March 2018 at 10:55:16 UTC, Mike Parker wrote: class A { private int _value = 12; int value() @property { return _value; } void updateValue() { value = 13; } } ... auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value); Sorry. I overlooked that B.a is const. It still works, the `value` just needs to be `const` (or `inout`) and _value needs to be used in updateValue: class A { private int _value = 12; int value() const { return _value; } void updateValue() { _value = 13; } } auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value); In action: https://run.dlang.io/is/Tk1rY1 @Robert: If you need this a lot, the accessors package might be interesting to you: https://code.dlang.org/packages/accessors ... and I didn't add `const` to A -> https://run.dlang.io/is/QObN1w but better have a look at Simen's response (https://forum.dlang.org/post/ottyywbmrwgfabgpf...@forum.dlang.org), it's what you are looking for. I read too quickly and only have of it :/
Re: Readonly field for class type
On Thursday, 15 March 2018 at 13:44:20 UTC, Seb wrote: On Thursday, 15 March 2018 at 10:57:52 UTC, Mike Parker wrote: On Thursday, 15 March 2018 at 10:55:16 UTC, Mike Parker wrote: [...] Sorry. I overlooked that B.a is const. It still works, the `value` just needs to be `const` (or `inout`) and _value needs to be used in updateValue: class A { private int _value = 12; int value() const { return _value; } void updateValue() { _value = 13; } } auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value); In action: https://run.dlang.io/is/Tk1rY1 @Robert: If you need this a lot, the accessors package might be interesting to you: https://code.dlang.org/packages/accessors (I meant @Andrey - sorry)
Re: Readonly field for class type
On Thursday, 15 March 2018 at 10:57:52 UTC, Mike Parker wrote: On Thursday, 15 March 2018 at 10:55:16 UTC, Mike Parker wrote: class A { private int _value = 12; int value() @property { return _value; } void updateValue() { value = 13; } } ... auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value); Sorry. I overlooked that B.a is const. It still works, the `value` just needs to be `const` (or `inout`) and _value needs to be used in updateValue: class A { private int _value = 12; int value() const { return _value; } void updateValue() { _value = 13; } } auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value); In action: https://run.dlang.io/is/Tk1rY1 @Robert: If you need this a lot, the accessors package might be interesting to you: https://code.dlang.org/packages/accessors
Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]
On Thursday, 15 March 2018 at 12:00:08 UTC, Robert-D wrote: I want the function to create a mutable copy from a const or a imutable Like this: void main() { const S s = S(["": ""]); S b = s.dup(); } How can i do that? In that case, the problem is that you also have to .dup the aa: S dup() const pure { return S(aa.dup); } However, it seems aa.dup returns the wrong type - one would expect V[K] for inout(V[K]), but it returns inout(V)[K], or inout(string)[string], in your case. That's apparently a known bug: https://issues.dlang.org/show_bug.cgi?id=14148. The solution for now, then, is this: S dup() const pure { return S(cast(string[string])aa.dup); } -- Simen
Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]
On Thursday, 15 March 2018 at 11:33:49 UTC, Simen Kjærås wrote: On Thursday, 15 March 2018 at 11:18:48 UTC, Robert-D wrote: [...] This is where things go wrong: [...] 'inout' means that this function can keep the const, immutable or mutable status of the type on which the function is called. This means that an inout function has to treat the object as const, because otherwise the function would break the guarantees of immutable and const. When using inout on a function, you always want to put inout on something else too - either a ref parameter or the return value. In your case, this works: inout(S) dup() inout pure { return inout(S)(aa); } -- Simen I want the function to create a mutable copy from a const or a imutable Like this: void main() { const S s = S(["": ""]); S b = s.dup(); } How can i do that?
Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]
On Thursday, 15 March 2018 at 11:18:48 UTC, Robert-D wrote: struct S { string[string] aa; S dup() inout pure { return S(aa); } } void main() { auto s = S(["": ""]); s.dup(); } Result: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string] I need help with the above program. This is where things go wrong: S dup() inout pure { 'inout' means that this function can keep the const, immutable or mutable status of the type on which the function is called. This means that an inout function has to treat the object as const, because otherwise the function would break the guarantees of immutable and const. When using inout on a function, you always want to put inout on something else too - either a ref parameter or the return value. In your case, this works: inout(S) dup() inout pure { return inout(S)(aa); } -- Simen
Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]
struct S { string[string] aa; S dup() inout pure { return S(aa); } } void main() { auto s = S(["": ""]); s.dup(); } Result: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string] I need help with the above program.
Re: Readonly field for class type
On Thursday, 15 March 2018 at 10:16:49 UTC, Andrey wrote: Hello, is there way to declare read only field for class type with ability to call inner non constant methods? i.e.: class A { int value = 12; void updateValue() { value = 13; } } class B { const A a; this() { a = new A(); a.updateValue(); // error: mutable method is not callable using const object } } class A { private int _value = 12; int value() @property { return _value; } void updateValue() { value = 13; } } ... auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value);
Re: Readonly field for class type
On Thursday, 15 March 2018 at 10:16:49 UTC, Andrey wrote: Hello, is there way to declare read only field for class type with ability to call inner non constant methods? i.e.: class A { int value = 12; void updateValue() { value = 13; } } class B { const A a; this() { a = new A(); a.updateValue(); // error: mutable method is not callable using const object } } You can do this: class B { private A _a; @property const(A) a() { return _a; } this() { _a = new A(); _a.updateValue(); } } -- Simen
Re: Readonly field for class type
On Thursday, 15 March 2018 at 10:55:16 UTC, Mike Parker wrote: class A { private int _value = 12; int value() @property { return _value; } void updateValue() { value = 13; } } ... auto a = new A(); writeln(a.value); a.updateValue(); writeln(a.value); Sorry. I overlooked that B.a is const.
Re: how to make private class member private
On Tuesday, 13 March 2018 at 22:56:31 UTC, Jonathan M Davis wrote: The downside is that it increases the number of symbols which the program has to deal with when linking against a shared library, which can have some negative effects. - Jonathan M Davis If I understand correctly it's also responsible for TypeInfo being generated for private classes regardless of whether or not it is ever used.
Readonly field for class type
Hello, is there way to declare read only field for class type with ability to call inner non constant methods? i.e.: class A { int value = 12; void updateValue() { value = 13; } } class B { const A a; this() { a = new A(); a.updateValue(); // error: mutable method is not callable using const object } }