Re: Struct immutable data and dict
On Tuesday, 4 September 2018 at 11:25:15 UTC, Alex wrote: On Tuesday, 4 September 2018 at 10:30:24 UTC, Timoses wrote: However, of course this also fails because randomly assigning the array elements will overwrite it. So the associative array seems like the better idea. However, not being able to INITIALIZE an assoc array element disallows its usage. Is there any solution, trick or workaround?? I tried two workarounds: 1) let the immutable away. 2) preallocate a full array of immutables. Then, misuse the assoc array by using the keys only. If the key is there, then, yield the appropriate element from the preallocated array. If not, yield the "elephant in Cairo". I also had this problem recently. I think aa.require() should allow to add immutables (feature request). Anyway, my workaround was along the lines of: final class AA(Key, Value) { Value[] _storage; size_t[Key] _aa; void opIndexAssign(Value value, Key key) { if (key !in _aa) { _storage ~= value; _aa[key] = _storage.length - 1; } } Value opIndex(Key key) { if (auto index = key in _aa) return _storage[*index]; throw new Exception("no key"); } } immutable struct S { int num; } void main() { import std.stdio : writeln; auto aa = new AA!(string, S); aa["one"] = S(1); aa["two"] = S(2); writeln(aa["one"]); writeln(aa["two"]); }
Re: extern __gshared const(char)* symbol fails
On Friday, 31 August 2018 at 06:20:09 UTC, James Blachly wrote: Hi all, I am linking to a C library which defines a symbol, const char seq_nt16_str[] = "=ACMGRSVTWYHKDBN"; In the C sources, this is an array of 16 bytes (17 I guess, because it is written as a string). In the C headers, it is listed as extern const char seq_nt16_str[]; When linking to this library from another C program, I am able to treat seq_nt16_str as any other array, and being defined as [] fundamentally it is a pointer. No. This is a misconception. Fundamentally, it's an array. When linking to this library from D, I have declared it as: extern __gshared const(char)* seq_nt16_str; ***But this segfaults when I treat it like an array (e.g. by accessing members by index).*** Because I know the length, I can instead declare: extern __gshared const(char)[16] seq_nt16_str; My question is: Why can I not treat it opaquely and use it declared as char* ? Does this have anything to do with it being a global stored in the static data segment? For the same reason you can't do it in C. --- main.c --- #include extern const char* array; /* then try array[] */ int main(void) { printf("%.5s\n", array); return 0; } --- lib.c --- const char array[] = "hello world"; # gcc -o main main.c lib.c # ./main Segmentation fault You need to declare your extern array as array in D and also in C, so that the compiler would know what that is (an array, not a pointer). In many situations C compiler would silently convert an array into a pointer (when it already knows its dealing with array), but it won't convert a pointer into an array.
Re: GC and void[N] in struct
On Monday, 6 August 2018 at 18:22:24 UTC, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. If the definition of S look like this: struct S{ void[N] data_; uint kind; } then program run fine with GC.enable. Whats the problem? Something with alignment? Probably. Try something like: struct S { uint kind; align((void *).alignof) void[N] data_; } And see if it solves the problem.
Re: Compile-time variables
On Friday, 6 April 2018 at 13:10:23 UTC, Kayomn wrote: ID tags are unique and spsecific to the class type. There shouldn't be more than one type ID assigned to one class type. The idea behind what it is I am doing is I am implementing a solution to getting a type index, similar to std.variant.Variant.type(). The way that I implemented this in C++ is like so: inline unsigned int getNodeTypeID() { static unsigned int lastID = 0; return lastID++; } template inline unsigned int getNodeTypeID() { static unsigned int typeID = getNodeTypeID(); return typeID; } In this C++ example I am exploiting the fact that templates are generated at compile-time to execute getNodeTypeID for each new type instance generated. After initial type generation, whenever they are called at runtime they were return the ID assigned to that function template instance that was generated at compile-time. It's pretty simple, and to be honest I'm surprised this has been causing me such a headache implementing it in D. That's because the C++ code doesn't do what you think it does. Apparently you think that getNodeID() is executed at compile time. This is not the case, which you can verify by adding "constexpr" to it: $ g++ -std=c++14 -Wall -Wextra -c -o example example.cpp main.cpp: In function ‘constexpr unsigned int getNodeTypeID()’: main.cpp:2:25: error: ‘lastID’ declared ‘static’ in ‘constexpr’ function static unsigned int lastID = 0; In fact, you're "exploiting" the fact that static variables in C++ can be initialized at runtime (which is probably not what you want). The equivalent D code is: uint newID() { static uint lastID; return lastID++; } uint getNodeID(T)() { static bool inited; static uint id; if (!inited) { id = newID(); inited = true; } return id; } (yes, C++ does insert some hidden bool that tells it whether the variable was initialized or not). Naturally, you can't use that for constructing switches or other compile time constructs.
Re: #import mapi.h
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin Tschierschke wrote: Is there an step by step introduction how to convert a C header of an external lib into the right extern(C){} block? A blog post or tutorial, or chapter in a D book? (I have those from Packt Publishing) (Especially I am trying to get this used with D: Montetdb C-API https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/MAPI With: https://github.com/snaga/monetdb/blob/master/clients/mapilib/mapi.h) The page: https://dlang.org/spec/interfaceToC.html is known, but not detailed enough for me. The easiest thing to do is to write a wrapper in C. The wrapper will include all necessary headers and provide some easy to use functions that you can call from D. Of course, you'll need to use a C compiler to compile it. Anyway, this header looks very straightforwar, no particular tricks with the preprocessor. It should be something like this (untested, obviously): import core.stdc.stdio : FILE; enum { MAPI_AUTO = 0, /* automatic type detection */ MAPI_TINY = 1, MAPI_UTINY = 2, MAPI_SHORT = 3, MAPI_USHORT= 4, MAPI_INT = 5, MAPI_UINT = 6, MAPI_LONG = 7, MAPI_ULONG = 8, MAPI_LONGLONG = 9, MAPI_ULONGLONG = 10, MAPI_CHAR = 11, MAPI_VARCHAR = 12, MAPI_FLOAT = 13, MAPI_DOUBLE= 14, MAPI_DATE = 15, MAPI_TIME = 16, MAPI_DATETIME = 17, MAPI_NUMERIC = 18, } enum int PLACEHOLDER = '?'; enum { MAPI_SEEK_SET = 0, MAPI_SEEK_CUR = 1, MAPI_SEEK_END = 2, } enum { MAPI_TRACE = 1, MAPI_TRACE_LANG = 2, } alias MapiMsg = int; enum { MOK = 0, MERROR = -1, MTIMEOUT= -2, MMORE = -3, MSERVER = -4, } enum { LANG_MAL= 0, LANG_SQL= 2, LANG_JAQL = 3, } /* prompts for MAPI protocol */ enum int PROMPTBEG = '\001'; /* start prompt bracket */ /* prompt: ready for new query */ const(char)* PROMPT1 = "\001\001\n".ptr; /* prompt: more data needed */ const(char)* PROMTP2 = "\001\002\n".ptr; /* * The table field information is extracted from the table headers * obtained from the server. This list may be extended in the future. * The type of both the 'param' and 'binding' * variables refer to their underlying C-type. They are used for * automatic type coercion between back-end and application. */ struct MapiStruct; alias Mapi = MapiStruct*; /* this definition is a straight copy from sql/include/sql_query.h */ enum { Q_PARSE = 0, Q_TABLE = 1, Q_UPDATE= 2, Q_SCHEMA= 3, Q_TRANS = 4, Q_PREPARE = 5, Q_BLOCK = 6, } struct MapiStatement; alias MapiHdl = MapiStatement*; alias mapi_uint64 = ulong; alias mapi_int64 = long; /* three structures used for communicating date/time information */ /* these structs are deliberately compatible with the ODBC versions SQL_DATE_STRUCT, SQL_TIME_STRUCT, and SQL_TIMESTAMP_STRUCT */ /* used by MAPI_DATE */ struct MapiDate { short year; ushort month; ushort day; } /* used by MAPI_TIME */ struct MapiTime { ushort hour; ushort minute; ushort second; } /* used by MAPI_DATETIME */ struct MapiDateTime { short year; ushort month; ushort day; ushort hour; ushort minute; ushort second; uint fraction; /* in 1000 millionths of a second (10e-9) */ } /* connection-oriented functions */ extern (C) { Mapi mapi_mapi(const char *host, int port, const char *username, const char *password, const char *lang, const char *dbname); // and so on... }
Re: Is it possible to specify the address returned by the address of operator?
On Wednesday, 27 September 2017 at 20:24:24 UTC, DreadKyller wrote: The attitude of "some people use this feature incorrectly, so let's ban it's use entirely" is honestly ridiculous to me, but oh well, that's apparently the modern philosophy. Not even modern, see Java :) ("I left out operator overloading as a fairly personal choice because I had seen too many people abuse it in C++." - James Gosling)
Re: Is it possible to specify the address returned by the address of operator?
On Wednesday, 27 September 2017 at 16:35:54 UTC, DreadKyller wrote: Been using D for a couple years now, however one problem I've had, more so recently since I've been dealing a lot with OpenGL is related to pointers. I have a matrix object to aid with the matrix math required for working with 3D transforms. However OpenGL (I'm using DerelictGL3 bindings) requires pointers to the data. I am currently doing the following: Matrix!float ortho(float l, float r, float b, float t, float f, float n = -1) { Matrix!float oMat = identity(); // Get default Identity Matrix oMat[0,0] = 2 / (r - l); oMat[1,1] = 2 / (t - b); oMat[2,2] = -2 / (f - n); oMat[3] = [-(r+l)/(r-l), -(t+b)/(t-b), -(f+n)/(f-n), 1]; return oMat; } And then to use with OpenGL (passing as uniform into shader): glUniformMatrix4fv(transform_uniform, 1, GL_FALSE, matrix.addr ); where addr is a property that returns the address of the first item in the Matrix's internal data. I know I can also use [0][0] My question is about overloading, several operators can be overloaded in D, one of the ones that can't apparently is the address of operator (). My question is have I simply missed it or does it actually not exist, and if it's not overloadable, is there any reason why this was decided? Because there's been numerous times that it'd be useful to me, just recently with how much I use the operator because of OpenGL I decided to ask. & is not overloadable, presumably because some people were annoyed by abuse of operator overloading in C++. The reason is to improve readability (of other people's code). Just rename matrix.addr to matrix.ptr... like in arrays: https://dlang.org/spec/arrays.html#array-properties That would be clearer (opinion), since the reader of your code can assume that matrix.ptr does the same thing with your matrix as array.ptr does with arrays. OTOH, overloading to do something different from built in seems like a pointless obfuscation to me.
Re: [OT] Converting booleans to numbers
On Wednesday, 20 September 2017 at 19:25:58 UTC, Timon Gehr wrote: Actually, it is useful enough to have a Wikipedia page: https://en.wikipedia.org/wiki/Iverson_bracket Mmmm... "The notation was originally introduced by Kenneth E. Iverson in his programming language APL". APL... yeah :) Programmers didn't like it, did they. Anyway, that seems to be explicit notation, analogous to (cond ? 1 : 0). Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { if (a<0 || a >= data.length) return; if (b<0 || b >= data[a].length) return; if (data[a][b] == c) return; data[a][b] = c; foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } } dfs(i, j); } I don't agree it's a good use. Actually, that seems quite obfuscated to me. Consider: foreach (point; [[1, 0], [-1, 0], [0, 1], [0, -1]]) { dfs(a + point[0], b + point[1]); } Finds some random 10 programmers and ask them what's easier to understand... Also, in my experience (in C and C++) it is extremely rare for programmers to use booleans in arithmetic. So even if in some situation you would have to replace this thing with more verbose (i == 0 ? 1 : 0), it's no big deal. OTOH, booleans being numbers is a source of some bugs (just like other cases of weak typing). Not a ton of bugs, but the utility of implicit conversion to numbers is so unnoticeable that I'm sure it's just not worth it.
Re: What the hell is wrong with D?
On Wednesday, 20 September 2017 at 02:16:16 UTC, EntangledQuanta wrote: Your an idiot, I know about how operator precedence works far more than you do. Wanna bet? how much? Your house? your wife? Your life? It's about doing things correctly, you seem to fail to understand, not your fault, can't expect a turd to understand logic. Ok, you win. I see now that you're very smart :)
Re: What the hell is wrong with D?
On Tuesday, 19 September 2017 at 17:40:20 UTC, EntangledQuanta wrote: Yeah, that is really logical! No wonder D sucks and has so many bugs! Always wants me to be explicit about the stuff it won't figure out but it implicitly does stuff that makes no sense. The whole point of the parenthesis is to inform the compiler about the expression to use. Not use everything to the left of ?. There are two issues there; operator precedence and booleans (_win[0] == '@') being a valid operands to +. If someone is too stupid to learn how precedence works, they should consider a different career instead of blaming others. OTOH, booleans converting to numbers is a very questionable feature. I certainly have never seen any good use for it. This is just an unfortunate legacy of C, which didn't even have booleans for a long time.
Re: extern(C) enum
On Sunday, 17 September 2017 at 17:06:10 UTC, bitwise wrote: I don't really see a way to deal with this aside from branching the entire library and inserting something like 'FT_SIZE_REQUEST_TYPE__FORCE_INT = 0x' into every enum incase the devs used it in a struct. Just put the burden on the users then. It's implementation defined, so they are in position to figure it out... for example, gcc: "Normally, the type is unsigned int if there are no negative values in the enumeration, otherwise int. If -fshort-enums is specified, then if there are negative values it is the first of signed char, short and int that can represent all the values, otherwise it is the first of unsigned char, unsigned short and unsigned int that can represent all the values. On some targets, -fshort-enums is the default; this is determined by the ABI." https://gcc.gnu.org/onlinedocs/gcc-6.4.0/gcc/Structures-unions-enumerations-and-bit-fields-implementation.html#Structures-unions-enumerations-and-bit-fields-implementation msvc++: "A variable declared as enum is an int." https://docs.microsoft.com/en-us/cpp/c-language/enum-type It's probably pretty safe to assume it's an int; people who play tricks with "-fshort-enums" deserve what's coming to them :)
Re: extern(C) enum
On Saturday, 16 September 2017 at 03:06:24 UTC, Timothy Foster wrote: You are correct, however 6.7.2.2 "Enumeration specifiers" states: "Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration." I believe that means that if you have the following: enum ABC { A, B, C } Then A, B, and C are by themselves ints, but the enum type ABC can be a char if the compiler decides that's what it wants it to be. Oops, you're right. Then the situation must be the same as in C++? If enum ABC is by itself a parameter of a function, the argument will be int (and if it weren't, it would be promoted to int anyway), but if the enum is a part of a structure, then it can be anything... At least, if enumerators themselves are ints, the enum type probably won't be larger than an int... small consolation :)
Re: extern(C) enum
On Friday, 15 September 2017 at 19:21:02 UTC, Timothy Foster wrote: I believe C enum size is implementation defined. A C compiler can pick the underlying type (1, 2, or 4 bytes, signed or unsigned) that fits the values in the enum. No, at least, not C99. See 6.4.4.3: "An identifier declared as an enumeration constant has type int". You must be thinking about C++.
Re: Inout table
On Wednesday, 13 September 2017 at 17:39:29 UTC, Steven Schveighoffer wrote: Correct. So given a function: inout(int*) foo(inout(int*)p1, inout(int*)p2) The table shows what inout is resolved as when calling the function. If you consider the column the mutability of p1, and the row the mutability of p2, then the value in the table represents the mutability of the return value. So for instance: int *m; const int *c; immutable int *i; inout int *w; auto v1 = foo(m, m); // typeof(v1) is int* auto v2 = foo(m, c); // typeof(v2) is const(int*) auto v3 = foo(i, m); // typeof(v3) is const(int*) auto v4 = foo(w, w); // typeof(v4) is inout(int*) auto v5 = foo(w, i); // typeof(v5) is inout(const(int *)) etc. Thank you. Now it is clear to me. The source of my confusion was that, say, given a function: inout(int*) foo(inout(int*) p) as per table, combining (mutable) argument int* m with parameter inout(int*) p would produce parameter type const(int*). But now I see that the table deduces the common type of all parameters, not the common type of a parameter and its argument (the documentation is kind of hard to parse: "If such a match occurs, the inout is considered the common qualifier of the matched qualifiers...").
Re: Adding empty static this() causes exception
On Tuesday, 12 September 2017 at 19:59:52 UTC, Joseph wrote: The compiler shouldn't arbitrarily force one to make arbitrary decisions that waste time and money. You might want to educate yourself about arbitrary decisions that waste time and money: https://isocpp.org/wiki/faq/ctors#static-init-order My solution was to turn those static this's in to functions and simply call them at at the start of main(). Same effect yet doesn't crash. The compiler should only run the static this's once per module load anyways, right? If it is such a problem then some way around it should be included: @force static this() { } ? There is a way, turn static this's into functions and simply call them at the start of main(). The compiler shouldn't make assumptions about the code I write and always choose the worse case, it becomes an unfriendly relationship at that point. If you want C++, you know where to find it, although I wouldn't exactly call it "friendly".
Re: Override with function overloads
On Monday, 11 September 2017 at 18:15:36 UTC, jmh530 wrote: An interesting example. I'm not sure overriding is the issue so most as what is in the overload set. I think foo(int) is not part of the overload set yet. The compiler is able to cast the long to int and then call the one in class B without needing to look to the base class. The behavior is also the same if you use alias this (below). It's just an issue (not really an issue :) of name lookup. First, compiler searches for names, that is, for something called "foo". Then, when it finds "foo" (or several in the same scope), it does overload resolution on them. If those are wrong names, it just reports an error, for example: class A { final void foo(int) { writeln("A.foo(int)"); } } class B : A { string foo = "bar"; } void main() { B b = new B; int n = 1; b.foo(n); } While looking for names, it doesn't even care if "foo" is a function or whatever. Would there be any problems with final functions of inherited or alias this types being included in the overload set? I don't know, maybe don't use alias this :) IMO, it's a really dubious feature...
Re: Override with function overloads
On Monday, 11 September 2017 at 15:13:25 UTC, jmh530 wrote: I suppose my issue is that final should prevent function hijacking because I shouldn't be allowed to override string bar(double d) anyway. It shouldn't be a worry. It has nothing to do with overriding. Consider: import std.stdio; class A { final void foo(int) { writeln("A.foo(int)"); } } class B : A { final void foo(long) { writeln("B.foo(long)"); } } void main() { B b = new B; int n = 1; b.foo(n); } That prints "B.foo(long)", even though foo() was called with an int (tbh, I'd say it's hijacking and shouldn't even compile, like it doesn't with virtual functions - try to remove finals). The compiler starts looking from B, finds name "foo" and tries that without looking any futher into base classes. If you want that, you can do it manually: class Foo2 : Foo { alias bar = super.bar; // bring Foo.bars in scope override void bar(int x) { } }
Inout table
There is this little table in https://dlang.org/spec/function.html#inout-functions: Common qualifier of the two type qualifiers mutable const immutable inout inout const mutable (= m) m c c c c const (= c)c c c c c immutable (= i)c c i wcwc inout (= w)c c wcw wc inout const (= wc) c c wcwcwc I don't understand what it is trying to say. What is it that is calculated here? The qualifier for the return value? And what's an "inout const"?
Re: ushort calls byte overload
On Tuesday, 30 May 2017 at 21:16:26 UTC, Oleg B wrote: Hello. I have this code import std.stdio; void foo(byte a) { writeln(typeof(a).stringof); } void foo(short a) { writeln(typeof(a).stringof); } void foo(int a) { writeln(typeof(a).stringof); } void main() { foo(0); // int, and byte if not define foo(int) foo(ushort(0)); // byte (unexpected for me) foo(cast(ushort)0); // byte (unexpected too) foo(cast(short)0); // short foo(short(0)); // short ushort x = 0; foo(x); // short } Is this a bug or I don't understand something? Hm, interesting. I think what you're seeing here is an unexpected application of value range propagation: http://www.drdobbs.com/tools/value-range-propagation/229300211 None of these functions can be called with ushort without conversions. As the manual says: The function with the best match is selected. The levels of matching are: no match match with implicit conversions match with conversion to const exact match All of your functions require some implicit conversions (the ushort here can be converted to byte because of value range propagation). So the next rule is in effect - the functions are ordered and the "most specialized" is chozen. The byte function is the most specialized, so it is called. Or something like that :) but if compiler find one-to-one correspondence it don't make assumptions, like here? Apparently then it just chooses the function that is "exact match".
Re: Out of memory error (even when using destroy())
On Saturday, 27 May 2017 at 17:57:03 UTC, Mike B Johnson wrote: And what if one isn't interfacing to C? All pointers should be known. Apparently some people are (were?) working on semi-precise GC: https://github.com/dlang/druntime/pull/1603 That still scans the stack conservatively, though. Therefor, in a true D program(no outsourcing) with no pointers used, the GC should never have to scan anything. All realistic programs (in any language) use a lot of pointers - for example, all slices in D have embedded pointers (slice.ptr), references are pointers, classes are references, etc. It seems the GC can be smarter than it is instead of just making blanket assumptions about the entire program(which rarely hold), which is generally always a poor choice when it comes to performance... If you only have compile time information, making blanket assumptions is inevitable - after all, compiler can't understand how a nontrivial program actually works. The alternative is doing more work at runtime (marking pointers that changed since previous collection, etc), which is also not good for performance. Who knows, some pointer externally might be peeping in on our hello world program. Of course, there is a pointer :) void main() { import std.stdio; writeln("hello world".ptr); }
Re: The syntax of sort and templates
On Friday, 26 May 2017 at 11:27:19 UTC, zakk wrote: I have a followup question: my background is C and in Wolfram Mathematica, so my knowledge of templates is limited to trivial examples in C++... It seems to me that when programming in D templates are something more powerful Even in C++ templates can work with more than just types (e.g., C++ templates accept other templates, numbers and pointers). And of course, D templates are even more powerful than in C++, so they can work with even more things: TemplateTypeParameter TemplateValueParameter TemplateAliasParameter TemplateSequenceParameter TemplateThisParameter (you can read about it here: https://dlang.org/spec/template.html#TemplateParameters)
Re: Why does this compile (method in class without return type)
On Wednesday, 3 May 2017 at 07:34:03 UTC, Daniel Kozák wrote: print in A is template: What :) How does it interact with 'final'?
Re: Why does this compile (method in class without return type)
On Wednesday, 3 May 2017 at 06:54:15 UTC, nkm1 wrote: final method type inference stuff Jacob and Jonathan - thank you, this is clear to me now. Hopefully it will get fixed at some point.
Why does this compile (method in class without return type)
Consider: import std.stdio; class A { final print() { writeln(this); } // no return type } class B : A { final void print() { writeln(this); } } void main() { auto b = new B; b.print(); A a1 = b; a1.print(); A a2 = new A; a2.print(); } That compiles: $ dmd -de -w -g ./main.d $ main main.B main.B main.A with dmd 2.074 on linux: $ dmd --version DMD64 D Compiler v2.074.0 Copyright (c) 1999-2017 by Digital Mars written by Walter Bright Is that a bug? (in the compiler). I'm learning D, and I'm half way through Andrei's book; I also read the documentation (on D's website) and I think that shouldn't compile?