Re: Why do immutable variables need reference counting?
On Monday, 11 April 2022 at 21:48:56 UTC, Ali Çehreli wrote: On 4/11/22 08:02, Paul Backus wrote: > any pointers or references To add, Salih and I were in an earlier discussion where that concept appeared as "indirections." Ali I tried the following and I didn't understand one thing: Why is there no need to use dup when slicing? ```d struct S(T) { T fileName; this(T fileName) { this.fileName = fileName; report(); } ~this() { report(); } void report(string func = __FUNCTION__) { import std.stdio; writefln!"%s\nworking with %s"(func, fileName); } } alias T1 = const(char)[]; alias T2 = const char[]; alias T3 = const(char[]); // T3 == T2 alias T4 = immutable char[]; // Not compiling! void main() { auto fileName = "foo.txt".dup; auto s = S!T1(fileName); fileName[0..3] = "bar"; }/* Results: * *T1: * source.S!(const(char)[]).S.this working with foo.txt. source.S!(const(char)[]).S.~this working with bar.txt. * *T2: * source.S!(const(char[])).S.this working with foo.txt source.S!(const(char[])).S.~this working with bar.txt * *T3: * source.S!(const(char[])).S.this working with foo.txt source.S!(const(char[])).S.~this working with bar.txt * *T4 * Error: slice `fileName[0..3]` is not mutable */ ``` SDB@79
Re: Why do immutable variables need reference counting?
On 4/12/22 12:54, wjoe wrote: > I.e. immutable is constant data which is created at compile time - like > laws of physics, For completeness, we already have 'enum' and 'static const' for that. > should get a better name - maybe 'in' and get rid of const. Yes! 'in' for parameters! :D >> import std.stdio; >> import std.format; >> >> struct S { >> const(char)[] fileName; >> >> this(const(char)[] fileName) { >> this.fileName = fileName; >> report(); >> } >> >> ~this() { >> report(); >> } >> >> void report(string func = __FUNCTION__) { >> writefln!"%s working with %s."(func, fileName); >> } >> } >> >> void main() { >> char[] fileName = "foo.txt".dup; >> auto s = S(fileName); >> fileName[0..3] = "bar"; >> } >> >> >> If fileName were immutable, then the owner would not be able to mutate >> anyway, so the struct could get away without copying the file name. >> >> Ali > > I presume you refer to fileName in main() ? No, I meant the member 'fileName'. If the member is 'const' (as in C++ and as in the example above), you have to take a copy because the caller may mutate. (The example is demonstrating the case where the struct assumes data won't changed and gets surprised by the mutation.) > And if yes, if it were > const, it couldn't be mutated either, You started as assuming 'fileName' in main, so, I will continue with that. If the struct had 'const fileName' and pleaded that the caller also define a 'const' variable, that would be wishful thinking. The struct cannot trust that all callers will obey that plea. That kind of trust (more like guarantee) comes with 'immutable' and this is a good example of how immutable is different from const. (immutable does not exist in some languages like C++.) > so isn't immutable and const sort > of synonymous in that case or am I missing your point? If on the other hand, the member were immutable, the caller would have to provide immutable data and the struct could rely on the fact that the data was immutable forever. No need for a copy... Ali
Re: Why do immutable variables need reference counting?
On Tuesday, 12 April 2022 at 19:54:13 UTC, wjoe wrote: Especially since it's only a promise and the compiler accepts this: void foo (const(char)[] arr) { cast(char[])arr[0..3] = "baz"; } string bar = "123"; foo(bar); assert(bar=="baz"); But I could cast away const and modify the string bar. No, you could not. You're relying on undefined behavior there. Just because the compiler accepts something, doesn't mean it's ok. If you want to be guarded against wandering into undefined territory, that's what @safe does. With @safe, the cast doesn't compile.
Re: Why do immutable variables need reference counting?
On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote: On 4/11/22 05:57, wjoe wrote: > And because the data could be > in ROM any modification is an error. Fully agreed. However, how could I initialize such an object then? (You may have meant a read-only memory page instead of ROM.) I was thinking during compile time. By initializing a variable with immutable data or a pointer that points to an address e.G. an EEPROM. Even 'const' cause confusions because it's used in at least two different ways (even e.g. in C++): 1) I will not mutate data through this reference. For example, a parameter that is pointer to const achieves that: void foo (const(int)[] arr); 2) This variable is const: const i = 42; Well, there is the confusion: There is no "reference" in the second case at all! In general, I guess, it's a bad idea to reuse the same word for 2 or more distinctly different ideas. Maybe the const keyword in 1) should have a better name. Especially since it's only a promise and the compiler accepts this: void foo (const(char)[] arr) { cast(char[])arr[0..3] = "baz"; } string bar = "123"; foo(bar); assert(bar=="baz"); But I could cast away const and modify the string bar. So with that said I don't agree with you when you say immutability should be const's domain because const covers item 1 above as well, where there is no immutability of data whatsoever. The data may be perfectly mutable or immutable, where my access will be readonly. When I said immutability should be the domain of const I am referring only to 2). I.e. immutable is constant data which is created at compile time - like laws of physics, const as in 2) is constant data which is created at run time - like man made laws, and 1) should get a better name - maybe 'in' and get rid of const. And to be able to use immutable anywhere other than where immutable is explicitly specified, a copy is necessary. I know it's not as simple as that. But one can dream, right? :) producer from mutating it further. Example: import std.stdio; import std.format; struct S { const(char)[] fileName; this(const(char)[] fileName) { this.fileName = fileName; report(); } ~this() { report(); } void report(string func = __FUNCTION__) { writefln!"%s working with %s."(func, fileName); } } void main() { char[] fileName = "foo.txt".dup; auto s = S(fileName); fileName[0..3] = "bar"; } If fileName were immutable, then the owner would not be able to mutate anyway, so the struct could get away without copying the file name. Ali I presume you refer to fileName in main() ? And if yes, if it were const, it couldn't be mutated either, so isn't immutable and const sort of synonymous in that case or am I missing your point?
Re: Importing version identifiers from another file?
On Tue, Apr 12, 2022 at 10:07:15AM -0700, Ali Çehreli via Digitalmars-d-learn wrote: > On 4/11/22 01:57, KytoDragon wrote: > > > Is there any way to import version specifiers from a separate file? > > Have you tried mixing in the versions? Have one file with the versions > in it: > > // file: 'versions' > version = x; > > Then mix it in: > > mixin (import ("versions")); > > version (x) { /* ... */ } > > Seems to work for me. [...] If you need globally-defined versions, I'd just use the command-line option `-version=MyVersionA -version=MyVersionB ...`. Or, if you absolutely have to define versions in a source file, why not just use enums + static if instead: // versions.d module versions; enum MyVersionA = true; enum MyVersionB = true; // program.d import versions; static if (MyVersionA) { ... } else { ... } // ... and so on T -- An elephant: A mouse built to government specifications. -- Robert Heinlein
Re: Importing version identifiers from another file?
On 4/11/22 01:57, KytoDragon wrote: > Is there any way to import > version specifiers from a separate file? Have you tried mixing in the versions? Have one file with the versions in it: // file: 'versions' version = x; Then mix it in: mixin (import ("versions")); version (x) { /* ... */ } Seems to work for me. Ali
Re: Why do immutable variables need reference counting?
On 4/12/22 03:28, Dom DiSc wrote: > On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote: >> 1) I will not mutate data through this reference. For example, a >> parameter that is pointer to const achieves that: >> >> void foo (const(int)[] arr); >> >> 2) This variable is const: >> >> const i = 42; >> >> Well, there is the confusion: There is no "reference" in the second >> case at all! > I think this second case should not be allowed. Use > > immutable i = 42; > > instead. The meaning is identical, Only if there are no indirections as in 'int'. If I use a struct struct S { const(char[]) arr; } void foo(const(char[]) arr) { immutable s = immutable(S)(arr); // <-- ERROR: // Error: cannot implicitly convert expression `arr` of type `const(char[])` to `immutable(string)` } void main() { int[] arr; foo(arr); } The reason is a property of immutable that I like to describe as "selective" (or "demanding"). The struct variable cannot be immutable because it would be demanding that its constructor argument be immutable, which cannot be because foo's 'const' parameter hides that information even when it were immutable e.g. in main(). > but we could remove the burden of two > different meanings from const if it is not allowed. const should only be > allowed in function declarations. A variable must be declared either > mutable or immutable. It's only functions that may guarantee not to > modify a parameter or the objects they belong to, and so are allowed to > work on both mutable and immutable objects. I understand but the guarantee of immutable seems to leave no other choice. Ali
Re: Why do immutable variables need reference counting?
On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote: 1) I will not mutate data through this reference. For example, a parameter that is pointer to const achieves that: void foo (const(int)[] arr); 2) This variable is const: const i = 42; Well, there is the confusion: There is no "reference" in the second case at all! I think this second case should not be allowed. Use immutable i = 42; instead. The meaning is identical, but we could remove the burden of two different meanings from const if it is not allowed. const should only be allowed in function declarations. A variable must be declared either mutable or immutable. It's only functions that may guarantee not to modify a parameter or the objects they belong to, and so are allowed to work on both mutable and immutable objects.
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 17:59:12 UTC, Adam D Ruppe wrote: ooh yeah there's multiple here so the names don't overload and one on the time itself would override the ones from mixin template. You'd have to alias them together on the type. Hello Adam D Ruppe, I see what you mean, thank you very much for your answers! -FA
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 17:33:28 UTC, Steven Schveighoffer wrote: As I mentioned elsewhere, it does work. But the situation I think must be that it's only one mixin template. Probably also you can't have any overloads in the type itself. Note that I also think string mixins would work perfectly fine. And UFCS will never work for operator overloads, but that is by design. -Steve Hello Steve, Thank you very much for your answers, you have been very clear and helpful! -FA
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 16:36:51 UTC, Tejas wrote: Looks like a compiler bug, since substituting the real methods makes the `mixin template` code compile fine Hi Tejas, Thank you very much for your answer! Also, remove the `const`, otherwise the method will word only on `const` instances even if the bug gets fixed And thank you for this advice: I'll definitely remove the `const`! FA