Re: how to declare an immutable class?
On Friday, 12 August 2016 at 04:49:46 UTC, Charles Hixson wrote: It works, it's just not the syntax that I'd prefer. And it leaves me wondering exactly what immutable class Msg {...} was declaring. This should demonstrate: ``` immutable class iMsg { int getX() { return 10; } } class Msg { int getX() { return 20; } } void main() { auto msg1 = new immutable iMsg; assert(msg1.getX() == 10); auto msg2 = new immutable Msg; assert(msg2.getX() == 20); } ``` The line with msg2.getX() will fail to compile, because it's calling a non-immutable method on an immutable object. Change the declaration of Msg to the following and it compiles: ``` class Msg { int getX() immutable { return 20; } } ``` immutable class Foo { ... } is the same as declaring every member of Foo as immutable, just as final class Foo { ... } makes every method final.
Re: how to declare an immutable class?
On 08/11/2016 06:33 PM, Mike Parker via Digitalmars-d-learn wrote: On Friday, 12 August 2016 at 00:44:31 UTC, Charles Hixson wrote: A way around this, which may be the same as the approach used by string was: alias immutable(Msg_)Msg; classMsg_ { ... This is exactly what Jonathan suggested in the post above. And yes, it's how string is handled: alias string = immutable(char)[]; This so far appears to do what I want. The only problem is that it introduces an extraneous symbol, which I would prefer to avoid. What problem do you want to avoid? This is a common D idiom. Alias names are very short-lived. Yes, it's another symbol in the namespace, but it will never make it to the object file. It won't even make it to error messages -- you'll see Msg_ there instead. Yes, I saw his answer after I'd posted my resolution. It works, it's just not the syntax that I'd prefer. And it leaves me wondering exactly what immutable class Msg {...} was declaring.
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 03:41:54 UTC, bachmeier wrote: On Friday, 12 August 2016 at 03:31:37 UTC, ketmar wrote: On Friday, 12 August 2016 at 03:20:59 UTC, grampus wrote: Didn't realise the D community is such active. yes, we are. while we may be not very huge in number, we are very passionate about our language of choice. ;-) Currently there are about 40,000 DMD downloads a month, so the community isn't terribly small. The forums see activity from a lot of different posters. sheer number of downloads doesn't say much. comparing to some other communities (let's talk about rust and go, for example, as relatively fresh performers on the stage) our community is small. but in the end it is quality that matters, not huge numbers, i believe. and signal/noise ratio of thing NG is great (especially when i'm not posting here).
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 03:31:37 UTC, ketmar wrote: On Friday, 12 August 2016 at 03:20:59 UTC, grampus wrote: Didn't realise the D community is such active. yes, we are. while we may be not very huge in number, we are very passionate about our language of choice. ;-) Currently there are about 40,000 DMD downloads a month, so the community isn't terribly small. The forums see activity from a lot of different posters.
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 03:20:59 UTC, grampus wrote: Didn't realise the D community is such active. yes, we are. while we may be not very huge in number, we are very passionate about our language of choice. ;-)
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 02:31:29 UTC, ketmar wrote: On Friday, 12 August 2016 at 01:36:34 UTC, grampus wrote: [...] then you have to check if runtime is initialized at the start of each function that can be called from C side. like this: [...] Understand, I will be careful here. Thank you all for the quick feedback. Didn't realise the D community is such active. I hope D will be more popular Cheers
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 01:36:34 UTC, grampus wrote: I can use dlang in this existing project as long as nothing can be changed on the C side. then you have to check if runtime is initialized at the start of each function that can be called from C side. like this: private void ensureRuntimeInited () { static bool tlsinited = false; __gshared bool inited = false; if (!tlsinited) { synchronized(Object.classinfo) { if (!inited) { import core.runtime : Runtime; if (!Runtime.initialize) { import core.stdc.stdio : stderr, fprintf; import core.stdc.stdlib : abort; fprintf(stderr, "\nFATAL: failed to initialize druntime!\n"); abort(); } inited = true; } } tlsinited = true; } } extern(C) int myExtAPI () { ensureRuntimeInited(); // your D code here return 0; } yes, you have to do that in each exported function. as for your another question: if you won't call `rt_term()`, no module dtors will be called, no garbage will be collected at exit. there also may be problems with unregistering signal handlers, but i'm not sure. if you C app routinely loads and unloads .so without notifying it about the fact that .so is being unloaded, you are in big troubles not only with D, but with .so written in any other language. you *may* hack around this, but it's *WAY* better to fix your C app in this case.
Re: mixin bug?
On Thursday, 11 August 2016 at 21:25:20 UTC, sldkf wrote: On Thursday, 11 August 2016 at 20:27:01 UTC, Engine Machine wrote: This requires F2 to know the future. It also forces it to use a specific bar. I want inheritance like logic. You are goind to hit a wall. Template programming is not OOP. I'm not even sure that reflection would work in order to determine the most "recent" overload. Well, duh, it is not oop, but that doesn't mean it doesn't have similar abstractions, you need to read between the lines a bit more. Which is what we get when we mixin one deep, but when we go deeper, it breaks. I think this is a bug. It seems like D is trying to resolve things only after each mixin, rather than resolving after all nested mixins are evaluated. This is the only issue I see: "It seems like D is trying to...". We need to know exactly what D does: https://issues.dlang.org/show_bug.cgi?id=16376. It would be nice if D would bind the function calls lazily, so to speak, that is all I'm saying. This way we can get polymorphic/oop like behavior, if you will. template A(T) { void Bark() { writeln("Ruff Ruff"); } } template B(T) { mixin A!T; void Talk() { Bark(); } } template Duck(T) { mixin B!T; private void Bark() { writeln("Quack"); } } this is a contrived and misleading example if you take it seriously. But Duck.Talk(); should Quack. It would if D resolved Bark from Talk after the final "mixin". (In Duck, not in B). Else we are stuck with a barking duck. What it seems to do is first evaluate the template A!T, then B!T, then Duck!T. Since B!T is evaluated first and plugged in to Duck, Talk is already resolved to use A!T.Bark. Rather, If Duck!T was evaluated first, D would understand that Bark was already defined and when Talk was added, it could have it use the bark defined in duck, rather than A. This, would, of course, require a sort of Duck!T.B!T type, since B!T used inside of Duck would have a different Talk() than if it is not used in Duck. Again, maybe the compiler is just to ignorant to do this as it is complex(might require flow analysis and all that stuff or just be an ill-defined problem in general).
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 01:45:29 UTC, Mike Parker wrote: On Friday, 12 August 2016 at 01:36:34 UTC, grampus wrote: On Friday, 12 August 2016 at 01:09:47 UTC, ketmar wrote: On Friday, 12 August 2016 at 00:57:42 UTC, grampus wrote: it's 'cause you didn't initialized druntime. you have to use dlsym to get "rt_init" function and call it right after loading your .so, but before calling any other API from it. also, note that druntime is using SIGUSR1 and SIGUSR2 for it's internal housekeeping, so don't use this signals in your C++ code. Thank you for the quick reply. Do you mean that I have to do some changes on the C side? I can use dlang in this existing project as long as nothing can be changed on the C side. Do you think I can use dlang in our case? Thank you One way to handle this is to add initialize/terminate functions to your shared library. In that case, rather than rt_init, you can call the Runtime functions [1]: import core.runtime; extern(C) int initialize() { return Runtime.initialize(); } extern(C) int terminate() { return Runtime.terminate(); } From your C program, call initialize after loading the library and terminate before exiting. [1] http://dlang.org/phobos/core_runtime.html#.Runtime I will try this solution. One more question, if Runtime.initialize(); is called but when sofile is unloaded without calling Runtime.terminate(); is it going to cause any problem? for example so file is loaded again and again, Runtime.initialize() is called many times without Runtime.terminate().
Re: mixin bug?
On Thursday, 11 August 2016 at 21:03:36 UTC, Ali Çehreli wrote: On 08/11/2016 01:27 PM, Engine Machine wrote: > I see the mixin as a sort of copy and paste. That's the case for string mixins. Template mixins bring a name resolution scope. My understanding of the topic: http://ddili.org/ders/d.en/mixin.html#ix_mixin.name%20space,%20mixin The spec: https://dlang.org/spec/template-mixin.html Ali "When a mixed-in name is the same as a name that is in the surrounding scope, then the name that is in the surrounding scope gets used:" Which is my point, for "2nd order or higher" mixins, this does not occur. The why I see it is that mixin template is sort of like a copy and paste, but only paste if the members do not exist already(i.e., the current behavior for "1st order" mixins. I would expect the same logic to hold for higher order mixins since a mixin of a mixin is still a mixin). I realize why D behaves the way it does, but this is limiting. It simply greedily resolves referencing members rather than lazily. If the greedy method actually has some desired characteristic, then a lazy mixin would be nice. lazy mixin T1!T;
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 01:36:34 UTC, grampus wrote: On Friday, 12 August 2016 at 01:09:47 UTC, ketmar wrote: On Friday, 12 August 2016 at 00:57:42 UTC, grampus wrote: it's 'cause you didn't initialized druntime. you have to use dlsym to get "rt_init" function and call it right after loading your .so, but before calling any other API from it. also, note that druntime is using SIGUSR1 and SIGUSR2 for it's internal housekeeping, so don't use this signals in your C++ code. Thank you for the quick reply. Do you mean that I have to do some changes on the C side? I can use dlang in this existing project as long as nothing can be changed on the C side. Do you think I can use dlang in our case? Thank you One way to handle this is to add initialize/terminate functions to your shared library. In that case, rather than rt_init, you can call the Runtime functions [1]: import core.runtime; extern(C) int initialize() { return Runtime.initialize(); } extern(C) int terminate() { return Runtime.terminate(); } From your C program, call initialize after loading the library and terminate before exiting. [1] http://dlang.org/phobos/core_runtime.html#.Runtime
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 00:57:42 UTC, grampus wrote: Hi,erveryone I am trying to use dLang to make so file for existing c/c++ project. I followed the examples on https://dlang.org/dll-linux.html, which works well. but when I replaced import core.stdc.stdio; with import std.stdio; to use writefln() instead of printf(), then things changed. To expand on ketmar's answer, support for some language features exists in D Runtime. If you never use those features directly or indirectly (which means limiting yourself to the C API, avoiding anything that touches the GC, no associative arrays, and so on) then you don't need to initialize D runtime. That's why you don't see the problem when calling printf, but writeln uses features internally that require the D Runtime and so you get the error when you execute the program.
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 01:09:47 UTC, ketmar wrote: On Friday, 12 August 2016 at 00:57:42 UTC, grampus wrote: it's 'cause you didn't initialized druntime. you have to use dlsym to get "rt_init" function and call it right after loading your .so, but before calling any other API from it. also, note that druntime is using SIGUSR1 and SIGUSR2 for it's internal housekeeping, so don't use this signals in your C++ code. Thank you for the quick reply. Do you mean that I have to do some changes on the C side? I can use dlang in this existing project as long as nothing can be changed on the C side. Do you think I can use dlang in our case? Thank you
Re: how to declare an immutable class?
On Friday, 12 August 2016 at 00:44:31 UTC, Charles Hixson wrote: A way around this, which may be the same as the approach used by string was: alias immutable(Msg_)Msg; classMsg_ { ... This is exactly what Jonathan suggested in the post above. And yes, it's how string is handled: alias string = immutable(char)[]; This so far appears to do what I want. The only problem is that it introduces an extraneous symbol, which I would prefer to avoid. What problem do you want to avoid? This is a common D idiom. Alias names are very short-lived. Yes, it's another symbol in the namespace, but it will never make it to the object file. It won't even make it to error messages -- you'll see Msg_ there instead.
Re: How to use std. packages in so files written in dlang
On Friday, 12 August 2016 at 00:57:42 UTC, grampus wrote: it's 'cause you didn't initialized druntime. you have to use dlsym to get "rt_init" function and call it right after loading your .so, but before calling any other API from it. also, note that druntime is using SIGUSR1 and SIGUSR2 for it's internal housekeeping, so don't use this signals in your C++ code.
How to use std. packages in so files written in dlang
Hi,erveryone I am trying to use dLang to make so file for existing c/c++ project. I followed the examples on https://dlang.org/dll-linux.html, which works well. but when I replaced import core.stdc.stdio; with import std.stdio; to use writefln() instead of printf(), then things changed. compiling was still fine. so file still can be loaded. But writefln() generated a error: "Segmentation fault (core dumped)" I tried to search for solutions everywhere but nothing works. BTW, in the command "dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is" which path should I use for "/path/to/where/shared/library/is"? Tried some possible paths, none of them works. I compiled so file without "-L-rpath". At least for the examples still works I am new to dLang. I hope I get help here. Thanks in advance.
Re: how to declare an immutable class?
A way around this, which may be the same as the approach used by string was: alias immutable(Msg_)Msg; classMsg_ { ... This so far appears to do what I want. The only problem is that it introduces an extraneous symbol, which I would prefer to avoid. OTOH, I did fix a few problems before this solution On 08/11/2016 10:56 AM, Charles Hixson via Digitalmars-d-learn wrote: I want to declare a class all instances of which will be immutable, and all references to which will be inherently immutable (so that I don't need to slip a huge number of "immutable" statements in my code). This is surely possible, because string acts just that way, but I can't figure out how to do this. immutable classMsg {this(...) immutable{...} ... } doesn't work that way, as when I do Msg m = new Msg (...); I get: Error: incompatible types for ((this.m) - (m)): 'immutable(Msg)' and 'cellram.Msg' and Error: immutable method cellram.Msg.this is not callable using a mutable object Does anyone know the correct approach?
Re: mixin bug?
On Thursday, 11 August 2016 at 20:27:01 UTC, Engine Machine wrote: This requires F2 to know the future. It also forces it to use a specific bar. I want inheritance like logic. You are goind to hit a wall. Template programming is not OOP. I'm not even sure that reflection would work in order to determine the most "recent" overload. Which is what we get when we mixin one deep, but when we go deeper, it breaks. I think this is a bug. It seems like D is trying to resolve things only after each mixin, rather than resolving after all nested mixins are evaluated. This is the only issue I see: "It seems like D is trying to...". We need to know exactly what D does: https://issues.dlang.org/show_bug.cgi?id=16376.
Re: Retreive method given object, name and arguments
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote: here is something for you to play with: import std.stdio; enum CallAllowed0; enum CallAllowed1; struct S { @CallAllowed0 void foo () { writeln("foo()"); } @CallAllowed1 void foo (int n) { writeln("foo(", n, ")"); } } bool hasGoodMethod(string methodName, UDA, C, Args...) () { import std.traits: hasUDA; bool res = false; alias Identity(T...) = T[0]; foreach (string mem; __traits(allMembers, C)) { static if (mem == methodName) { static if (is(typeof(__traits(getMember, C, mem { alias mx = Identity!(__traits(getMember, C, mem)); foreach (auto t; __traits(getOverloads, C, mem)) { static if (hasUDA!(t, UDA)) { static if (is(typeof((Args args) { auto dg = &t; dg(args); }))) { res = true; break; } } } } } } return res; } auto doit(string methodName, UDA, C, Args...) (C c, Args args) { static if (hasGoodMethod!(methodName, UDA, C, Args)) { mixin("return c."~methodName~"(args);"); } else { static assert(0, "can't call method '"~methodName~"' in type "~C.stringof); } } void main () { S s; version(v0) { s.doit!("foo", CallAllowed0)(42); } else version(v1) { s.doit!("foo", CallAllowed1)(42); } else version(v2) { s.doit!("foo", CallAllowed0)(); } else version(v3) { s.doit!("foo", CallAllowed1)(); } else { static assert(0, "version?"); } } % rdmd -version=v0 z02.d z02.d(47): Error: static assert "can't call method 'foo' in type S" z02.d(55):instantiated from here: doit!("foo", CallAllowed0, S, int) % rdmd -version=v1 z02.d foo(42) % rdmd -version=v2 z02.d foo() % rdmd -version=v3 z02.d z02.d(47): Error: static assert "can't call method 'foo' in type S" z02.d(61):instantiated from here: doit!("foo", CallAllowed1, S)
Re: mixin bug?
On 08/11/2016 01:27 PM, Engine Machine wrote: > I see the mixin as a sort of copy and paste. That's the case for string mixins. Template mixins bring a name resolution scope. My understanding of the topic: http://ddili.org/ders/d.en/mixin.html#ix_mixin.name%20space,%20mixin The spec: https://dlang.org/spec/template-mixin.html Ali
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote: I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. While one could argue that it can be unsafe, in the my context, it is not. Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? I use several parameters to pass info to the type that does not change affect the type itself. It prevents the "same type" from being used with "itself". another example: struct s(T1, T2) { T1; } then s!(int, double) and s!(int, float) should really be the same type! The fact that T2 is not used is important! I guess D just can't handle it though? It can be done, but you have to be explicit and should think very carefully if this is really a good design. struct X(int defaultSize = 100) { int size; int* p; void foo(int size) { size = max(size, defaultSize); p = cast(int*)malloc(size); } X opAssign(X2: X!n, int n)(X2 other) { //Do whatever you want here } X2 changeDefaultSize(int n)() { auto newX = X!n(n, p); p = null; //Release ownership of p return newX; } } void takesX50(X!50 x) { //... } void main() { X!100 n; X!100 m; X!50 o; n = m; o = m; takesX50(n); //Error takesX50(n.changeDefaultSize!50); //Okay } Really though this problem is properly solved by runtime polymorphism.
Re: Retreive method given object, name and arguments
On Thursday, 11 August 2016 at 20:41:33 UTC, ketmar wrote: ah, my bad, i missed UDA part of the question. sorry. ;-)
Re: Retreive method given object, name and arguments
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote: import std.stdio; struct S { void foo () { writeln("foo()"); } void foo (int n) { writeln("foo(", n, ")"); } } auto doit(string methodName, C, Args...) (C c, Args args) { static if (is(typeof(mixin("c."~methodName~"(args)" { mixin("return c."~methodName~"(args);"); } else { throw new Exception("no method '"~methodName~"' in type "~C.stringof); } } void main () { S s; s.doit!"foo"(42); s.doit!"foo"(); s.doit!"oops"(); // this throws } of course, you can replace `static if` with `static assert` to turn it into compile-time error.
Re: Template parameters that don't affect template type
On 8/11/16 4:15 PM, Engine Machine wrote: On Thursday, 11 August 2016 at 18:42:51 UTC, Steven Schveighoffer wrote: On 8/11/16 2:11 PM, Engine Machine wrote: I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. And they should be different types. The code generated for the type is different, in this case it's important to declare these are not the same type. For example, if x = y worked, then what should x.foo(5) do? While one could argue that it can be unsafe, in the my context, it is not. Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? The type is part of the template, and the instantiations are different. So no. I use several parameters to pass info to the type that does not change affect the type itself. It prevents the "same type" from being used with "itself". Then define how the compiler can convert from one to another. Or redesign the type to specify the parameters at the right time. another example: struct s(T1, T2) { T1; } then s!(int, double) and s!(int, float) should really be the same type! The fact that T2 is not used is important! That's not how template types work. your code is shorthand for: template s(T1, T2) { struct s { T1 t1; // I assume you wanted to put a member here? } } Two different instantiations of s create two different namespaces where the structs are not the same. I don't think this proves anything. You just rewrote the template. T2 is still not used in either case and hence the type does not depend on it. OK, I'll use a different example: struct S(int N) { int x; } S!1 s1; S!2 s2 = s1; // error This is very similar to what you are asking for. This can be reimagined like so: struct S1 { int x; } struct S2 { int x; } S1 s1; S2 s2 = s1; // error The names end in a different number. They have the same types and structure, but the compiler considers them to be different types. Each instantiation of a template defines a DIFFERENT namespace. The only time the namespaces are identical are when the template parameters are identical. The reason templates are so useful is because I don't HAVE to write both S1 and S2. I can write it once and not have to repeat myself. But the template itself is not a namespace. Only the instantiated template is one. Basically your logic is something like: A = 0*5 is different than B = 0*6. But both are the same, just because they look different doesn't change that. Not at all. This is way off. You are misunderstanding what I am asking or saying. The code may be different, but one reference can store the value of another. The type itself does not depend on the parameter. The namespace in which the type is declared depends on the parameter. Templates depend on this. For instance: template Foo(string name) { static int x; } Foo!"blah".x = 5; auto y = Foo!"blar".x; The namespace I've declared depends on the name I've passed the template. I want to fetch a *different* x when I declare a *different* namespace. That's the point! If the compiler said "hey, you aren't using the name string, so I'm just going to assume all these are the same", that's going to screw up the entire purpose of this construct. X!100 x; X!50 y; 50 for y does not change anything to the outside world about y. So, for all practical purposes, we have X x; X y; No, you have X100 x; X50 y; Where X100 and X50 have the exact same structure. But they are different types because the names are different. You are confusing the general case with the specific case. Sure, in general, it doesn't work, we know that. But not all types are dependent on their type parameter. Just because such parameters are specified does not necessarily mean they should be different types. Again, not how templates work. You are looking for a different mechanism. -Steve
Re: Retreive method given object, name and arguments
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote: Is there a way to implement "getSymbolOfCall" and "getDelegateOfCall" such that doit is functionally equivalent to calling the method directly? auto doit(C, string methodName, Args...)(C c, Args args) { alias methodSymbol = getSymbolOfCall!(c, methodName, Args); pragma(msg, hasUDA!(methodSymbol, "my attr")); auto dg = getDelegateOfCall!(c, methodName, Args); return dg(args); } They should deal with getting the right overload, opDispatch-ing, and deducing template arguments from the real argument list to get a concrete delegate pointer. methodSymbol should give access to compile-time introspection like full signature and UDAs. The ability to do this for non-member functions would be cool too, but is beyond my use case. Maybe I'm not understanding correctly, but I think you can use string mixins: auto doit(string methodName, C, Args...)(C c, Args args) { mixin("return c." ~ methodName ~ "(args);"); }
Retreive method given object, name and arguments
Is there a way to implement "getSymbolOfCall" and "getDelegateOfCall" such that doit is functionally equivalent to calling the method directly? auto doit(C, string methodName, Args...)(C c, Args args) { alias methodSymbol = getSymbolOfCall!(c, methodName, Args); pragma(msg, hasUDA!(methodSymbol, "my attr")); auto dg = getDelegateOfCall!(c, methodName, Args); return dg(args); } They should deal with getting the right overload, opDispatch-ing, and deducing template arguments from the real argument list to get a concrete delegate pointer. methodSymbol should give access to compile-time introspection like full signature and UDAs. The ability to do this for non-member functions would be cool too, but is beyond my use case.
Re: mixin bug?
On Thursday, 11 August 2016 at 19:05:58 UTC, sldkf wrote: On Thursday, 11 August 2016 at 17:56:47 UTC, Engine Machine wrote: template F1(T) { void bar() { writeln("Bar0"); } } template F2(T) { mixin F1!T; void foo() { bar(); } } template F3(T) { mixin F2!T; void bar() { writeln("Bar1"); } // <- This bar should be used for F2's foo! } struct F4(T) { mixin F3!T; } (Or on can turn F3 in to a struct directly) Then f3.foo() calls bar from F0, not F3's bar! This seems like a big bug! One expects the same behavior of mixins regardless of mixin nesting. While you could argue that foo, when declared, is calling F0's bar, this is not consistent with the view that mixin templates only adds what is not there. I don't like the idea that calls are resolved first come first serve as it means one can't extend templates in a natural logical way. I don't think it's a bug. F3's bar() doesn't exist yet in F2. Logically F1's one is called. Yes, but when we "mixin" again, bar then does exist. I see the mixin as a sort of copy and paste. We only paste in what doesn't exist. So the first time bar gets inserted in to F2, but then that bar doesn't get inserted in to F3 because it already exists. Basically a mixin of a mixin is not logically a mixin. That makes no sense to me. A mixin is suppose to behave a certain way, but when we do a mixin of a mixin we get behavior that doesn't behave the same way as a single mixin. The language allows to alias a mixin so that a particular overload can be called. In you case you can really target F1.bar without problem: I don't want to target F1.bar, I want foo to target future bar's. It is like overloading, but for templates. If you were doing overloading, and it called the base function instead, it wouldn't be overloading, would it? °°° template F1(T){void bar() {writeln("Bar0");}} template F2(T) { mixin F1!T FF1; void foo() { FF3.bar; } } This requires F2 to know the future. It also forces it to use a specific bar. I want inheritance like logic. Which is what we get when we mixin one deep, but when we go deeper, it breaks. I think this is a bug. It seems like D is trying to resolve things only after each mixin, rather than resolving after all nested mixins are evaluated.
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 18:42:51 UTC, Steven Schveighoffer wrote: On 8/11/16 2:11 PM, Engine Machine wrote: I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. And they should be different types. The code generated for the type is different, in this case it's important to declare these are not the same type. For example, if x = y worked, then what should x.foo(5) do? While one could argue that it can be unsafe, in the my context, it is not. Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? The type is part of the template, and the instantiations are different. So no. I use several parameters to pass info to the type that does not change affect the type itself. It prevents the "same type" from being used with "itself". Then define how the compiler can convert from one to another. Or redesign the type to specify the parameters at the right time. another example: struct s(T1, T2) { T1; } then s!(int, double) and s!(int, float) should really be the same type! The fact that T2 is not used is important! That's not how template types work. your code is shorthand for: template s(T1, T2) { struct s { T1 t1; // I assume you wanted to put a member here? } } Two different instantiations of s create two different namespaces where the structs are not the same. I don't think this proves anything. You just rewrote the template. T2 is still not used in either case and hence the type does not depend on it. Basically your logic is something like: A = 0*5 is different than B = 0*6. But both are the same, just because they look different doesn't change that. I'd suggest if you don't use a template parameter, don't declare it. If you use it in a member function only (as in your first example), declare it in the member function as a template parameter. I guess D just can't handle it though? No, it doesn't handle incorrect assumptions very well ;) -Steve You are misunderstanding what I am asking or saying. The code may be different, but one reference can store the value of another. The type itself does not depend on the parameter. X!100 x; X!50 y; 50 for y does not change anything to the outside world about y. So, for all practical purposes, we have X x; X y; in which case we can do x = y; with no problem. You are confusing the general case with the specific case. Sure, in general, it doesn't work, we know that. But not all types are dependent on their type parameter. Just because such parameters are specified does not necessarily mean they should be different types. My example is not good because the types are different. If I did something like void foo(int size) { Size = max(size, defaultSize, 100); p = cast(int*)malloc(Size); } Then it would be different. in this case X!50 and X!100 would be the same. X!101 would not.
Re: Template parameters that don't affect template type
Also, what if we use a class instead of a struct? in this case they are both references to the same thing. I see a problem with reflection though, as one could get the template parameter value and it would wrong on conversion. D takes the easy way out of just preventing complex and potentially ill-defined behavior, I guess that is ultimately a good thing, even if it makes it a pain in some cases.
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 19:28:47 UTC, Lodovico Giaretta wrote: On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote: [...] If, in your case, it is possible to use one type as the other, then specify it. I mean, implement a templated opAssign that allows you to assign values of one instantiation to values of another. While doing so, remember that this will not change the behaviour of the assigned-to variable, but will only transfer the runtime state from one variable to the other. struct S(T1, T2) { T1 t; void opAssign(T)(auto ref S!(T1, T) other) { t = other.t; } } unittest { S!(int, float) x(1); S!(int, char) y(3); x = y; assert(x.t == 3);// the value of x is changed static assert(is(typeof(x) == S!(int, float))) // the type of x isn't changed } Ok, well, my point is that in some cases, the OpAssign is trivially since everything is copied. I guess being explicit is not a bad thing in this case though.
Re: how to declare an immutable class?
On Thursday, August 11, 2016 10:56:59 Charles Hixson via Digitalmars-d-learn wrote: > I want to declare a class all instances of which will be immutable, and > all references to which will be inherently immutable (so that I don't > need to slip a huge number of "immutable" statements in my code). > > This is surely possible, because string acts just that way, but I can't > figure out how to do this. > > immutable classMsg {this(...) immutable{...} ... } > > doesn't work that way, as when I do > > Msg m = new Msg (...); > > I get: > > Error: incompatible types for ((this.m) - (m)): 'immutable(Msg)' and > 'cellram.Msg' > > and > > Error: immutable method cellram.Msg.this is not callable using a mutable > object > > > Does anyone know the correct approach? There is no such thing as an immutable class. You can have an instance of a class that's immutable, and you can make it so that all of the members of a class are immutable, but you're still going to need to use the keyword immutable with the type to indicate that it's immutable. If you do immutable class C { ... } that's the same as immutable { class C { ... } } It makes it so that all of the members of the class are immutable, but if you use C in the code, it won't be immutable - only immutable C will be immutable. Now, you could use an alias to reduce your typing. e.g. alias IC = immutable C; and then whenever you use IC, it will be replaced with immutable C by the compiler, but anywhere you use C rather than the alias, you're going to need to put immutable on it if you want it to be immutable. So, your code could become something like immutable class _Msg { // the immutable on the class made this immutable. There's no need // to mark it with immutable. this(...) { } ... } alias Msg = immutable _Msg; and then when you do auto msg = new Msg; you'll get an immutable(_Msg). - Jonathan M Davis
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote: [...] If, in your case, it is possible to use one type as the other, then specify it. I mean, implement a templated opAssign that allows you to assign values of one instantiation to values of another. While doing so, remember that this will not change the behaviour of the assigned-to variable, but will only transfer the runtime state from one variable to the other. struct S(T1, T2) { T1 t; void opAssign(T)(auto ref S!(T1, T) other) { t = other.t; } } unittest { S!(int, float) x(1); S!(int, char) y(3); x = y; assert(x.t == 3);// the value of x is changed static assert(is(typeof(x) == S!(int, float))) // the type of x isn't changed }
Re: mixin bug?
On Thursday, 11 August 2016 at 17:56:47 UTC, Engine Machine wrote: template F1(T) { void bar() { writeln("Bar0"); } } template F2(T) { mixin F1!T; void foo() { bar(); } } template F3(T) { mixin F2!T; void bar() { writeln("Bar1"); } // <- This bar should be used for F2's foo! } struct F4(T) { mixin F3!T; } (Or on can turn F3 in to a struct directly) Then f3.foo() calls bar from F0, not F3's bar! This seems like a big bug! One expects the same behavior of mixins regardless of mixin nesting. While you could argue that foo, when declared, is calling F0's bar, this is not consistent with the view that mixin templates only adds what is not there. I don't like the idea that calls are resolved first come first serve as it means one can't extend templates in a natural logical way. I don't think it's a bug. F3's bar() doesn't exist yet in F2. Logically F1's one is called. The language allows to alias a mixin so that a particular overload can be called. In you case you can really target F1.bar without problem: °°° template F1(T){void bar() {writeln("Bar0");}} template F2(T) { mixin F1!T FF1; void foo() { FF3.bar; } } template F3(T) { mixin F2!T FF2; void bar() { writeln("Bar1");} } struct F4(T){mixin F3!T FF3;} °°° See https://dlang.org/spec/template-mixin.html#mixin_scope However the specification doesn't say what is the rule that's applied. Even if it look logical that F1.bar() is chosen it has to be written somewhere.
Re: Template parameters that don't affect template type
On 8/11/16 2:42 PM, Steven Schveighoffer wrote: On 8/11/16 2:11 PM, Engine Machine wrote: I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. And they should be different types. The code generated for the type is different, in this case it's important to declare these are not the same type. For example, if x = y worked, then what should x.foo(5) do? Of course, I meant x = z :) -Steve
Re: Template parameters that don't affect template type
On 08/11/2016 11:11 AM, Engine Machine wrote: > I have the need, in some cases, to pass static information to a template > class but don't want it to affect its type. > > import std.algorithm, core.stdc.stdlib; > struct X(int defaultSize = 100) > { >int Size; >int* p; >void foo(int size) >{ > Size = max(size, defaultSize); > p = cast(int*)malloc(Size); >} > } > > If I do > > X!100 x; > X!100 y; > X!50 z; > > then I can do > > x = y; > > but not > > x = z; > > but of course D things these are completely different types. The reason they are different types is the fact that the code generated for X!100 and X!50 are different. If x=z were allowed, which foo() would you expect to be executed for x.foo()? If it would change at run time depending on the actual type, we need a run-time expression, which cannot be a template parameter. > The type it > self does not depend on the default size. > > While one could argue that it can be unsafe, in the my context, it is not. Understood but not possible with the template definition of D. > Is there any way to get D to understand I want do not want a template > parameter to be part of the type comparison? It must involve runtime. > I use several parameters to pass info to the type that does not change > affect the type itself. It prevents the "same type" from being used with > "itself". > > another example: > > struct s(T1, T2) > { > T1; > } > > then > > s!(int, double) > > and > > s!(int, float) > > should really be the same type! The fact that T2 is not used is important! It's not used in this module but another module may be using __traits (or std.traits) to inspect that second argument. > I guess D just can't handle it though? By design, no. (Another language that behaves this way is C++.) Ali
Re: how to declare an immutable class?
On Thursday, 11 August 2016 at 17:56:59 UTC, Charles Hixson wrote: Does anyone know the correct approach? I do: °° immutable class Foo { this() {} } void main() { auto foo = new immutable(Foo); } °° But take care because you can't do much with an immutable class.
Re: Template parameters that don't affect template type
On 8/11/16 2:11 PM, Engine Machine wrote: I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. And they should be different types. The code generated for the type is different, in this case it's important to declare these are not the same type. For example, if x = y worked, then what should x.foo(5) do? While one could argue that it can be unsafe, in the my context, it is not. Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? The type is part of the template, and the instantiations are different. So no. I use several parameters to pass info to the type that does not change affect the type itself. It prevents the "same type" from being used with "itself". Then define how the compiler can convert from one to another. Or redesign the type to specify the parameters at the right time. another example: struct s(T1, T2) { T1; } then s!(int, double) and s!(int, float) should really be the same type! The fact that T2 is not used is important! That's not how template types work. your code is shorthand for: template s(T1, T2) { struct s { T1 t1; // I assume you wanted to put a member here? } } Two different instantiations of s create two different namespaces where the structs are not the same. I'd suggest if you don't use a template parameter, don't declare it. If you use it in a member function only (as in your first example), declare it in the member function as a template parameter. I guess D just can't handle it though? No, it doesn't handle incorrect assumptions very well ;) -Steve
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote: Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? No. Use a standard run-time parameter. Your problem can be solved by defining a constructor.
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote: I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. While one could argue that it can be unsafe, in the my context, it is not. Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? I use several parameters to pass info to the type that does not change affect the type itself. It prevents the "same type" from being used with "itself". another example: struct s(T1, T2) { T1; } then s!(int, double) and s!(int, float) should really be the same type! The fact that T2 is not used is important! I guess D just can't handle it though? Another good example is if something like template X(bool ClearMemory = false) { } ClearMemory would clearly not affect the type if it just clears memory that is malloc'ed, yet D would treat treat X!true from X!false.
Template parameters that don't affect template type
I have the need, in some cases, to pass static information to a template class but don't want it to affect its type. import std.algorithm, core.stdc.stdlib; struct X(int defaultSize = 100) { int Size; int* p; void foo(int size) { Size = max(size, defaultSize); p = cast(int*)malloc(Size); } } If I do X!100 x; X!100 y; X!50 z; then I can do x = y; but not x = z; but of course D things these are completely different types. The type it self does not depend on the default size. While one could argue that it can be unsafe, in the my context, it is not. Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison? I use several parameters to pass info to the type that does not change affect the type itself. It prevents the "same type" from being used with "itself". another example: struct s(T1, T2) { T1; } then s!(int, double) and s!(int, float) should really be the same type! The fact that T2 is not used is important! I guess D just can't handle it though?
mixin bug?
template F1(T) { void bar() { writeln("Bar0"); } } template F2(T) { mixin F1!T; void foo() { bar(); } } template F3(T) { mixin F2!T; void bar() { writeln("Bar1"); } // <- This bar should be used for F2's foo! } struct F4(T) { mixin F3!T; } (Or on can turn F3 in to a struct directly) Then f3.foo() calls bar from F0, not F3's bar! This seems like a big bug! One expects the same behavior of mixins regardless of mixin nesting. While you could argue that foo, when declared, is calling F0's bar, this is not consistent with the view that mixin templates only adds what is not there. I don't like the idea that calls are resolved first come first serve as it means one can't extend templates in a natural logical way.
how to declare an immutable class?
I want to declare a class all instances of which will be immutable, and all references to which will be inherently immutable (so that I don't need to slip a huge number of "immutable" statements in my code). This is surely possible, because string acts just that way, but I can't figure out how to do this. immutable classMsg {this(...) immutable{...} ... } doesn't work that way, as when I do Msg m = new Msg (...); I get: Error: incompatible types for ((this.m) - (m)): 'immutable(Msg)' and 'cellram.Msg' and Error: immutable method cellram.Msg.this is not callable using a mutable object Does anyone know the correct approach?
Re: Unexpected foreach lowering
On Thursday, August 11, 2016 08:42:27 Steven Schveighoffer via Digitalmars-d- learn wrote: > On 8/11/16 12:28 AM, Jonathan M Davis via Digitalmars-d-learn wrote: > > On Wednesday, August 10, 2016 21:00:01 Lodovico Giaretta via > > Digitalmars-d- > > > > learn wrote: > >> Wow. Thanks. I didn't know the compiler would try opSlice. I will > >> file it. > > > > It does that so that you can use foreach with containers without having to > > call something on the container. The idea is that the container will > > implement opSlice and make it return a range over the container, and > > foreach will then use that range to iterate over the container. > > I get that. But it shouldn't try opSlice *first* if the item itself is a > range (and it does do this). Many random-access ranges define opSlice, > and most of the time range[] returns this. But in this case, it doesn't. > > But it's a no-op for ranges, why waste time calling it? I was just explaining what the deal with opSlice and containers was, since the OP wasn't familiar with it. I wasn't really saying anything about the suggested change. However, I have to agree that the suggested change is likely a good one. As it stands, no range should be implementing opSlice with no arguments, since it's a container function, not a range function. No range trait tests for it, and no range-based code should be using it. It's just supposed to be used on containers to get a range not on the ranges themselves. But some folks put it on ranges anyway (IIRC, there are even at least a couple of cases in Phobos where opSlice is implemented on ranges when it shouldn't be), and it causes problems. There might be a reason why it would be a bad idea to change it so that opSlice is ignored by foreach if the type is a range, but I can't think of any right now. Unfortunately, ranges and foreach have a tendency to get a bit funny thanks to the differing behavior between types (e.g. ranges that are implicitly saved when used with foreach vs those that aren't), so mucking around with it should be done with care, but it at least seems like your suggestion to skip opSlice if the range primitives are there is a good one. - Jonathan M Davis
Re: How to add nogc to delegate
On Thursday, 11 August 2016 at 05:12:39 UTC, ag0aep6g wrote: On 08/11/2016 06:15 AM, Engine Machine wrote: void foo(@nogc void delegate()) doesn't work. Put it after the parameter list, like so: void foo(void delegate() @nogc) You may also need to add the scope keyword too. Reference: http://forum.dlang.org/thread/zaxaqgeeenwypmijr...@forum.dlang.org
Re: Unexpected foreach lowering
On 8/10/16 5:14 PM, ag0aep6g wrote: On 08/10/2016 10:54 PM, Steven Schveighoffer wrote: The issue is that it tries using [] on the item to see if it defines a range-like thing. Since you don't define opSlice(), it automatically goes to the subrange. This breaks for int[] as well as Array. If I add opSlice to your code (and return this) it works. This is definitely a bug, it should try range functions before opSlice. Please file. Related: https://issues.dlang.org/show_bug.cgi?id=14619 That's the same issue. Thanks. Your case is even worse, because calling save could be unnecessary and costly. Note that the compiler will turn this: foreach(...; foo[]) into this: foreach(...; foo[][]) ugly... -Steve
Re: Unexpected foreach lowering
On 8/11/16 12:28 AM, Jonathan M Davis via Digitalmars-d-learn wrote: On Wednesday, August 10, 2016 21:00:01 Lodovico Giaretta via Digitalmars-d- learn wrote: Wow. Thanks. I didn't know the compiler would try opSlice. I will file it. It does that so that you can use foreach with containers without having to call something on the container. The idea is that the container will implement opSlice and make it return a range over the container, and foreach will then use that range to iterate over the container. I get that. But it shouldn't try opSlice *first* if the item itself is a range (and it does do this). Many random-access ranges define opSlice, and most of the time range[] returns this. But in this case, it doesn't. But it's a no-op for ranges, why waste time calling it? -Steve
Re: minor question of the difference between " and '
On Wednesday, 10 August 2016 at 23:32:54 UTC, WhatMeWorry wrote: Afterall, isn't that the definition of a string? So what's up with the two groupings of single quotes? http://www.howtogeek.com/howto/29980/whats-the-difference-between-single-and-double-quotes-in-the-bash-shell/