Re: Why does a switch break cause a segmentation fault
Shouldn't (stream == null) be (stream is null)? -Eric From: "adamgoldberg via Digitalmars-d-learn" To: digitalmars-d-learn@puremagic.com Sent: Monday, July 22, 2019 3:05:17 PM Subject: Why does a switch break cause a segmentation fault Hey, I just happened to be writing a program in D an stumbled upon a bug, that causes it to terminate after receiving a SEGV signal, nothing wierd so far but it looks everything I tried shows it is the break statement inside of a switch. It seems to have a relatively random chance of occuring, and also somewhat dependant on the compiler, and build mode used. I'm short on time so instead of rewriting my SO post I will just link it. Here! https://stackoverflow.com/questions/57153617/random-segmentation-fault-in-d-lang-on-switch-break Hope someone can help!
Re: write a function template specialisation that tests if an argument is known at compile time
On Tuesday, 14 August 2018 at 03:01:11 UTC, Cecil Ward wrote: On Tuesday, 14 August 2018 at 02:53:01 UTC, Cecil Ward wrote: On Sunday, 12 August 2018 at 12:27:59 UTC, Alex wrote: On Saturday, 11 August 2018 at 05:17:51 UTC, Cecil Ward wrote: T myfunc(T)( T x, uint mask ) if ( mask == 3 ) { return fast_func( x, mask ); } [...] Is it the volcano pattern you are looking for? https://p0nce.github.io/d-idioms/#Is-this-available-at-compile-time-or-runtime? Wow, now that _is_ clever. I think that is definitely a big part of it. Now somehow after having used a static if to select the known-at-compile-time case I then have to test the argument for particular values. So how to get the next step along the way? Would it be ok to ask Walter maybe ? I am so far out of my depth here tho. If you are that far, then it seems simple. You always call it as a template: T myfunc(uint mask, T)(T x) {} In myfunc you decide if umask is compile time or not. If not, then call a templated function with static if's for specific values, otherwise call the regular function.
Re: unimplemented abstract function compiles.
I thought it would work the same way as an interface (which must be implemented by the direct sub class, otherwise compile error). But apparently it's possible to implement an abstract function anywhere in the class hierarchy. That makes it, in this case, impossible to check during compile time. I ran into this while loading objects from a file using Object.factory and forgot to implement an abstract function in one class.
unimplemented abstract function compiles.
Code below compiles while I would not expect it to compile. Is there a reason that this compiles? Specs are a bit lite on abstract classes. Only thing I found that would need to allow this is: "19.4 functions without bodies" https://dlang.org/spec/function.html#function-declarations But that's explicitly without the abstract keyword.. class I { abstract void f(); } class C : I { } unittest { C c = cast(C) Object.factory("C"); c.f(); } I also couldn't find anything about this in the issue tracker.
Action at a distance, separating operations from subjects
Not a question. I came up with a nice and simple way to apply operations on an arbitrary number of members of unknown type of a set of objects of unknown type. This without having to reimplement these operations for each class that needs to support the operation(s). All this without explicitly storing references to these members. The only requirement is that the members fulfill the expectations of the operations. An example will make it clearer. // First we need to store the operations somewhere: class Storage { Operations operations; } // And here we have a subject that contains data structs (of any type) that we want to apply the operations on. // There may also be a SubjectB, C, ... // For simplicity it subclasses Storage but operations could also be stored externaly, e.g in an array, or in some cases in the subject itself. class SubjectA : Storage { // The members we want operations to work on. // Their type doesn't matter as long as they are compatible with // the operations. In this example assume these have a name and value member SomeStruct1 a; SomeStruct2 b; SomeStruct3!Y c; // Make these members available for operations with one line: this() { operations.operateOn(a, b, c); } } // After this simple setup you can now apply operations from anywhere and whenever you want: foreach(Storage stor; storageList) { string s = stor.operations.concatNames(); // concats the names of a b c stor.operations.setValue(s); // sets the value of a b c } The advantage of this is that you can have SubjectB, SubjectC, ... all with different kind of members, and it only takes one line to make them available for the operations. Also, the subjects do not need to know how many operation there are and what these operations do with the members a,b,c. // Here is how to define the operations: struct Operations { void operateOn(T...)(ref T ts) { concatNames = { string name; foreach(ref t; ts) name = name ~ t.name; return name; }; setValue = (string val) => { foreach(ref t; ts) t.value = val; }; } string delegate() concatNames; void delegate(string s) setValue; }
Re: crash when using in struct constructor
On Wednesday, 18 July 2018 at 12:10:18 UTC, baz wrote: Specs are clear : it's a global so it's evaluated at compile time (https://dlang.org/spec/declaration.html#global_static_init) Example code should not compile. Indeed. Inside a function it does actually work. And ofcourse for class Test { List ls = 1; } it's going to make a static initializer which is then copied during construction of Test, so that's never going to work with the
Re: crash when using in struct constructor
On Monday, 16 July 2018 at 22:16:10 UTC, Adam D. Ruppe wrote: On Monday, 16 July 2018 at 22:08:34 UTC, Eric wrote: This makes the compiler crash. Is it illegal code? Yes, a struct can be moved at any time by the compiler which means pointers to it can be invalidated at random. Unless you always allocate it externally yourself... I know that. At the moment I disable the postblit and use an init(): class Test { List ls; this() { ls.init(); } } But I want to be able to write something less verbose like: class Test { List ls = 1; } And I was hoping a this(int) constructor would happen in place, not move things around.
Re: crash when using in struct constructor
Pasted slightly wrong code, last line should be: List ls = 2; Question still stands.
crash when using in struct constructor
This makes the compiler crash. Is it illegal code? struct List { private List* head; private List* tail; this(int x) { head = null; tail = // <-- crasher } } List2 ls = 2;
Re: indexing stuff during compile time
I am just a bit confused why I had to use tuple() while the doc Because of the enum, that code was full of errors :/ Got it now: auto groupIndex(Ts...)() { import std.meta; import std.algorithm.comparison : cmp, strcmp = cmp; enum Comp(N1, N2) = strcmp(N1.stringof, N2.stringof); alias sorted = staticSort!(Comp, Ts); return GroupId!sorted.id; }
Re: indexing stuff during compile time
Ok, solved. It appears you can sort tuples. I am just a bit confused why I had to use tuple() while the doc for staticSort states it works on AliasSeq. auto groupIndex(Ts...)() { import std.meta; enum Comp(alias N1, alias N2) = { __traits(identifier, typeof(N1)) < __traits(identifier, typeof(N2))}; enum t = tuple!(Ts); enum sorted = staticSort!(Comp, t); return GroupId!sorted.id; }
Re: indexing stuff during compile time
Forgot to mention that I also want groupIndex!(A,B) == groupIndex!(B,A) Which I wanted to do by sorting the names. If that requirement wasn't there it would be as simple as: auto groupIndex(Ts...)() { return GroupId!Ts.id; } size_t s_nextIdx=1; struct GroupId(Ts ...) { static size_t id; static this() { id = s_nextIdx++; } }
indexing stuff during compile time
I am trying to build a string->int dictionary at compile time. The ints are unique and must not be greater than the number of unique strings. So, they are sequential for each string that is not yet indexed. Example: size_t idx1 = nameToIndex!"blah"; // 0 size_t idx2 = nameToIndex!"blah2"; // 1 size_t idx3 = nameToIndex!"blah"; // 0 size_t idx4 = nameToIndex!"blah3"; // 2 So, you need to keep a static nextFreeIndex somewhere, but the problem is that you can't use static vars during compile time. Any ideas how to work around this? FWISW, here's some code. I am actually trying to map a combination of types to an index: struct A {} struct B {} void test() { writeln("a : " ~ groupIndex!(A).tostr); // 0 writeln("b : " ~ groupIndex!(B).tostr); // 1 writeln("ab : " ~ groupIndex!(A,B).tostr); // 2 } auto groupIndex(Ts...)() { enum n = groupName!Ts(); enum idx = nameToIdx(n); return idx; } // get or associate new index with the name size_t nameToIdx(string n) { static size_t[string] name2idx; static size_t s_nextIdx = 0; size_t* idx = n in name2idx; if (!idx) { name2idx[n] = s_nextIdx++; return s_nextIdx-1; } else return *idx; } // different attempt, but same problem: //size_t nameToIdx(string n)() { // mixin("static struct _"~n ~ "{ static int id;}"); // return mixin("_"~n~".id"); //} string groupName(Ts...)() { string n; foreach(t; Ts) { n = n ~ t.stringof; } return n; } string tostr(T)(T t) { import std.conv; return to!string(t); }
problem overloading functions with complex enum type
import std.stdio; enum A : int { a, b }; enum B : int { a, b }; enum AS : string[2] { a = ["1","2"], b = ["3","4"] }; enum BS : string[2] { a = ["5","6"], b = ["7","8"] }; void func(A a) { writeln("A"); } void func(B b) { writeln("B"); } void funcs(AS a) { writeln("AS"); } void funcs(BS b) { writeln("BS"); } void test() { func(A.a); // no compiler error funcs(AS.a); // compiler error: matches both funcs(AS) and funcs(BS) } void main(string[] args) { } In the above code, the function with the simple enum type argument can be overloaded, but the function with the complex enum type argument cannot be overloaded. Is this a bug? Thx. Eric
Re: Need advice on using DUB registry
On Sunday, 2 April 2017 at 04:14:56 UTC, rikki cattermole wrote: On 02/04/2017 2:37 AM, Eric wrote: I'm planning on some day putting a package in the DUB registry. My package is dependent on my "util" package which is a collection of stuff I use across all my projects. Does this mean I also have to put my util package in the DUB registry? Could I just make "util" a git sub module of the package I want to release? Dub can't use git submodules. In fact it doesn't know anything about git! So is the answer to my question, "yes, you need to put your util package in the DUB registry also?"
Need advice on using DUB registry
I'm planning on some day putting a package in the DUB registry. My package is dependent on my "util" package which is a collection of stuff I use across all my projects. Does this mean I also have to put my util package in the DUB registry? Could I just make "util" a git sub module of the package I want to release?
Re: Problem building DMD
On Saturday, 11 March 2017 at 17:54:55 UTC, ag0aep6g wrote: On 03/11/2017 06:41 PM, Eric wrote: I'm trying to build the master branch of DMD on redhat 7. I get the following errors: ddmd/root/newdelete.c:26:8: error: expected identifier or ‘(’ before string constant extern "C" ^ ddmd/root/newdelete.c:31:17: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘new’ void * operator new(size_t m_size) ^ ddmd/root/newdelete.c:36:15: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘delete’ void operator delete(void *p) Does anyone know what I am doing wrong? Looks like a C compiler is used instead of a C++ compiler. Despite the extension, dmd's *.c files are C++ code. Yes - I needed to install gcc-c++, not g++. That fixed everything.
Re: Problem building DMD
On Saturday, 11 March 2017 at 17:54:55 UTC, ag0aep6g wrote: Looks like a C compiler is used instead of a C++ compiler. Despite the extension, dmd's *.c files are C++ code. Yes, that's what I thought - redhat has gcc, but not g++. There must be a needed compile option...
Problem building DMD
I'm trying to build the master branch of DMD on redhat 7. I get the following errors: ddmd/root/newdelete.c:26:8: error: expected identifier or ‘(’ before string constant extern "C" ^ ddmd/root/newdelete.c:31:17: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘new’ void * operator new(size_t m_size) ^ ddmd/root/newdelete.c:36:15: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘delete’ void operator delete(void *p) Does anyone know what I am doing wrong?
Re: Is this template constraint a bug?
Yes, it's a bug. Please file an issue. Meanwhile try this workaround: class A(T) { static assert(is(T : A!T), "..."); } Bug report filed, and thanks for the workaround. -Eric
Is this template constraint a bug?
is(T : A!T) tells if T can automatically be converted to A!T. The last line below is doing just that, yet the template constraint does not work. class A(T) if (is(T : A!T)) { } // if (is(T : A!T)) gives this error: // Error: template instance x.A!(B) does not match //template declaration A(T) if (is(T : A!T)) //while looking for match for A!(B) class B : A!(B) { } void main(string[] args) { B b = new B(); A!B a = b; // compiles fine } -Eric
Re: Is this a bug?
On Friday, 15 April 2016 at 18:28:58 UTC, Eric wrote: line 6 can be fixed like this: "const I!(J) i = a;" Now if I can just figure out how to fix line 15... This works: 1 alias J = const C; 2 3 void main(string[] args) 4 { 5 J a = new C(); 6 const (I!(J)) i = a; 7 } 8 9 interface I(V) { } 10 11 class F(V) if (is(V : const(I!(V { } 12 13 class C : const (I!(J)) 14 { 15F!(J) m; 16 } 17 -Eric
Re: Is this a bug?
On Friday, 15 April 2016 at 18:22:02 UTC, Eric wrote: On Friday, 15 April 2016 at 17:43:59 UTC, ag0aep6g wrote: On 15.04.2016 19:13, Eric wrote: 1 alias J = const C; 2 3 void main(string[] args) 4 { 5 J a = new C(); 6 I!(J) i = a; 7 } 8 9 interface I(V) { } 10 11 class F(V) if (is(V : I!(V))) { } 12 13 class C : I!(J) 14 { 15 F!(J) m; 16 } Line 6 isn't accepted either. If you remove the constraint, the compiler complains about it. So it's just the next error in line. And really const C can't be converted to I!(const C) implicitly. The former is const, the latter is mutable => no go. Thanks. I see that now. Is there any way I can make the compiler understand that the interface is const? -Eric line 6 can be fixed like this: "const I!(J) i = a;" Now if I can just figure out how to fix line 15...
Re: Is this a bug?
On Friday, 15 April 2016 at 17:43:59 UTC, ag0aep6g wrote: On 15.04.2016 19:13, Eric wrote: 1 alias J = const C; 2 3 void main(string[] args) 4 { 5 J a = new C(); 6 I!(J) i = a; 7 } 8 9 interface I(V) { } 10 11 class F(V) if (is(V : I!(V))) { } 12 13 class C : I!(J) 14 { 15 F!(J) m; 16 } Line 6 isn't accepted either. If you remove the constraint, the compiler complains about it. So it's just the next error in line. And really const C can't be converted to I!(const C) implicitly. The former is const, the latter is mutable => no go. Thanks. I see that now. Is there any way I can make the compiler understand that the interface is const? -Eric
Is this a bug?
1 alias J = const C; 2 3 void main(string[] args) 4 { 5 J a = new C(); 6 I!(J) i = a; 7 } 8 9 interface I(V) { } 10 11 class F(V) if (is(V : I!(V))) { } 12 13 class C : I!(J) 14 { 15 F!(J) m; 16 } The above code gives the following compile error: Error: template instance F!(const(C)) does not match template declaration F(V) if (is(V : I!V)) on line 15. If I change line 1 to "alias J = C;" the code will compile. The problem seems to be the template constraint on line 11. I think the constraint says, "If V can be automatically converted to I!(V) then this template can be used". However, line 6 does not give an error, and it seems to be automaticaly converting J to I!(J). -Eric
Re: Internal compiler erorr
On Monday, 11 April 2016 at 00:55:44 UTC, Mike Parker wrote: On Sunday, 10 April 2016 at 17:19:14 UTC, Eric wrote: I am getting this error when I compile: Error: Internal Compiler Error: unsupported type const(string) No line number is given. Does anyone know what causes this? compiler version = v2.071.0 -Eric An ICE should always be considered a bug, no matter its cause. The thing to do here is to search bugzilla to see if your issue has already been reported and, if not, open a new one with a minimal reproducible test case. I don't see this specific error in bugzilla. Unfortunately I am getting this error in a large module that has "const string" all over. So I can't come up with a simple test case. The compiler does not seem to have a problem with just using a "const string" declaration.
Internal compiler erorr
I am getting this error when I compile: Error: Internal Compiler Error: unsupported type const(string) No line number is given. Does anyone know what causes this? compiler version = v2.071.0 -Eric
Re: Need help with DLANGUI
BTW, why do you need FreeImage to create image? Isn't it just possible inside dlangui? This is basically my question. Is there a drawing engine that can draw lines, circles, and shapes as well as single pixels? -Eric
opEquals unsafe? Please tell me this isnt true...
@safe class Y { } @safe class X { } @safe class Z { int x; this() { if (typeid(X) == typeid(Y)) x = 1; // Compile Error else x = 2; } } void main() { new Z; } // test.d(19): Error: safe function 'test.Z.this' // cannot call system function 'object.opEquals' Isn't this analagous to saying that the instanceof operator in java endangers the GC? Is it correct to replace '==' with 'is'? -Eric
Re: opEquals unsafe? Please tell me this isnt true...
On Tuesday, 25 November 2014 at 02:48:43 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: On Monday, November 24, 2014 22:12:08 Eric via Digitalmars-d-learn wrote: @safe class Y { } @safe class X { } @safe class Z { int x; this() { if (typeid(X) == typeid(Y)) x = 1; // Compile Error else x = 2; } } void main() { new Z; } // test.d(19): Error: safe function 'test.Z.this' // cannot call system function 'object.opEquals' Isn't this analagous to saying that the instanceof operator in java endangers the GC? Is it correct to replace '==' with 'is'? It's not that it's inherently unsafe. The problem is a combination of the fact that stuff in druntime that pre-existed @safe hasn't been made @safe yet (particularly, stuff in TypeInfo) and the fact that Object shouldn't even have opEquals, opCmp, toHash, or toString on it, because that restricts which attributes can be used ( https://issues.dlang.org/show_bug.cgi?id=9769 ), though I think that with @safe, we can work around that (unlike with const). However, for whatever reason, TypeInfo's opEquals function hasn't been marked with @safe or @trusted, so it's considered @system. That will need to be fixed, but I don't know if there are any implementation issues preventing it. It _looks_ like it could probably be marked @trusted, but I haven't actually dug into it in detail. In any case, you should be able to just mark the constructor as @trusted for now to work around the issue, and at some point in the future opEqualso or TypeInfo should be @trusted or @safe. - Jonathan M Davis Thanks for reminding me about @trusted. I'm finding it really hard to write robust classes in D due to all the problems with Object. -Eric
Re: overiding mutable methods in immutable classes
On Saturday, 22 November 2014 at 09:57:55 UTC, anonymous wrote: On Saturday, 22 November 2014 at 02:37:21 UTC, Eric wrote: I know I can make a class immutable, but the problem is I want to constrain a template parameter to only immutable types, and I want to use class types. template Foo(T : immutable Object) Accepts immutable(Object) and other immutable class types. Rejects non-immutable class types like Object and const(Object), and non-class types. Yes, but if I don't declare the class T as immutable, I don't think this constraint will work. -Eric
Re: How to pass static array to function not by value?
On Saturday, 22 November 2014 at 15:20:55 UTC, drug wrote: I tried to pass pointer to static array but it didn't work. try this: import std.stdio; void change(ref int[3] arr) { arr[1] = 6; } void main() { int[3] a = [1, 2, 3]; writeln(a = , a); change(a); writeln(a = , a); } -Eric
Re: How to pass static array to function not by value?
On Saturday, 22 November 2014 at 15:20:55 UTC, drug wrote: I tried to pass pointer to static array but it didn't work. Also, if you really want to be lame and actually use a pointer try this: import std.stdio; void change(int *arr) { arr[1] = 6; } void main() { int[3] a = [1, 2, 3]; writeln(a = , a); change(a.ptr); writeln(a = , a); } Maybe this is not so lame because change() can take any length of static array. -Eric
Re: How to pass static array to function not by value?
On Saturday, 22 November 2014 at 15:57:40 UTC, ketmar via Digitalmars-d-learn wrote: On Sat, 22 Nov 2014 15:45:51 + Eric via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Maybe this is not so lame because change() can take any length of static array. void change (int[] arr) { arr[1] = 42; } void main () { int[$] a = [1, 2, 3]; change(a); import std.stdio : writeln; writeln(a); // [1, 42, 3] } Okay, the pointer way really is lame then:) -Eric
Re: How to pass static array to function not by value?
On Saturday, 22 November 2014 at 16:07:25 UTC, drug wrote: On 22.11.2014 19:34, ketmar via Digitalmars-d-learn wrote: On Sat, 22 Nov 2014 18:20:44 +0400 drug via Digitalmars-d-learndigitalmars-d-learn@puremagic.com wrote: I tried to pass pointer to static array but it didn't work. i tried it right now and it works. if you really want to get some help, you'd better give us something to start with. i.e. your code, minified. D is great, but it still can't grant telepathic abilities to us. Sorry for inconvenience. http://dpaste.dzfl.pl/64ab69ae80d2 this causes stackoverflow because static array is big enough. I'd like to pass it not by value to avoid stack overflowing. Even if I use ref dmd pass it by value. Your problem is not the reference issue. D has a limit on how big static arrays can be in a function. You can make them bigger by declaring them globally, but I think even that has a limit. Try this: import std.stdio; enum A = 65536; enum B = 32; alias MyType = int[A][B]; void foo(ref MyType arr) { writeln(arr[3][3]); } MyType arr; void main() { writeln(arr[3][3] = , arr[3][3]); foo(arr); } -Eric
Re: overiding mutable methods in immutable classes
On Saturday, 22 November 2014 at 17:06:29 UTC, anonymous wrote: On Saturday, 22 November 2014 at 15:00:00 UTC, Eric wrote: Yes, but if I don't declare the class T as immutable, I don't think this constraint will work. You're mistaken. It works just fine. class X /* not immutable */ { private int x; this(int x) pure { this.x = x; } } template foo(T : immutable Object) { void foo(T thing) {} } void main() { foo(new immutable X(5)); } Yes, but this is what I really want: class X(T : immutable Object) { private T x; this(T x) pure { this.x = x; } } class Y { private int x; this(int x) pure { this.x = x; } } void main() { immutable(Y) y = new immutable Y(5); X!(Y) x = new X!(Y)(y); } // test.d(16): Error: template instance X!(Y) does not // match template declaration X(T : immutable(Object))
Re: overiding mutable methods in immutable classes
But I'm not sure if maybe I changed to much about it. My point is, that I think it's generally a good idea to be flexible when possible, and not make (im)mutability demands unless actually necessary. You may know the following, but I feel like there may be some confusion about it: Note that immutable(Y) is a different type from just Y. And declaring Y as `immutable class Y` wouldn't change a thing about that, as the immutable there only affects the members of Y. Objects of the bare type Y would still be (head) mutable. I thought I had my code working if instead of declaring class Y, I declared immutable class Y, but now it is not working for me. But finally this works: class X(T : immutable Object) { private T x; this(T x) pure { this.x = x; } } class Y { private const int x; this(int x) pure { this.x = x; } } void main() { immutable(Y) y = new immutable Y(4); X!(immutable(Y)) x = new X!(immutable(Y))(y); } Thanks for your help. -Eric
how to compare the type of a subclass
Suppose I have: module test; class X { } class Y : X { } Y y = new Y; X x = y; assert(is(typeof(x) == test.Y); // this assertion will fail assert(typeid(x).toString() == test.Y); // this assertion will pass Is there a way I can check the type of x without doing a string comparison? -Eric
Re: how to compare the type of a subclass
On Friday, 21 November 2014 at 22:25:32 UTC, anonymous wrote: On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote: Suppose I have: module test; class X { } class Y : X { } Y y = new Y; X x = y; assert(is(typeof(x) == test.Y); // this assertion will fail assert(typeid(x).toString() == test.Y); // this assertion will pass Is there a way I can check the type of x without doing a string comparison? -Eric assert(typeid(x) == typeid(Y)); Thanks. That works. I have't quite mastered the whole is/typeof/typeid thing yet.
Re: how to compare the type of a subclass
On Friday, 21 November 2014 at 22:52:54 UTC, H. S. Teoh via Digitalmars-d-learn wrote: On Fri, Nov 21, 2014 at 10:30:51PM +, Eric via Digitalmars-d-learn wrote: On Friday, 21 November 2014 at 22:25:32 UTC, anonymous wrote: On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote: [...] Is there a way I can check the type of x without doing a string comparison? -Eric assert(typeid(x) == typeid(Y)); Thanks. That works. I have't quite mastered the whole is/typeof/typeid thing yet. Binary `is` (i.e., `a is b`) is for comparing two references for equality. It returns true if two class reference point to the same object; false otherwise. But you probably already know this. Unary `is` (`is(...)`) is a monstrous maze of obscure syntax, that's best learned on a case-by-case basis. :-) But in this particular case, it's basically to provide a context for comparing types, since types aren't actual objects at runtime. So you can't write `if (typeof(a) == typeof(b))`, for example, because types aren't objects. Instead, you have to write `if (is(typeof(a) == typeof(b)))`. `typeof` is to extract types at compile-time. It returns the *declared* type of the variable (which may not be the most derived class if you assigned a derived object to a base class reference). `typeid` is to introspect types at runtime. It returns the most derived type of the object, even if the declared type is a base class. The returned type is an actual runtime object -- since at compile-time, the most derived type may not be known, so it's not representable as an actual type at compile-time. Instead, the D runtime returns a TypeInfo object that corresponds with the runtime type of the object. So you don't need to (and shouldn't) use `is(...)` when comparing typeid's. In short: To compare (declared) types at compile time: is(typeof(x) == typeof(y)) // x has the same (declared) type as y is(typeof(x) : typeof(y)) // x implicitly converts to y To compare (actual) types at runtime: typeid(x) == typeid(y) // x has the same (actual) time as y cast(B)x !is null // x is a derived class instance of base class B There are many other cases, of course, but these are the pertinent ones in the context of your original question. T Thanks, this helps a lot. -Eric
overiding mutable methods in immutable classes
immutable class X { private int x; this(int x) { this.x = x; } ... override size_t toHash(); // error: can't override mutable method } Since toHash() cannot be overridden in an immutable class, is there a work-around? In other words, immutable X x1 = new immutable X(5); immutable X x2 = new immutable X(5); I would like for x1.toHash() to equal x2.toHash(), but this is not the case because toHash() cannot be overridden. Note also that (x1 != x2) even though they should be equal (I think...) Is this a bug or a feature? -Eric
Re: overiding mutable methods in immutable classes
But think about if enforced immutability is really what you want. You don't need to mark the fields immutable to be able to construct immutable Xs. A `pure` constructor is handy, as it can construct both mutable and immutable objects. class X { private int x; this(int x) pure { this.x = x; } } void main() { auto m = new X(5); auto i = new immutable X(5); } Note also that (x1 != x2) even though they should be equal (I think...) By default, equality of objects is defined as identity. That is, an Object is equal only to itself. Override opEquals to change that. I know I can make a class immutable, but the problem is I want to constrain a template parameter to only immutable types, and I want to use class types. -Eric
Recursive template
Hi - I've never designed a recursive template before, but I think that would solve my problem. What I would like is someting like this: class X(V, K...) { // I want to declare a type based on K and V such // that for X!(V, int, string, double) the resulting // declaration would be: SomeType!(int, SomeType!(string, SomeType!(double, V))) var; // or put another way: SomeType!(K[0], SomeType!(K[1], SomeType(K[2], V))) var; } Can anyone give me some ideas on how to set up the declaration? Thanks, Eric
Re: Recursive template
Thanks! -Eric On Saturday, 15 November 2014 at 18:49:32 UTC, anonymous wrote: On Saturday, 15 November 2014 at 18:30:00 UTC, Eric wrote: Hi - I've never designed a recursive template before, but I think that would solve my problem. What I would like is someting like this: class X(V, K...) { // I want to declare a type based on K and V such // that for X!(V, int, string, double) the resulting // declaration would be: SomeType!(int, SomeType!(string, SomeType!(double, V))) var; // or put another way: SomeType!(K[0], SomeType!(K[1], SomeType(K[2], V))) var; } Can anyone give me some ideas on how to set up the declaration? Thanks, Eric It's pretty straight forward: struct SomeType(K, V) {} template X(V, K...) { static if(K.length == 1) alias X = SomeType!(K[0], V); else static if(K.length 1) alias X = SomeType!(K[0], X!(V, K[1 .. $])); else static assert(false); }
memory/array question
Suppose I have some memory allocated on the heap, and I have two pointers pointing to the beginning and end of a contiguous segment of that memory. Is there a way I can convert those two pointers to an array slice without actually copying anything within the segment? Thx, Eric
Re: memory/array question
On Thursday, 31 July 2014 at 19:43:00 UTC, bearophile wrote: Eric: Suppose I have some memory allocated on the heap, and I have two pointers pointing to the beginning and end of a contiguous segment of that memory. Is there a way I can convert those two pointers to an array slice without actually copying anything within the segment? Use something like this (but make sure the length is correct): auto mySlice = ptr1[0 .. ptr2 - ptr1]; Bye, bearophile Thanks. That really works. I timed doing auto mySlice = ptr1[0 .. ptr2 - ptr1]; 1,000,000 times versus auto mySlice = ptr1[0 .. ptr2 - ptr1].dup; 1,000,000 times and I am quite convinced the data is not being copied.
Re: memory/array question
On Thursday, 31 July 2014 at 20:59:46 UTC, Vlad Levenfeld wrote: On Thursday, 31 July 2014 at 20:43:11 UTC, bearophile wrote: Take a look at the asm! Bye, bearophile I use DMD and Dub, how do I view the asm? Actually I did't think to look at the asm, mainly because I've never bothered to do it before. But I was just reading Adam's book the other day, and I remember seeing this: objdump -d -M intel simpleOctal Not sure what the switches are for; the name of the program is simpleOctal. But the name of the utility is objdump. (on Linux). Not sure about Windoze. -Eric
Need help with basic functional programming
I have been writing several lexers and parsers. The grammars I need to parse are really complex, and consequently I didn't feel confident about the code quality, especially in the lexers. So I decided to jump on the functional progamming bandwagon to see if that would help. It definitely does help, there are fewer lines of code, and I feel better about the code quality. I started at the high level, and had the input buffer return a range of characters, and the lexer return a range of tokens. But when I got down to the lower levels of building up tokens, I ran into a problem: First I started with this which worked: private void getNumber(MCInputStreamRange buf) { while (!buf.empty()) { p++; buf.popFront(); if (buf.front() = '0' || buf.front() = '9') break; *p = buf.front(); } curTok.kind = Token_t.NUMBER; curTok.image = cast(string) cbuffer[0 .. (p - cbuffer.ptr)].dup; } I thought I could improve this like so: private void getNumber(MCInputStreamRange buf) { auto s = buf.until(a = '0' || a = '9'); curTok.kind = Token_t.NUMBER; curTok.image = to!string(s); } The problem is that until seems to not stop at the end of the number, and instead continues until the end of the buffer. Am I doing something wrong here? Also, what is the fastest way to convert a range to a string? Thanks, Eric
Re: Need help with basic functional programming
By the way, do you really mean to stop on '0' and '9'? Do you perhaps mean a '0' || a '9'? Yes, my bad...
Re: Need help with basic functional programming
On Tuesday, 22 July 2014 at 17:09:29 UTC, bearophile wrote: Eric: while (!buf.empty()) { p++; buf.popFront(); Those () can be omitted, if you mind the noise (but you can also keep them). if (buf.front() = '0' || buf.front() = '9') break; std.ascii.isDigit helps. curTok.image = cast(string) cbuffer[0 .. (p - cbuffer.ptr)].dup; If you want a string, then idup is better. Try to minimize the number of casts in your code. auto s = buf.until(a = '0' || a = '9'); Perhaps you need a ! after the until, or a !q{a = '0' || a = '9'}. Also, what is the fastest way to convert a range to a string? The text function is the simplest. Bye, bearophile Thanks! All very good suggestions... -Eric
Really nooB question - @property
There are a lot of discussions in the forums about how @property should or could be implemented. But I can't seem to find anything that explains why or when I should use @property with the current compiler. Can anyone explain why and when I should use the @property tag? Thx. Eric
Re: Really nooB question - @property
Use @property when you want a pseudo-variable or something that might be conceptually considered a property of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; This is basically what I suspected. But why write: @property int getValue() { return(value); } When you could just have a public field: int value; That lets you set and get the value without the parens anyways? thanks, Eric