Re: char[] == null
On Thursday, 19 November 2015 at 15:36:44 UTC, Steven Schveighoffer wrote: On 11/19/15 3:30 AM, Jonathan M Davis via Digitalmars-d-learn wrote: On Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote: On 18.11.2015 22:02, rsw0x wrote: slices aren't arrays http://dlang.org/d-array-article.html The language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that. [1] http://dlang.org/arrays.html Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all. It was not a mistake :) It's how I still think of it. The spec is confusing, and my terminology, IMO, is a much more consistent (and accurate) way to think of it. -Steve Why formal definition of dynamic array caused confusion and is inconsistent? It is well consistent with static array and other aggregate types notions. Consider this: int *x = new int; // this is 'int type' ans it is 'dynamic' int y; int *a = // and this is not 'int type' The problem is treating chunk of heap memory as some kind of type (dynamic in this case). Type of object determines an interface of interacting with object while storage determines memory location and possibly duration of lifetime. It is possible to have object of any type to be allocated on different storages - for example, slice does not necessarily points to dynamic array (in your terms). C and C++ established a long tradition of such standard notions as object, lifetime, storage and type. From system language perspective calling memory a type (in other words, type of object depends on where it was allocated) does not make much sense.
Re: Preventing implicit conversion
On Wednesday, 4 November 2015 at 21:22:04 UTC, ixid wrote: On Wednesday, 4 November 2015 at 19:09:42 UTC, Maxim Fomin wrote: On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote: Is there an elegant way of avoiding implicit conversion to int when you're using shorter types? Only with library solution. Implicit conversions are built into language. Doesn't that seem rather limiting and unnecessary? Well, indeed it often produces confusion (this is inherited from C for compatibility purpose).
Re: Preventing implicit conversion
On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote: Is there an elegant way of avoiding implicit conversion to int when you're using shorter types? Only with library solution. Implicit conversions are built into language.
Re: Overloading an imported function
On Wednesday, 21 October 2015 at 12:05:27 UTC, Shriramana Sharma wrote: import std.math; real round(real val, int prec) { real pow = 10 ^^ prec; return round(val * pow) / pow; } Trying to compile this I get: foo.d(5): Error: function foo.round (real val, int prec) is not callable using argument types (real) When I've imported std.math which contains round(real), why is the compiler complaining about not being able to call the overload function defined in *this* module? I don't see anything in http://dlang.org/module.html that says I cannot define an overload of an imported function. Did I miss something? My guess is that .round shadows math.round. But you can get desired behavior by moving declaration of math.round inside scope of .round. This compiles: real round(real val, int prec) { import std.math; real pow = 10 ^^ prec; return round(val * pow) / pow; }
Re: Array of subclasses
On Thursday, 22 October 2015 at 13:29:06 UTC, DarkRiDDeR wrote: I don't need the base class data. How to create a array of subclasses objects with the derived data members? The language is implemented in this way. You have already have the answer: writeln(Core.users.name) Out: USERS
Re: Array of subclasses
On Thursday, 22 October 2015 at 11:02:05 UTC, DarkRiDDeR wrote: This variant works strangely. Example: abstract class Addon { public string name = "0"; } class Users: Addon { override { public string name = "USERS"; } } static final class Core { static: public Addon[] activated; public Users users; public void activate() { users = new Users; activated = [new Users, new Users]; } } Core.activate(); writeln(Core.users.name ~ "\n" ~ Core.activated[1].name); Out: USERS 0 First of all, the code does not compile with override. It is impossible to override a data. Override should be removed. The reason it works this way is that the first access is to base class data while the second is to the derived data member.
Re: Implicit conversion rules
On Wednesday, 21 October 2015 at 19:49:35 UTC, Ali Çehreli wrote: On 10/21/2015 12:37 PM, Sigg wrote: > cause at least few more "fun" side effects. One of those side effects would be function calls binding silently to another overload: void foo(bool){/* ... */} void foo(int) {/* ... */} auto a = 0; // If the type were deduced by the value, foo(a); // then this would be a call to foo(bool)... // until someone changed the value to 2. :) Ali Actually 'a' is deduced to be int, so int version is called (as expected?). See my example above for the VRO overload issue.
Re: Implicit conversion rules
On Wednesday, 21 October 2015 at 22:49:16 UTC, Marco Leise wrote: Am Wed, 21 Oct 2015 12:49:35 -0700 schrieb Ali Çehreli: On 10/21/2015 12:37 PM, Sigg wrote: > cause at least few more "fun" side effects. One of those side effects would be function calls binding silently to another overload: void foo(bool){/* ... */} void foo(int) {/* ... */} auto a = 0; // If the type were deduced by the value, foo(a); // then this would be a call to foo(bool)... // until someone changed the value to 2. :) Ali God forbid anyone implement such nonsense into D ! That would be the last thing we need that we cannot rely on the overload resolution any more. It would be as if making 'a' const would change the overload resolution when none of the overloads deal with constness... AFAIK it was implemented long time ago and discussed last time couple of years ago with example similar to Ali's. void foo(bool) void foo(int) foo(0); // bool foo(1); // bool foo(2); // int
Re: how come is this legal? 'void fun(int){ }' ?
On Sunday, 14 June 2015 at 01:20:39 UTC, Timothee Cour wrote: I understand this is legal for declaration wo definition (void fun(int);) but why allow this: void test(int){} ? Actually it is void test(int _param_0) { } You can test by compiling void test(int) { _param_0 = 0; } Nameless parameters are simulated by providing internal symbol as above.
Re: Cannot Qualify Variadic Functions with Lazy Arguments as nothrow
On Thursday, 14 May 2015 at 09:53:20 UTC, Per Nordlöw wrote: At https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L43 I've implemented a function either() with behaviour similar to the `or` function/operator in dynamic languages such as Python and Lisp. I'm almost satisified with it except that the lazy evaluation at https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L45 cannot be made nothrow. If I qualify the function as nothrow DMD complains as algorithm_ex.d(45,16): Error: 'a' is not nothrow algorithm_ex.d(46,29): Error: '_param_1' is not nothrow I don't see a reason why any of these two cases should throw. Lazy argument is essentially delegate/function. Currently there is no way to mark it as nothrow. The same problem occurs if I make the implementation use only one function and check the recursion termination case with `static if (bs.length == 1)` instead. Is there a workaround for this? One way to address is to use delegate explicitly. int foo(lazy int a) //nothrow { return a; } int bar(int delegate() nothrow dg) nothrow { return dg(); } void main() nothrow { int a; bar(()=a); }
Re: Can't modify this
On Saturday, 28 June 2014 at 20:40:21 UTC, Ary Borenszweig wrote: This doesn't work: class Foo { this() { this = new Foo; } } Error: Cannot modify 'this' However you can do this: class Foo { this() { auto p = this; *p = new Foo(); } } It even changes the value of this! Should that compile? I mean, it's the same as modifying 'this'... D language was not aimed toward preventing any attepmt to circumvent some hypothetical limitations (it does not even cope with things which it should definetely prevent). There are holes much - much worse. And changing value of this parameter is not a problem anyway, since it is possible to have typeid(this) != typeid of type of current method which is bigger problem than pointing to different value of same type.
Re: Struct constructor, opCall mess.
On Monday, 24 February 2014 at 14:14:43 UTC, Tobias Pankrath wrote: On Monday, 24 February 2014 at 13:56:01 UTC, Remo wrote: Hi, right now I am truing to figure out how the constructors behave in D2. Question 1: why it is not possible to create custom ctor for struct? The design of D relies on the fact that every type has a T.init property that is known to the compiler and used when in C++ the default ctor would get called. In constructors you can rely on (this == T.init), for example. You need to pick one T.init or default constructors and D picked T.init. The design of D relies on Andrei opinion. He is indeed convinced that default constructors are impossible. However, you can write default constructor right now like: struct S { Type t; this(int) { t = whather_is_callable_in_CTFE(); } } enum E : S { A = S(0) } void main() { E e; assert (e.t == whather_is_callable_in_CTFE()); } Since compiler does this, it can also accept straight syntax and semantic: struct S { Type t; this() // proxibited default constructor now { t = whather_is_callable_in_CTFE(); } } What D really lacks is ability to call function in runtime after struct instance creation like: struct S { @runtime this() {} ~this(){} } lowering to: S s; s.__runtime_ctor(); However, since compiler does this all over the place (postblits, copy constructors, destructors, etc.) There is no conceptual difference between having: S s s.__runtime_ctor(); and S s; s.__dtor(); In other words, there is no objective necessity not to have compile time and runtime default struct constructors since compiler already heavily does conceptually and technically similar things.
Re: Struct constructor, opCall mess.
On Monday, 24 February 2014 at 19:41:57 UTC, Remo wrote: For Vector example this works pretty well this way. But my main problem is more complicated. extern(C) int init(ref CWrapper p); extern(C) void free(ref CWrapper p); struct CWrapper { //some data that must be the same at C side. Data m_data; this() { init(this); } ~this() { free(this); } } How to do something like this in D ? Using class appears for me to be wrong direction. 1) Please comment after previous speaker, not before. You can't avoid default struct constructor problem if functions which you call in constructors are not at least CTFEable because you would need to call them if you wish to define default struct constructor. Since this is not your case, you can do: 2) You can use static OpCall, Voldemort type or alias this. In case of alias this it looks like: extern(C) int printf(const char*, ...); extern(C) int init(CWrapper* p) { printf(init\n); return 0; } extern(C) void d_free(CWrapper* p) { printf(free\n); } struct Data { void do_something(){} } struct CWrapper { //some data that must be the same at C side. Data m_data; bool m_init; /*this(int) { init(this); }*/ ~this() { d_free(this); } Data get() { if (!m_init) init(this); return m_data; } alias get this; } void main() { CWrapper cw; cw.do_something(); } In case of Voldermort struct some struct is defined inside function, so the only way (in theory) to create an instance is to call that function. It is inconviniet but guarantees that you will not have non initialzed structs (in theory). extern(C) int printf(const char*,...); auto make_struct() { struct Data{} struct CWrapper { extern(C) int m_init(CWrapper* p){ return 0; } extern(C) void m_free(CWrapper* p){ printf(free\n);} //some data that must be the same at C side. Data m_data; this(int) { m_init(this); } ~this() { m_free(this); } } return CWrapper(0); } void main() { auto x = make_struct(); } 4) Please do not define free() function.
Re: hiding a class property behind a method
On Saturday, 22 February 2014 at 17:41:58 UTC, Ali Çehreli wrote: The code uses the two objects through the A interface and x() is a virtual function on that interface. When the C interface is used then we get C.x, which happens to be hiding the x() function of the base class. It looks normal to me. Ali Spec is silent on this, so this is indeed a question. Actually A is not interface, so I don't understand why you mention it. And there is neither 'taking C interface' because static type is A, so A function is called, neither it hides function of the base class because it is base class function which is called. I don't understand you completely. AFAIK this feature exists for many years, at least 3, possibly roots to D1. What happens is follows: since there is no function, base class virtual is not replaced, so virtual table of C looks like A, so A member function is called. If example is modified, then import std.stdio; class A { //string x () { return A; }; string x = A; } class B : A { //override string x () { return B; }; string x = B; } class C : A { //string x = C; // should this be illegal? string x () { return C; } } void main () { A o1 = new B(); A o2 = new C(); writeln(o1.x); // A writeln(o2.x); //A } so it appears that data member have priority over function. Probably this should be filed as a spec or compiler bug.
Re: Bug with references (no casting used)
On Saturday, 22 February 2014 at 17:22:51 UTC, andrea9940 wrote: Hi everyone, I was trying to get my vector struct to use extensively references for passing parameters and I found a subtle bug which make me lose a few hour. A sample code that shows the bug is here http://pastebin.com/rvcNdjAE (fails with dmd 2.064 on linux) I think that the code is wrong and dmd does not recognize it: opBinary() allocates a struct on the stack which is then accepted by reference in opOpAssign. I'd like to know if currently there are correct ways to pass rvalue structs by reference or if I should pass everything by value and hope the compiler optimizes all reduntant copies. Looks like compiler bug.
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 09:14:43 UTC, Cooler wrote: If you want to modify the slice and make changes visible in caller, you should use ref. If you don't care whether changes are visible in caller, you can omit any attributes and use plain array. This belongs to the case you are asking about. If you don't want to change array in callee, pass it as const qualified. Now, after rethinking the issue I am inclining that don't care whether changes are visible for caller is not very wrong, but not very good design. Ideally it should be specified to avoid unexpected problems to pop up. So yes, it is better to qualify array. Another point. This casino games of whether changes would be visible or not is direct consequence of how slices are implemented (and how runtime service them). Remember, that many features in D work in a strange way not because of wise design but as a consequence of not fully thought design (like array). As a result, some features work in not best way they should. Although many folks in newsgroups would eagerly say that you don't understand the lang, it wouldn't make a bad design a good one. Please stop explain me how fun3() works. I know that. This is first problem. You are being explained what is the *purpose* of the fun3() but you repeatedly fail to accept it. One of the main idea of D is that things must work as planned, or would not compile at all. Outcryingly wrong. Study bugzilla which shows how some things go wrong and read DIPs to learn that there are some issues in the language for which the communitty still struggles to formulate good solution. First and second variants follow this idea. But fun3() can work not as planned on the caller side (depends on fun3() body's implementation). Many things can work not as intended. Please read forums, bugzilla, etc. I bet passing array will not be the only thing you find confusing. The question again - may be prohibit fun3() variant? Prohibiting code like: void foo(int[] arr) {} would break hell of a code and pose doubts on what happens with arrays if so simple construction is prohibited. In addition, I mentioned that don't care is probably sometimes an option. Emitting warning here has some merits but it would be consitently ignored (I expect).
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 10:49:42 UTC, Cooler wrote: Now I am trying to speak ideally. What ideal language should be, not the practical implementation. ... Again - don't look back. Consider how we can make D better. ... Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors. Looks like you are overestimating yourself. Now, try: 1) write pull request to reject the code 2) convince developers somehow that your proposal is good 3) convince Walter to accept the change 4) after merging pull convince angry maintainers that it is good idea to reject unqualified array passing because Cooler tries to make the language better
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 16:48:51 UTC, Cooler wrote: On Thursday, 30 January 2014 at 16:18:33 UTC, Steven Schveighoffer wrote: void foo(int x) { x = 5; } hey, why doesn't that work! Setting a parameter to another value should be illegal! -Steve Please understand - I am not against void foo(int[] x){} I am for predictability of behavior. Predictability of behavior is not a principle of D and even if it would be, it can't be applied blindly. D is not a formal mathematic system. You suggest to describe function's behavior in documentation - quotation from your article It is a good idea to note in the documentation how the passed in slice might or might not be overwritten. My idea is that all potential errors must be detected as soon as possible. It is impossible to detect all errors in D per se, let alone taking into account separate compilation model. In some circumstances compiler can guess possible ways, but particular case we discussing is so common, that nothing can be done to 'fix' it. By the way, this case is not strictly speaking an error. It is error in context when caller cares about changes but this can be hardly verified at compile time (compiler need to read brain to know it). The D principle - The program compile and runs as expected, or not compile at all. It is all talk. Trying to apply this 'principle' in all cases is too naive. If you really need to call function that can change content of an array, but cannot change size of an array the language syntax should allow express it in function signature. I consider void fun(int[] const x){} more error prone than void fun(int[] x){} and for the caller and for implemeter. Personally this syntax is awful. By the way, there is another similar issue in D: import std.stdio; void foo(int[int] aa) { aa[1] = 1; } void main() { int[int] aa; foo(aa); writeln(aa); // [] aa[0] = 0; foo(aa); writeln(aa); // [0:0, 1:1] aa = null; foo(aa); writeln(aa); // [] } Here changes in AA array will be visible conditional that array is non null. If it is null, changes will be lost. This is another example of situation of the caller MAY or MAY NOT see changes to (citing your post above). In general, such semivalue-semireference semantic is produced when there is pointer wrapped into struct (doesn't matter whether it is opaque lang type or user defined). This happens in some language types, but may be also in user defined types. I don't think that verifying arbitrary semantic is compiler job.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 16:26:05 UTC, Cooler wrote: On Wednesday, 29 January 2014 at 16:15:36 UTC, Tobias Pankrath wrote: On Wednesday, 29 January 2014 at 16:01:08 UTC, Cooler wrote: Do you read my post? I am answering... why do I need fun3() if I already have fun1() and fun2(). fun3 guarantees that the argument has the same length for example. Where argument has the same length? After function call, or inside function? I don't understand what my intention should be to push me to use fun3()? If you want to modify the slice and make changes visible in caller, you should use ref. If you don't care whether changes are visible in caller, you can omit any attributes and use plain array. This belongs to the case you are asking about. If you don't want to change array in callee, pass it as const qualified. Now, after rethinking the issue I am inclining that don't care whether changes are visible for caller is not very wrong, but not very good design. Ideally it should be specified to avoid unexpected problems to pop up. So yes, it is better to qualify array. Another point. This casino games of whether changes would be visible or not is direct consequence of how slices are implemented (and how runtime service them). Remember, that many features in D work in a strange way not because of wise design but as a consequence of not fully thought design (like array). As a result, some features work in not best way they should. Although many folks in newsgroups would eagerly say that you don't understand the lang, it wouldn't make a bad design a good one.
Re: struct postblit not called, but still destructed
On Sunday, 19 January 2014 at 20:46:06 UTC, monarch_dodra wrote: I think the behavior is not *strictly* incorrect: When you write: sup = a; it triggers a postblit of a into sup. To do said postblit, you destroy sup. It's the way it works :/ Arguably, since it is initialization, we could avoid the destruction altogether, but it's not strictly *wrong*. I'll file it as an ER, and try to get Kenji on it. It is rather bug than ER because recently there was work to recognize such cases (initial assignment in constructors) as initialization, not just assignment. However I am not sure here because these changes were not documented properly.
Re: Why is string.front dchar?
On Monday, 20 January 2014 at 09:58:07 UTC, Jakob Ovrum wrote: On Thursday, 16 January 2014 at 06:59:43 UTC, Maxim Fomin wrote: This is wrong. String in D is de facto (by implementation, spec may say whatever is convenient for advertising D) array of single bytes which can keep UTF-8 code units. No way string type in D is always a string in a sense of code points/characters. Sometimes it happens that string type behaves like 'string', but if you put UTF-16 or UTF-32 text it would remind you what string type really is. By implementation they are also UTF strings. String literals use UTF, `char.init` is 0xFF and `wchar.init` is 0x, foreach over narrow strings with `dchar` iterator variable type does UTF decoding etc. I don't think you know what you're talking about; putting UTF-16 or UTF-32 in `string` is utter madness and not trivially possible. We have `wchar`/`wstring` and `dchar`/`dstring` for UTF-16 and UTF-32, respectively. import std.stdio; void main() { string s = о; writeln(s.length); } This compiles and prints 2. This means that string type is broken. It is broken in the way as I was attempting to explain. This is attempt to explain problematic design as a wise action. No, it's not. Please leave crappy, unsubstantiated arguments like this out of these forums. Note, that I provided examples why design is problematic. The arguement isn't unsubstained. [1] http://dlang.org/type By the way, the link you provide says char is unsigned 8 bit type which can keep value of UTF-8 code unit. Not *can*, but *does*. Otherwise it is an error in the program. The specification, compiler implementation (as shown above) and standard library all treat `char` as a UTF-8 code unit. Treat it otherwise at your own peril. But such treating is nonsense. It is like treating integer or floating number as sequence of bytes. You are essentially saying that treating char as UTF-8 code unit is OK because language is treating char as UTF-8 code unit. The only problem in the implementation here that you illustrate is that `['s', 'ä', 'д']` is of type `int[]`, which is a bug. It should be `dchar[]`. The length of `char[]` works as intended. You are saying that length of char works as intended, which is true, but shows that design is broken. Problems with string type can be illustrated as possible situation in domain of integers type. Assume that user wants 'number' type which accepts both integers, floats and doubles and treats them properly. This would require either library solution or a new special type in a language which is supported by both compiler and runtime library, which performs operation at runtime on objects of number type according to their effective type. D designers want to support such feature (to make the language better), but as it happens in other situations, the support is only limited: compiler allows to do alias immutable(int)[] number; number my_number = [0, 3.14, 3.14l]; I don't understand this example. The compiler does *not* allow that code; try it for yourself. It does not allow because it is nonsense. However it does allows equivalent nonsesnce in character types. alias immutable(int)[] number; number my_number = [0, 3.14, 3.14l]; // does not compile alias immutable(char)[] string; string s = säд; // compiles, however säд should default to wstring or dstring Same reasons which prevent sane person from being OK with int[] number = [3.14l] should prevent him from being OK with string s = säд
Re: Why is string.front dchar?
On Thursday, 16 January 2014 at 05:56:48 UTC, Jakob Ovrum wrote: On Tuesday, 14 January 2014 at 11:42:34 UTC, Maxim Fomin wrote: The root of the issue is that string literals containing characters which do not fit into signle byte are still converted to char[] array. This is strictly speaking not type safe because it allows to reinterpret 2 or 4 byte code unit as sequence of characters of 1 byte size. The string type is in some sense problematic in D. That's why the fact that .front returns dhcar is a way to correct the problem, it is not an attempt to introduce confusion. This assertion makes all the wrong assumptions. `char` is a UTF-8 code unit[1], and `string` is an array of immutable UTF-8 code units. The whole point of UTF-8 is the ability to encode code points that need multiple bytes (UTF-8 code units), so the string literal behaviour is perfectly regular. This is wrong. String in D is de facto (by implementation, spec may say whatever is convenient for advertising D) array of single bytes which can keep UTF-8 code units. No way string type in D is always a string in a sense of code points/characters. Sometimes it happens that string type behaves like 'string', but if you put UTF-16 or UTF-32 text it would remind you what string type really is. Operations on code units are rare, which is why the standard library instead treats strings as ranges of code points, for correctness by default. However, we must not prevent the user from being able to work on arrays of code units, as many string algorithms can be optimized by not doing full UTF decoding. The standard library does this on many occasions, and there are more to come. This is attempt to explain problematic design as a wise action. Note that the Unicode definition of an unqualified character is the translation of a code *point*, which is very different from a *glyph*, which is what people generally associate the word character with. Thus, `string` is not an array of characters (i.e. an array where each element is a character), but `dstring` can be said to be. [1] http://dlang.org/type By the way, the link you provide says char is unsigned 8 bit type which can keep value of UTF-8 code unit. UTF is irrelevant because the problem is in D implementation. See http://forum.dlang.org/thread/hoopiiobddbapybbw...@forum.dlang.org (in particular 2nd page). The root of the issue is that D does not provide 'utf' type which would handle correctly strings and characters irrespective of the format. But instead the language pretends that it supports such type by allowing to convert to single byte char array both literals sad and säд. And ['s', 'ä', 'д'] is by the way neither char[], no wchar[], even not dchar[] but sequence of integers, which compounds oddities in character types. Problems with string type can be illustrated as possible situation in domain of integers type. Assume that user wants 'number' type which accepts both integers, floats and doubles and treats them properly. This would require either library solution or a new special type in a language which is supported by both compiler and runtime library, which performs operation at runtime on objects of number type according to their effective type. D designers want to support such feature (to make the language better), but as it happens in other situations, the support is only limited: compiler allows to do alias immutable(int)[] number; number my_number = [0, 3.14, 3.14l]; but there is no support in runtime library. On surface, this looks like language have type which supports wanted feature, but if you use it, you will face the problems, as my_number[2] would give strange integer instead of float 3.14 and length of this array is 4 instead of 3. In addition this is not a type safe approach because there is option to reinterpret double as two integers. Now in order to fix this, there is number of functions in library which treat number type properly. Such practice (limited and broken language support, unsafe and illogical type, functions to correct design mistakes) is embedded into practice so deeply, that anyone who point out on this problem in newsgroup is treated as a fool and is sent to study IEE 754 standard.
Re: Why is string.front dchar?
On Monday, 13 January 2014 at 23:10:04 UTC, TheFlyingFiddle wrote: I'm curious, why is the .front property of narrow strings of type dchar? And not the underlying character type for the string. The root of the issue is that string literals containing characters which do not fit into signle byte are still converted to char[] array. This is strictly speaking not type safe because it allows to reinterpret 2 or 4 byte code unit as sequence of characters of 1 byte size. The string type is in some sense problematic in D. That's why the fact that .front returns dhcar is a way to correct the problem, it is not an attempt to introduce confusion.
Re: Question on static declaration
On Saturday, 11 January 2014 at 17:50:01 UTC, Eric wrote: Apparently the line, static shared static int x; will compile just fine. Is this sort of a bug, or does it mean something different from just static shared int x; ? Also, the line, static static static int x; will also compile. Does this mean x is extra static? -Eric It is a particular example of current nonsense in attribution parsing. This compiles: void main() { pure int i; @disable int di; nothrow int ni; } as well as more sophisticated nonsense. Issue is filed is bugzilla, so it will be fixed sooner or latter, current policy is to ignore it.
Re: Type inference and overloaded functions
On Friday, 13 December 2013 at 04:13:04 UTC, Kenji Hara wrote: On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote: If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable: void foo(int[]) {} void main() { foo([1, 2, 3]); int[3] tmp = [4, 5, 6]; foo(tmp); } There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in @safe code. Kenji Hara I think there is consensus that in @safe code this should be blocked.
Re: Is this reasonable?
On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote: Is this unavoidable, or could the compiler safely make the conversion implicitly? It is example of notorious phenomemena called integer promotions and usual arithmetic conversions. It is unavoidable given Walter's decision to keep this C stuff in D.
Re: Is this reasonable?
On Thursday, 5 December 2013 at 19:51:52 UTC, Ary Borenszweig wrote: But to make array.length uint by default and have these surprises all of the time just because a negative length doesn't make sense... I don't know, I feel it's not the right way to do it. Length of array type is not uint by default. This is second issue in array.length.
Re: Is this reasonable?
On Thursday, 5 December 2013 at 18:26:48 UTC, Jonathan M Davis wrote: On Thursday, December 05, 2013 19:16:29 Maxim Fomin wrote: On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote: Is this unavoidable, or could the compiler safely make the conversion implicitly? It is example of notorious phenomemena called integer promotions and usual arithmetic conversions. It is unavoidable given Walter's decision to keep this C stuff in D. To be fair, you can't solve the problem automatically. It's fundamentally wrong to compare signed and unsigned values, and doing either the conversion to unsigned or to signed could be wrong (or both could be wrong), depending on the values. The best that could be done would be to warn about the comparison or to make it an error. http://d.puremagic.com/issues/show_bug.cgi?id=259 - Jonathan M Davis Warning would be an option, but AFAIK Walter does not like warnings, so it is unlikely to be implemented.
Re: enum value vs. immutable
On Tuesday, 3 December 2013 at 08:28:23 UTC, Ali Çehreli wrote: That works for some types as both enum and immutable have their problems: * enum is no good for arrays and AAs as it is very likely to be unnecessarily slow. * immutable is no good for types that contain mutable references at least during assignment: struct S { int i; int[] others; } void main() { auto a = S(42); immutable b = a; // Error: cannot implicitly convert expression (a) of type S to immutable(S) } Kenji is working on this http://wiki.dlang.org/DIP49 It is C++ism like follwoing code: struct S { public: this(type){} ... } or static Type t; // in module scope Both of those do happen. ;) Ali Yes, this isn't good at all.
Re: Associative array references
On Monday, 2 December 2013 at 13:30:44 UTC, Atila Neves wrote: Bug or feature? This one caught me by surprise: void main() { { int[string] aa[string]; aa[foo][bar] = 1; assert(aa[foo][bar] == 1); //ok auto aa2 = aa; aa2[boo][dar] = 2; assert(aa[foo][bar] == 1); //ok } { int[string] aa[string]; //not set to anything yet auto aa2 = aa; aa2[boo][dar] = 2; assert(aa[foo][bar] == 1); //oops } } It seems that assigning an AA to another makes both point at the same data only if the first array has data to begin with. Is that the expected behaviour? Atila I would say it is consequence of current implementation, and, taking into account ongoing efforts to rewrite AA implementation, this special detail of null AA behavior may one day be gone.
Re: Foreach loop behaviour and manipulation
On Friday, 29 November 2013 at 00:41:16 UTC, bearophile wrote: H. S. Teoh: Modifying the loop variable of a foreach is, in general, a risky move. Right. In my opinion D programmers should learn that this is the preferred idiom of using foreach ranged loops: foreach (immutable i; 0 .. n) {} Bye, bearophile Unfortunately if you iterate over delegates, this may break immutability. See http://forum.dlang.org/thread/felqszcrbvtrepjtf...@forum.dlang.org?page=1
Re: enum value vs. immutable
On Monday, 2 December 2013 at 07:27:25 UTC, Ali Çehreli wrote: On 12/01/2013 09:57 PM, CJS wrote: I was reading the enum page of Ali Çehreli's (excellent) D book (http://ddili.org/ders/d.en/enum.html), and I'm confused by an enum value (not enum type), such as enum secondsPerDay = 60 * 60 * 24; In that situation I would have used an immutable variable. Is there any reason to prefer enum vs. immutable when defining constants? After realizing the other day that even 'static const' can be used for template instantiations, I am not sure myself anymore. :) Simple rules are great. I wanted to accept the following guidelines, none of which are clear cut: 1) Prefer enum first because enum values can be used for template instantiations. You can instatiate templates not only with enums. Main pro for enums is that they are CT values. 3) Prefer const last as it erases immutable attribute if present. (We can't know just by looking at a reference to const whether the original value has been immutable or mutable.) It is interesting to know where such advices come from. Const in D is useless except as as parameter qualifier, method qualifier, tool to alias const data and non-const data and as qualifier of some field - member of aggregate. Writing code like const int i = SOME_VALUE; is loosing advantages of immutable or enum while gaining nothing in return. It is C++ism like follwoing code: struct S { public: this(type){} ... } or static Type t; // in module scope
Re: Destructors calling sequence
On Friday, 29 November 2013 at 16:48:58 UTC, Temtaime wrote: Hi ! http://dpaste.dzfl.pl/53d9a59e How i can enforce that ~A will be called after ~B ? I'm writing 3D engine and it's critical to me. Thanks for yours aid ! It is impossible to do this directly given current gc implementation, but you can do something like that: class A { bool reset; void delegate dtor(); ~this() { if (!reset) dtor(); } } class B { A a; bool run; ~this() { if (!run) a.reset = true; run = true; } } A a = new A; B b = new B; b.a = a; b.a.dtor = b.__dtor;
Re: From D struct to C struct
On Monday, 18 November 2013 at 14:15:02 UTC, Namespace wrote: On Monday, 18 November 2013 at 10:09:12 UTC, qznc wrote: On Monday, 18 November 2013 at 08:32:11 UTC, Namespace wrote: I found another approach. It avoids the GC and the Heap: A Circular Buffer: http://dpaste.dzfl.pl/cf1e7afb That should work. It is unsafe, but might work in your specific case. The problem is that future changes might exhibit memory corruption, if the limit of your buffer is too low. Would probably be a hell to debug. Yes, but I know I never need more than 4 C pointer at the same time. I think there is bigger problem (and bigger memory error) here. When you inside struct method load pointer to some field you cannot rely that after leaving the method, the pointer will be safe. Structs are almost often located in stack and there are movable, which means that struct stack 'this' pointer may change. There is even issue in bugzilla with example when delegate touches struct field and is invoked at some point later which causes silent memory error because delegate pointer became invalid.
Re: From D struct to C struct
On Monday, 18 November 2013 at 16:03:33 UTC, Namespace wrote: On Monday, 18 November 2013 at 15:27:46 UTC, Maxim Fomin wrote: I think there is bigger problem (and bigger memory error) here. When you inside struct method load pointer to some field you cannot rely that after leaving the method, the pointer will be safe. Structs are almost often located in stack and there are movable, which means that struct stack 'this' pointer may change. There is even issue in bugzilla with example when delegate touches struct field and is invoked at some point later which causes silent memory error because delegate pointer became invalid. So I should change it from C[8] to C[] = new C[8]; to be sure? Yes.
Re: longjmp crashes on Windows
On Saturday, 16 November 2013 at 14:14:24 UTC, Piotr Podsiadły wrote: Hello, I'm trying to use setjmp and longjmp on Windows with DMD compiler (version 2.064). When compiled as 64-bit application, it works, but 32-bit version crashes inside longjmp. What should be changed to get it to work? I tried changing value of _JBLEN for x86 to some bigger number (like 1024), but it crashes too. Code: import std.stdio; version(Windows) { version(X86) enum _JBLEN = 64; else version(X86_64) enum _JBLEN = 256; else version(IA64) enum _JBLEN = 528; alias ubyte[_JBLEN] jmp_buf; extern(C) { int _setjmp(ref jmp_buf _Buf); void longjmp(ref jmp_buf _Buf, int _Value); } alias _setjmp setjmp; } What kind of problem you try to solve by manual defining system data structures? Why not use platform independent valid declarations? Why did you decide that _JBLEN is 64, 256, 528 according to version? Why did you decide that having _JBLEN bytes filled with zeros is a valid value of jmp_buf object? Why should setjmp/longjmp take buffer by reference? void main() { jmp_buf env; uint i; if(setjmp(env) 3) { writeln(ping); longjmp(env, ++i); } writeln(done); } Call stack: c:\Users\vbox\Documents\testtest.exe ping object.Error: Access Violation 0x00423F78 in _local_unwind 0x004214D0 in longjmp 0x0040B300 in void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll().void __lambda1() 0x0040B2D3 in void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() 0x0040B1EB in _d_run_main 0x0040B018 in main 0x0042142D in mainCRTStartup 0x754F3677 in BaseThreadInitThunk 0x77959F42 in RtlInitializeExceptionChain 0x77959F15 in RtlInitializeExceptionChain Try to use proper version of setjmp/jmp_buf from druntime. By the way, why did you decide to use it in D language in a first place?
Re: UFCS with constructors
On Wednesday, 6 November 2013 at 17:10:34 UTC, Ali Çehreli wrote: I would be very surprised if unary - produced a different type from the operand: Ali Operator does not produce type, it produces value of expression, and type of expression happens not to be the type you expected. But such expectations need not correspond to language rules (try to think from from language laywer perspective). In bearophile case, I guess Typedef!double overloads unary operator which returns double which is primary reason for such behavior.
Re: How to re-initialise an associative array.
On Wednesday, 6 November 2013 at 17:49:41 UTC, H. S. Teoh wrote: The GC will take care of cleaning up the old data. T Unfortunately it will not take care of calling struct destructors.
Re: UFCS with constructors
On Wednesday, 6 November 2013 at 18:02:32 UTC, Ali Çehreli wrote: But such expectations need not correspond to language rules (try to think from from language laywer perspective). I still argue that the expression -expr must have the same type as expr. In bearophile case, I guess Typedef!double overloads unary operator which returns double which is primary reason for such behavior. That's what I deduced from qznc's post and tried to mean that such behavior would be confusing to programmers. Ali I think that reason for such behavior is the way used defined operator overloading functions are implemented, not the language per se, so programmers confuse themselves.
Re: Trait keyword.
On Saturday, 2 November 2013 at 21:28:46 UTC, Adam D. Ruppe wrote: On Saturday, 2 November 2013 at 20:45:28 UTC, TheFlyingFiddle wrote: I'm basically wondering why the __traits keyword looks so horrible. I think it looks beautiful and wished all the keywords used the leading underscores. This is about taste and it is subjective. The reason is that the __keywords are reserved, so they don't conflict with user words. __traits was added somewhat late into the language, so using a reserved word for it meant less broken code. Now you can still call your own variables traits - I'd love it if all keywords were this way so we could, in theory at least, use the anywhere. Statement that in D __identifiers are reserved is dubious as nothing stops users from defining them (I was under impression that D really prevents but is actually was misconception). D incorporates substantial amount of C but does not impose similar limitations on reserved identifiers (__identifier is not the only one reserved in C). Futhermore, dmd internally generates lots of identifiers and does not prohibit user from 'picking up' them - it is huge amount of accept-invalid code. There is also a bug that code struct S { void __foo(){} void bar() {} } pragma(msg, __traits(allMembers, S)); printed only 'bar' since some commit in 2.064 (I haven't tested current version). Except these issues, '__identifiers' and 'identifiers' are pretty much the same. Using the former bears some 'risk' that such identifiers may hijack some symbol but it is low. I believe that __trais was chosen because of combination of unwillingness to intervene into 'identifiers' category (in some sense it is desire to 'stabilize the language' by pretending that language is 'stable') and belief that introducing new features/fixing existing features should not break existing code (but it is inconsistent policy as the same time pretty much code is broken each release, and there is pretty much another code which will very likely be broken in the future). Anyway, the decision seems to be within the path which was followed by C (_Noreturn, _Thread_local), so it is not that bad.
Re: fieldPostBlit - what is wrong with this and workarounds
On Thursday, 31 October 2013 at 14:03:28 UTC, Daniel Davidson wrote: Given this code: import plus.tvm.rate_curve; struct T { RateCurve m; } struct S { const(T) rc; } I get this error: Error: mutable method plus.models.dossier.__unittestL42_1.T.__fieldPostBlit is not callable using a const object Is this fundamentally incorrect? I abandoned immutable in hopes that const would be more manageable and so far it has. But these types of issues still crop up and stop me in my tracks. What are the requirements on RateCurve and T for this to work? Thanks Dan D language is fundamentally incorrect here. There are sufficient issues in bugzilla (one which bearophile provided is actually relevant, it shows same problem from a little bit different aspect) and the problem tends to pop up quire regularly. It looks like nothing is done because it is design issue and although there were attempts to come up with, no idea is viewed as final solution. The easiest way to solve problem is to strip const.
Re: structs holding on to reference data by pointer
On Thursday, 31 October 2013 at 17:34:21 UTC, Daniel Davidson wrote: On Thursday, 31 October 2013 at 16:16:36 UTC, bearophile wrote: That's wrong code, you are escaping a reference to memory (of rc variable) allocated in the stack frame of foo(). The D compiler is not smart enough to recognize the bug. There are optimizations that patch and avoid this bug (like inlining, or allocating rc inside the stack frame of the main) but you can't rely on them. Ahh ok. Because of issues with const members (copying them when they are composed in other classes does not work well) I'm trying to get around the copy by storing reference data as const(T) *. This is why I'm asking. So here are some follow ups: - As I see it there is grave risk. Is the risk introduced by the fact that I am storing a member as const(T)*? Risk is that pointer to local variable is escaped, not because it is stored in const qualified pbject. - I assume that if I had created the RC instance on the heap there would be no problems. Is there a way in general to ensure that a const(T)* is referring to something on the heap as opposed to the stack (ideally at compile time). Yes, you can explicitly allocate on heap. You can check whether data is on heap, stack, tls, or just global object by inspecting pointer at runtime. Ideally there would be such function in druntime. It is impossible to do this in CT (except if comiler support flow analysis and can prove in some scenarious that data is on stack or not, but due to separate compilation it is impossible to do in general case) (and probably shouldn't). - What is the root problem - having a const(T)* member which then requires code to take address, or taking address? My first thought was, just never take address of local static variable - which is generally good advice. But once you are in a function that takes ref const(T) you can take the address of that as well - see modification below. This suffers the same problem but in a less obvious way. Any suggestions welcome. Thanks Dan import opmix.mix; import plus.tvm.rate_curve; import std.stdio; struct RC { this(this) { data = data.dup; } int[] data; } struct T { const(RC) *rc; void goo() { writeln(Data is , rc.data); } } T goo(ref RC rc) { return T(rc); } T foo() { RC rc = { [1,2,3] }; writeln(Address is , rc); return goo(rc); } void main() { T t = foo(); t.goo(); writeln(Address is , t.rc); } Yes, this is known issue. There are lots of other tricks to break the language.
Re: fieldPostBlit - what is wrong with this and workarounds
On Thursday, 31 October 2013 at 17:22:07 UTC, Daniel Davidson wrote: I'm think you may be correct... but what specifically is incorrect about the language? When I see __fieldPostBlit I get the feeling it is more an implementation issue than the language. __postblit also looks like implementation detail but it is same problem. Field postblit means that aggregate has some members which have postblits so they should be called. This is same problem which blows in higher level. If as you suggest, D language is fundamentally broken - is it possible we can just get a plan for fixing it? To me this seems like a huge design hole and I come back to the threads with questions again and again and I really don't know how others manage the use of const/immutable. This is probable tenth thread about const postblits which I do remember for all my (only) 2 years in D. D2 (version currently in use) dates back to 2004 AFAIK and Andrei (helping to design the language) is in D since 2006, also AFAIK. Draw your own conclusions. I've already given up on immutable. If I have to strip const as well then that is a huge pain and unfortunate since the concept seems sound and well argued in TDPL. Trying to mess with mutable/const/immutable on mostly working code is like playing whack a mole. One can do: 1) revise the design to challange whether consts are really necessary 2a) use workarounds like const pointer 2b) use cast to break const or another tricks (explicit casts are better because holes in type system may be fixed in some point in the feature)
Re: structs holding on to reference data by pointer
On Thursday, 31 October 2013 at 18:51:46 UTC, bearophile wrote: Maxim Fomin: You can check whether data is on heap, stack, tls, or just global object by inspecting pointer at runtime. Ideally there would be such function in druntime. This seems like a nice enhancement request for Bugzilla :-) Are you going to open it? It seems useful for me too. You are expert in making enhacement request :) It is impossible to do this in CT (except if comiler support flow analysis and can prove in some scenarious that data is on stack or not, but due to separate compilation it is impossible to do in general case) (and probably shouldn't). You can do it even with separate compilation (at compile time) if your language has different kinds of pointers as Rust. Perhaps in D this can be done using Phobos-defined smart pointers. Bye, bearophile But I don't believe that D being system laguage will diverge from traidtional C/C++ pointer model. Right, in runtime smart pointers can probably do some job by guessing allocation kind looking at pointer.
Re: Bug in RefCounted?
On Monday, 28 October 2013 at 20:43:01 UTC, Ali Çehreli wrote: What is the purpose of writeln in that delegate? Obviously, to print 1. Yet it doesn't happen that way. Is this accepted to be a bug? Should the programmer 'new' the object instead? Ali In my opinion it is a corner case, a consequence of two things: 1) need to allocate struct into heap due to lambda 2) need to put dtor invocation in the end as usual.
Re: Bug in RefCounted?
On Tuesday, 29 October 2013 at 12:03:09 UTC, Rene Zwanenburg wrote: On Monday, 28 October 2013 at 19:40:26 UTC, Maxim Fomin wrote: The fact that structs are movable and there is too few struct runtime reflection makes them noncollectable. However, you can wrap struct inside class, in such case struct dtor will be called. Yeah, if wrapping inside a class wouldn't work either we'd be in a whole new world of hurt. But what do you exactly mean by noncollectable? And what does movability have to do with that? I think the memory will be reclaimed without a problem, so new-ing a struct without destructor would be fine. This doesn't leak: struct S { int i; } void main() { while(true) { new S; } } I would say it leaks because dtor (if defined) is not called, although memory is reclaimed at some point. In my opinion struct movability is a problem for heap struct collection because it is hard to say judging to struct stack/heap pointer whether it should be collected or not. If you look at output from previous example, ctor, 1 dtor, 77ED8FF8, 1 ctor, 2 dtor, 7FFFDB30, 1 you will see that adressess are different and refer to stack, yet object is in the heap. By the way, there is another issue - if you have delegate inside struct method touching some field, than invoking such delegate after returning from method may break memory, because delegate references 'this' struct pointer, but it may be changed across lifetime. I am not sure whether some algorithm for solving heap struct collectibility can be made, but I don't have any idea right now.
Re: Types soup with enum and bool
On Tuesday, 29 October 2013 at 12:43:17 UTC, bearophile wrote: This code is accepted by the D compiler: enum Foo { A, B, C } void main() { bool[5] bools; auto b = bools[2] != Foo.C; bools[2] = Foo.A; } Who is that likes such kind of code? What are the advantages of accepting such kind of code? I can see the disadvantages and risks. Bye, bearophile Probably may be related to even worse issue: import std.stdio; void foo(bool b) { writeln(bool); } void foo(long l) { writeln(long); } void main() { foo(0); // bool foo(1); // bool foo(2); // long int i = true; foo(i); // long } If reasons for accepting yours and this example are the same, then this is by design (to be more precise, the part which is related to bool types being essentially kind of integer types + VRP + overloading rules).
Re: Bug in RefCounted?
On Tuesday, 29 October 2013 at 17:57:01 UTC, Ali Çehreli wrote: On 10/29/2013 08:47 AM, Maxim Fomin wrote: On Monday, 28 October 2013 at 20:43:01 UTC, Ali Çehreli wrote: What is the purpose of writeln in that delegate? Obviously, to print 1. Yet it doesn't happen that way. Is this accepted to be a bug? Should the programmer 'new' the object instead? Ali In my opinion it is a corner case, a consequence of two things: 1) need to allocate struct into heap due to lambda 2) need to put dtor invocation in the end as usual. As a continuation of this sub thread, I've opened the following thread in the D newsgroup: http://forum.dlang.org/post/l4osr0$2f3q$1...@digitalmars.com Ali I did this in 2 January (http://forum.dlang.org/thread/lpljpfjxwobniglwn...@forum.dlang.org) and received exactly zero responces.
Re: Types soup with enum and bool
On Tuesday, 29 October 2013 at 18:23:03 UTC, bearophile wrote: Ali Çehreli: enum Foo { A, B, C } void main() { bool[5] bools; auto b = bools[2] != Foo.C; bools[2] = Foo.A; } ... There was a long discussion about that. Walter was happy that bool was a integer type. Many of us had objections: My problem is mostly with enums. I don't remember Walter explaining the rationale of the D enum conversion design. I prefer the C++11 enums. Bye, bearophile Bools being integer types is reason of your problem with enums. Relevant lines from your code are translated to: bool b = 0 != 2; bools[2] = 0; taking into account that 'bool' is integer type having capacity to represent values 0 and 1.
Re: Types soup with enum and bool
On Tuesday, 29 October 2013 at 21:24:35 UTC, bearophile wrote: Maxim Fomin: Bools being integer types is reason of your problem with enums. The reason of that problem of mine with enums is that they convert implicitly to integers. And I still don't know the original rationale of Walter of this design mistake. Bye, bearophile It works according to spec: A named enum member can be implicitly cast to its EnumBaseType, but EnumBaseType types cannot be implicitly cast to an enum type. In this respect D enums behave like C enums.
Re: Class References
On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote: Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = ClassOne, CLASS2 = ClassTwo } You can define class references in module scope and initialize them in module constructor. This will not help if you want to have working classes in compile time, but may be useful in runtime.
Re: Class References
On Monday, 28 October 2013 at 12:10:37 UTC, John Colvin wrote: On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote: Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = ClassOne, CLASS2 = ClassTwo } Short answer: No Long answer: the enum values must be compile-time constants, that's what enums are all about. Addresses and references are not compile-time constants. This is an arbitrary limitation imposed by Don and I disagree with him. According to opinion you presented providing classes at CT requires having addresses but it can be viewed other way - providing classes at CT requires some valid value which should be preserved for using in RT. For example, nobody complains that having enumeration constant or module scope immutable qualified basic type int at CT requires to have some address. Although int belongs to value type category, int as module variable has address. Example to illustrate issue: enum E : int[] { A = [0,1] } immutable EI = [0,1]; enum EE = [0, 1]; void main() { E e1, e2; assert (e1 == e2 e1 == [0,1]); e1[0] = 1; assert(e2[0] == 0); //EI[0] = 1; // Error: cannot modify immutable expression EI[0] assert(EI[0] == 0); // EE[0] = 1; // Error: constant [0, 1][0] is not an lvalue assert(EE[0] == 0); } Dynamic arrays like classes are reference types, so there are addresses involved. Not only this shows that CT references are possible, but that dmd can support similar behavior for classes. Replace int[] with some class and you will arrive that there is something wrong about idea that enum values must be compile-time constants, addresses and references are not compile-time constants, thus reference types can't be compile-time expressions.
Re: Bug in RefCounted?
On Monday, 28 October 2013 at 16:53:11 UTC, monarch_dodra wrote: On Monday, 28 October 2013 at 10:07:15 UTC, Rene Zwanenburg wrote: Yeah, I'd like to know this as well. I do remember structs allocated on the heap don't have their destructors called at all due to the GC not being precise, I think. But one object allowed to be destructed multiple times? That sounds really bad.. If that's true a lot of my code is probably incorrect. Hum... I seem to remember having replied earlier, but I guess I forgot to hit send. In any case, I could be mistaken, but I simply know that under certain circumstances, it can happen. OK I don't know if that's a bug though. I'll try to find the cases where it happens. So do you *know* cases or suspect that they may exists? Or remember some bug issue? Here is my attempt: import std.stdio; struct S { int i; this(int i) { writefln(ctor, %X, i); this.i = i; } this(this) { writefln(postblit, %X, %X, this, i); } ~this() { writefln(dtor, %X, %X, this, i); } } auto foo() { S s = S(1); return { s = S(2); } ; } void main() { foo()(); } ctor, 1 dtor, 77ED8FF8, 1 ctor, 2 dtor, 7FFFDB30, 1 Inside foo() function object 's' is destroyed twice: first time as a regular struct at the end of block scope, second time before assigning S(2). There are other tools: union bug, control flow tricks, __traits, __dtor but they are move obvious.
Re: Bug in RefCounted?
On Monday, 28 October 2013 at 10:07:15 UTC, Rene Zwanenburg wrote: On Sunday, 27 October 2013 at 23:33:55 UTC, Ali Çehreli wrote: That's news to me. I know that objects may never be destroyed but why multiple times? How many lives do they have? ;) Yeah, I'd like to know this as well. I do remember structs allocated on the heap don't have their destructors called at all due to the GC not being precise, I think. The fact that structs are movable and there is too few struct runtime reflection makes them noncollectable. However, you can wrap struct inside class, in such case struct dtor will be called. But one object allowed to be destructed multiple times? That sounds really bad.. If that's true a lot of my code is probably incorrect. I think one need to be aware of this bug (no dtor), rather than cases when dtor is called multiple times. import std.stdio; struct S { int i; this(int i) { writefln(ctor, %X, i); this.i = i; } this(this) { writefln(postblit, %X, %X, this, i); } ~this() { writefln(dtor, %X, %X, this, i); } } int this_throws() { throw new Exception(); } void foo(S s, int i) {} void main() { try { foo(S(1), this_throws); } catch(Exception e) {} }
Re: Array of struct with floating point members seg faults
On Saturday, 26 October 2013 at 17:46:31 UTC, Ali Çehreli wrote: The following program seg faults: struct Point { double x; double y; } void main() { Point[1] arr; } Any combination of float and double members exhibit the same bug as long as the size of the struct is 16. I vaguely remember seeing a similar bug before but I can't find it in bugzilla. Ali http://d.puremagic.com/issues/show_bug.cgi?id=9969 http://d.puremagic.com/issues/show_bug.cgi?id=9449
Re: Copying to an immutable array in a costructor
On Thursday, 24 October 2013 at 10:58:30 UTC, bearophile wrote: Jonathan M Davis: It's a compiler bug. immutable data should not be initialized more than once. My point was another one, regarding this refused code: import std.algorithm: copy; immutable int[2] data; static this() { [10, 20].copy(data[]); // Error. } void main() {} Bye, bearophile Reduced: immutable int[] data; void foo(int[] data) {} static this() { foo(data); }
Re: Copying to an immutable array in a costructor
On Thursday, 24 October 2013 at 07:02:25 UTC, bearophile wrote: This shows a limitation of the D type system: import std.algorithm: copy; immutable int[2] data; static this() { foreach (i, x; [10, 20]) data[i] = x; // OK data[] = [10, 20]; // OK [10, 20].copy(data[]); // Error. } void main() {} Bye, bearophile Because control flow check for immutable data is almost absent. I don't know any situation where are such checks (except constructors). There is similar issue with respect to initializsing immutable member field in struct constructor. There is issue in bugzilla filed for it (it looks like it will be fixed), where Andrei proposed a concept of cooked object, basically implying control flow for initializaing immutable members. I think that the code you posted as an additional case for the issue.
Re: Warnings/What should I know?
On Friday, 18 October 2013 at 06:56:49 UTC, monarch_dodra wrote: On Friday, 18 October 2013 at 06:13:38 UTC, DDD wrote: I'm learning D. I'm curious about surprises I may get. I typically use C++, C# and javascript Off the top of my head, I think the biggest one is that D doesn't offer default constructors. Instead, it only has a default value initialization. EG: S s; S s = S.init; S s = S(); S s = S(5); The first 3 lines are more or less equivalent. Not always actually. This can bite you in the ass if you write something like: struct S { this(int i = 5) {} } S s = S(); //Does *not* call the constructor with the value 5. One can bite in the ass even more in case of struct S { @disable this(); } and using S.init or void foo () { int i; struct S { int bar() { return i; } } and also using S.init Finally, D doesn't have copy constructor. It has something a bit sweeter called postblit. Basically, you first bitcopy the object you want to duplicate, and then, a function called postblit gets called, which does the work that is required (should any be required). What's nice about this is that the target object and source object never actually communicate. How much are there threads asking what is wrong with the language when there are const/immutable structs and postblit :) ?
Re: does cast make an lvalue appear to be an rvalue
On Wednesday, 16 October 2013 at 17:05:25 UTC, Daniel Davidson wrote: The code below fails to compile due to the last line. I was hoping casting away immutable would allow the call to foo. I think it is not accepted because of the rval to ref issue. If that is the case, how can foo be called by casting? I'm not a fan of casting but I'm finding cases where it is the only recourse to create immutable data using impure functions that should be pure. Thanks Dan import std.conv; struct T { int[] i; string[string] ss; } void foo(ref T t) { } void main() { T t1; auto t2 = immutable T(); foo(t1); foo(cast()t2); } foo([cast()t2][0]); (It would be good to have compound literals like in C)
Re: Understanding opAssign and 'alias this'
On Monday, 14 October 2013 at 09:17:12 UTC, John Colvin wrote: Everything is working fine except for the error on [2] when xxx == true, which I think is a bug. minimised test: struct A { void opAssign(A a) {} } struct B { A a; alias a this; } void main() { A a; B b; b = a; } Error: function assign.B.opAssign (B p) is not callable using argument types (A) This does not work (and need not) because compiler generates default function B.opAssign(B) which is really not callable using argument types (A).
Re: copying const struct
On Monday, 14 October 2013 at 11:35:32 UTC, Jack Applegame wrote: Why this doesn't compile? http://dpaste.dzfl.pl/21ef5b04 class Foo {} struct Bar1 { const(Foo[]) member; } struct Bar2 { const Foo member; } void main() { const Bar1 bar1; const Bar2 bar2; Bar1 b1 = bar1; // ok Bar2 b2 = bar2; // cannot implicitly convert expression (bar2) of type const(Bar2) to Bar2 } This is compilable using git head.
Re: copying const struct
On Monday, 14 October 2013 at 13:56:58 UTC, Benjamin Thaut wrote: Am 14.10.2013 13:54, schrieb Dicebot: On Monday, 14 October 2013 at 11:45:30 UTC, Jack Applegame wrote: On Monday, 14 October 2013 at 11:38:23 UTC, Benjamin Thaut wrote: The line Bar2 b2 = bar2; would remove const from member Seems strange, because b2.member is const by declaration. Strange indeed and smells like a bug. `auto bar = Bar2(bar2.member)` works so it should be assignable. d.puremagic.com/issues/show_bug.cgi?id=9665 I don't see how this is related to the topic.
Re: Understanding opAssign and 'alias this'
On Monday, 14 October 2013 at 10:45:26 UTC, Maurice wrote: On Monday, 14 October 2013 at 09:32:15 UTC, Maxim Fomin wrote: On Monday, 14 October 2013 at 09:17:12 UTC, John Colvin wrote: Everything is working fine except for the error on [2] when xxx == true, which I think is a bug. minimised test: struct A { void opAssign(A a) {} } struct B { A a; alias a this; } void main() { A a; B b; b = a; } Error: function assign.B.opAssign (B p) is not callable using argument types (A) This does not work (and need not) because compiler generates default function B.opAssign(B) which is really not callable using argument types (A). Then why does it work when replacing opAssign(A a) with opAssign(int)? struct A { void opAssign(int) {} } struct B { A a; alias a this; } void main() { A a; B b; b = a; // This now compiles fine... } OK, it seems to be what actually causes the problem is implicit conversion from B to A. Situation depends on presence of A.opAssign(A ) because when compiler tries to resolve function call, it is confused between calling B.opAssign(B) and casting through alias this B to A and calling A.opAssign(A). When it realizes that there is no best match it throws error. Since argument B is casted to A, the error message looks so weird.
Re: copying const struct
On Monday, 14 October 2013 at 17:38:22 UTC, Ali Çehreli wrote: On 10/14/2013 10:33 AM, Kenji Hara wrote: On Monday, 14 October 2013 at 14:18:10 UTC, Maxim Fomin wrote: This is compilable using git head. When I read that line ... Kenji Hara ... I was thinking about that person. :) Thank you Kenji! Ali Right. Kenji is true D celebrity. Funniest thing happen in cases like this when he reports the bug himself and soon fixes it, later bug is hit by someone else but during reporting it is realized that bug is already fixed, pull is pushed to master and everyone salutes Kenji. What bothers me is that some (in fact, probably many) delicate language cases are silently fixed by Kenji without proper documentation so D language has some sparse and obsolete spec, even more obsolete book and sporadic patches - just couple of developers are aware about each of them. When someone hits corner language case - weird compiler behavior it is general unknown what should compiler do, whether current behavior is bug or a fix for some other previous bug about which you are unaware of. When different parts of language interact, problem becomes even more complicated.
Re: Is there a way to see if .init has been set by the user?
On Saturday, 21 September 2013 at 11:13:57 UTC, simendsjo wrote: I want to know if a variable has changed .init, but I don't know if it's possible if the .init value is the same. Does anyone have a solution for this? int a; int b = 0; pragma(msg, a.init); // 0 pragma(msg, b.init); // 0 // how can I see that b has = 0? Strictly speaking this is an ill-posed question. Are talking about testing at runtime whether some variable was changed from init to some non-default value?
Re: Is there a way to see if .init has been set by the user?
On Saturday, 21 September 2013 at 11:35:11 UTC, bearophile wrote: init is part of a type and you can't change it. Bye, bearophile Well, D wouldn't be D, if it did not allow something like this for aggregate types: import core.stdc.string, std.stdio; pure hack(T)(T value) if (is(T == class)) { byte[] init_mem = new byte[T.classinfo.init.length]; memcpy(init_mem.ptr, cast(byte*)value, T.classinfo.init.length); T.classinfo.init = init_mem; } class A { int a; } pure foo(int val) { A a = new A; a.a++; hack(a); return a.a + val; } void main() { writeln(0.foo, 0.foo, 0.foo); // prints 1,2,3 } And taking into accout some additional runtime magic, assertion below may fail: class A { int i = 5; } struct S { A a;} S s; assert(s.a is null);
Re: Unable to use tradional tools to find memory leaks
On Saturday, 21 September 2013 at 14:30:19 UTC, Flamaros wrote: I tried to used Valgrind (Linux) and Dr Memory (Windows) without success to find a big leak I have in my application. But both tools can't launch my application without make it crash. Is application crashing without these tools? Probably you have some bug which is detected by valgrind. By the way, some pitfalls of using valgrind for testing D code: 1) Its implementation of float numbers at compile time is buggy (for example, there may be static asserts which are true when running under native envorionment and false under valgrind) 2) Dmd's codegen is sometimes not supported by valgrind (cannot execute some instructions which is rare case when something from D beats some tool outside) 3) It has some false positives regarding using uninitialized values especially during execution of GC code. Do I need do something particular, to have a chance to see one of those tool working fine with my application? If you run into #2 then you cannot fix it. It can be really hard to find leaks manually, maybe some option of the gc can help me? If you look into gc sources, you can found some testing code, but it needs druntime recompilation.
Re: Unable to use tradional tools to find memory leaks
On Saturday, 21 September 2013 at 17:03:14 UTC, Brad Roberts wrote: On 9/21/13 9:01 AM, Maxim Fomin wrote: On Saturday, 21 September 2013 at 14:30:19 UTC, Flamaros wrote: I tried to used Valgrind (Linux) and Dr Memory (Windows) without success to find a big leak I have in my application. But both tools can't launch my application without make it crash. Is application crashing without these tools? Probably you have some bug which is detected by valgrind. By the way, some pitfalls of using valgrind for testing D code: 1) Its implementation of float numbers at compile time is buggy (for example, there may be static asserts which are true when running under native envorionment and false under valgrind) 2) Dmd's codegen is sometimes not supported by valgrind (cannot execute some instructions which is rare case when something from D beats some tool outside) 3) It has some false positives regarding using uninitialized values especially during execution of GC code. Do I need do something particular, to have a chance to see one of those tool working fine with my application? If you run into #2 then you cannot fix it. That's wrong. Both DMD and Valgrind are software, both of which can be debugged and changed. Please file appropriate bug reports, hopefully with nicely minimized test cases. No, that's true. DMD does produce some code which is executed by native envoronment but not by valrgind which is likely to be a valgrind bug. Sure, you can fix the issue belonging to a valgrind code if you are a valring developer, but this is not an option for most users.
Re: surrounded type modifier
On Wednesday, 18 September 2013 at 13:23:10 UTC, Namespace wrote: Code: const { /// [1] int a = 3; } void main() { const { /// [2] int b = 4; } } Why is [1] allowed, but not [2]? Citing grammar: FunctionBody: BlockStatement BodyStatement InStatement BodyStatement OutStatement BodyStatement InStatement OutStatement BodyStatement OutStatement InStatement BodyStatement BlockStatement: { } { StatementList } As you can see there is no room for attributes. Why dmd does not support attributes here is separate question - probably because such construct would be confused with lambda, but this is not a serious reason.
Re: surrounded type modifier
On Wednesday, 18 September 2013 at 14:23:25 UTC, Namespace wrote: Should I open an enhancement report? Of course you are always free to open enhancement reports.
Re: User defined attributes use
On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote: All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun(@nonNull C c) { ... }; C c; fun(c); //compilation error since C is null No, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features.
Re: User defined attributes use
On Monday, 16 September 2013 at 16:50:43 UTC, Namespace wrote: On Monday, 16 September 2013 at 15:47:36 UTC, ilya-stromberg wrote: On Monday, 16 September 2013 at 15:12:05 UTC, Maxim Fomin wrote: On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote: All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun(@nonNull C c) { ... }; C c; fun(c); //compilation error since C is null No, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features. It's intresting how can I check that pointer is not null at the compile time. Can you print a example, please? I know that we can use contract programming, but it requires runtime check. That isn't possible. ;) Similar effect can be achieved by different way. If some function takes S as parameter, one cannot pass directly instance of A or null - error will be issued which is some sort of compile-time protection. class A { int i; } struct S { A a; A getA() { if (a is null) a = new A; return a; } alias getA this; } void main() { S s; assert (s.i is 0); S ss = S.init; assert (ss.i is 0); } Unfortunately D does not have non-nullable classes which is a problem #1. Ideally structs should have default constructors (hello to those who miss them - problem #2) which could initialize class instance. Since they are absent, wrapping struct can be enhanced by inserting disabled constructor to ensure that no default struct instances with null references are created. However, since disabled constructors are also flawed (they don't prevent from producing T.init values by design and in some situations dmd is not smart enough to detect other cases by mistake) which is a problem #3, non-null classes can be simulated by code above using alias this + rt check. At least this works with two most problematic cases of struct initilialization: without initializer and with T.init value.
Re: User defined attributes use
On Monday, 16 September 2013 at 19:21:47 UTC, H. S. Teoh wrote: On Mon, Sep 16, 2013 at 08:56:17PM +0200, Namespace wrote: [...] I hate this NotNull struct hack. It is the same crap as the current scope solution. BTW: I'm curious which built-in feature will be removed next, maybe AA? [...] That wouldn't be a bad idea, actually. The current AA implementation is so horribly broken, and so wrong in so many ways (there are at least 75 bugs related to AA's, some of the worst of which are 11037, 11025, 10916, 10525, 10381, 10380, 10046, just to name a few), that it would do a world of good to get rid of them altogether, and then reintroduce a properly-designed library solution for them. Of course, in the meantime everyone whose code breaks because of that will form a mob to lynch me, so I'll have to survive long enough to get the library solution working first. :-P T This demonstrates an interesting issue. I think the primary reason why you are complaining about AAs is not because their implementation is flawed but because you can't fix it without dmd's internals knowledge :) I always consider ability to hack dmd as important skill (at least in better language understanding because it is not defined by standard but by reference implementation) in D and that's why I am skeptical about many ideas proposed in form of DIPs - (unless they are proposed by those folks whose names often appear in dmd git commit log) because such proposals are not implementable without dmd's knowledge. I remember one point made recently by one regular D forum participant that it is more important 'to know the language itself', 'to be abstract from one particular implementation' rather then knowing 'dirty implementation details' to propose DIPs and that those who know dmd will eventually implement DIPs - yet number of DIPs is close to 50 and judging by ratio implemented DIPs/total DIPs it obvious that such assumption doesn't hold. As a result community is stuck with many features of language are flawed but they can be hardly fixed - plenty discussions and DIPs are generated but problems are not moved by an inch. I think if a person who has druntime/phobos commits to fix some issue but no dmd's one should ask in a forum thread/directly address to Walter/Kenji for a help request (addressing Walter should happen without hesitation because he is the first to be blamed :) ).
Re: GC.collect bug ?
On Friday, 13 September 2013 at 15:24:17 UTC, Temtaime wrote: Hello for all ! I need to call all objects destructors in one place. It's guaranted, that there is no objects instances. I tried use GC.collect but it's produces strange results. import std.stdio; import core.memory; class A { ~this() { writeln(`dtor`); }; }; void main() { auto a = new A; a = null; GC.collect(); writeln(`after dtor`); } Output is: after dtor dtor Why? Regards. For me it prints dtor - after dtor in case of pure compilation. In general it depends on compiler switches and druntime.
Re: override and package
On Thursday, 12 September 2013 at 11:29:22 UTC, Jacob Carlborg wrote: On 2013-09-12 11:28, Namespace wrote: But if I try to write 'override' before [1], I get this error message: Error: function T4._apply cannot override a non-virtual function This seems inconsistent. I really overwrite the method, and then I put it in a package label. I think the error message is pretty clear. You cannot override a function that isn't virtual. Private and package methods are not virtual. Actually error message is misleading - it complains as T1._apply would be non-virtual function which is wrong, it is one. The problem is not in case of overriding non-virtual function but in attempt to override virtual function (private) by non-virtual one (package). I think error mesage should be something like: Error: function T4._apply is non-virtual function and cannot ovverride virtual function T1._apply
Re: A small and simple library for working with Qt.
On Monday, 9 September 2013 at 08:06:17 UTC, MGW wrote: I am D since the spring. Without a simple GUI to work hard. I tried to deal with QtD quick disconnects, but I failed. I had to develop its small and very simple library to work with Qt. The working title of QtE. Works in Windows 32 and Linux 32. A very simple idea. Instances of classes get through QtE.dll (in C++) and methods directly with Qt. Unfortunately it sounds for me like yet attempt to build a project which will be eventually given up. Are you sure you can maintain the project? You wrote that you have recently read TDPL - are you sure you are skilled enough? By the way, have you thought about the reason why qtd doesn't work as you expected? The source code and examples http://qte.ucoz.ru/ 1) Ucoz.ru sites are notorious known for their quality. There are some sites for projects written in D, for example dsourse.org (probably there are others, but I don't know). By the way, if you visit it, you will found how much projects were given up. 2) It is bad to promote something written in russian to international group. You should definetly transalte some docs before advertising your project. By the way, I have read passages from main page of your site. Something to comment: - D is very far to be 'perfect' or even to be completed - there are many features that either don't work or misbehave; - D is not even close to be 'theoretically sound' (it is so on paper rather in practice) - although it can classified as strongly typed, its type system is compromised by many holes and as ongoing discussions show, the language design has severe issues. This is important because one of D's troubles is gap between what is promoted and what is provided which shouldn't happen.
Re: UFCS from within classes
On Monday, 9 September 2013 at 17:07:59 UTC, Gyron wrote: Hey there, I've experimented a little with UFCS today and ran into a problem. My first question, which is kinda off-topic: Why does D use the int type if you give it a number started with 0x(hex), shouldn't it use uint for that ? It is not a bug, but a feature - see Decimal Literal Types table at http://dlang.org/lex.html Here comes the real question: I've extended the int by one function, which is the following (just to represent the problem): public static T read(T)(int address) { return cast(T)1; } It works perfectly if the function stands alone (is global), but it doesn't work if I put it into a class (because I want it to be a bit more organized) like that: class CMemory { public static T read(T)(int address) { return cast(T)1; } } I'm not able to write something like: 0x1212.CMemory.read!bool(); So the question is, how can I make it to be able to be used like this: 0x1212.read!bool(); but still organized within the class ? class CMemory { public static T read(T)(int address) { return cast(T)1; } } alias CMemory.read!int CMread; void main() { 0.CMread(); } You can also use alias CMemory.read CMread; plus 0.CMread!int();
Re: Get class size of object
On Sunday, 11 August 2013 at 15:28:44 UTC, JS wrote: On Sunday, 11 August 2013 at 13:40:41 UTC, Timon Gehr wrote: On 08/11/2013 06:25 AM, JS wrote: Given an object, is there a built in way to get the size of the class the object represents? Yes. Troll. I guess he does not answer to the question as well as others do (including me) because of your misbehavior in D newsgroups. Solution to your question is obvious (built-in feature without any import). By the way, GC.sizeOf seems to return size of allocated page which is bigger than needed (for ex. it returns 16 for a new int which is 4).
Re: Get class size of object
On Sunday, 11 August 2013 at 16:16:26 UTC, bearophile wrote: Maxim Fomin: GC.sizeOf seems to return size of allocated page which is bigger than needed (for ex. it returns 16 for a new int which is 4). The object instance contains a pointer to the virtual table, so there's a way to know what object it is. With that runtime information it should be possible to know the static size of the instance. Bye, bearophile I do not know how you can calculate precisely object size by knowing that GC.sizeOf returns some aligned amount plus knowing something about virtual table. In case of simple objects (like ints) it does not work since int has no virtual table. Anyway such guessing is useless since D provides feature to get size of class instance (if it is defined) even in comple time like enum S = _get_size ...
Re: Get class size of object
On Sunday, 11 August 2013 at 16:36:53 UTC, Adam D. Ruppe wrote: On Sunday, 11 August 2013 at 04:25:21 UTC, JS wrote: Given an object, is there a built in way to get the size of the class the object represents? try this: Object obj = new Whatever(); auto size = typeid(obj).init.length; Yes, this is answer to the question. By the way, it can be simply enum S = typeid(Whatever).init.length;
Re: Is enum static?
On Thursday, 8 August 2013 at 23:19:49 UTC, bearophile wrote: Ali Çehreli: More than that. :) enums are manifest constants. Imagine that enum as being pasted into source code as is. This used to have surprising effects for AAs, as an enum AA would be instantiated from scratch everywhere that AA enum was used in the code. I think that some time ago Don has proposed to disallow the 'enum' tag for things like AAs, on the base that such behavour is not efficient, surprising, and maybe even not useful... I don't know where his proposal has gone later. Bye, bearophile Enum trick is useful to workaround bug with aggregate members of reference types being initialized - all instances share reference to same data and to enable default struct constructors.
Re: Declare reference to variable ?
On Monday, 29 July 2013 at 21:37:30 UTC, bearophile wrote: Temtaime: Why i cannot declare reference in D ? I don't know the reasons. But maybe you can create a little struct with just a pointer inside and an alias this to a member function that returns a ref. Bye, bearophile It doesn't work because alias this does not capture context pointer like delegate.
Re: Why is size_t unsigned?
On Monday, 22 July 2013 at 15:04:25 UTC, monarch_dodra wrote: On Monday, 22 July 2013 at 12:51:31 UTC, Andrej Mitrovic wrote: On 7/22/13, JS js.m...@gmail.com wrote: foreach doesn't allow you to modify the index to skip over elements. It does: - import std.stdio; void main() { int[] x = [1, 2, 3, 4, 5]; foreach (ref i; 0 .. 5) { writeln(x[i]); ++i; } } - Writes: 1 3 5 99% sure that's unspecified behavior. I wouldn't rely on anything like that. Of course it is specified behavior. ForeachStatement: Foreach (ForeachTypeList ; Aggregate) NoScopeNonEmptyStatement Foreach: foreach foreach_reverse ForeachTypeList: ForeachType ForeachType , ForeachTypeList ForeachType: refopt BasicType Declarator refopt Identifier Aggregate: Expression This is an example of unspecified behavior: import std.stdio; void main() { int[] x = [1, 2, 3, 4, 5]; foreach (ref i; 0 .. 5) { __limit1631--; writeln(x[i]); } }
Re: Why is size_t unsigned?
On Monday, 22 July 2013 at 15:51:45 UTC, monarch_dodra wrote: So... you are saying that if the grammar allows it, then the behavior is specified? You may argue that although grammar does allows it, the feature is semantically not defined. However here it is known what ref int i means, to be more precise what you can do with objects marked with ref attribute. All I see, is you iterating over references to the elements of an aggregate. The final behavior really depends on how said aggregate is implemented. If anything, if the behavior *was* defined, then I'd simply argue the behavior is wrong: I don't see why changing the values of the elements of the aggregate should change the amount of elements you iterate on at all. Also: // int[] x = [1, 2, 3, 4, 5]; foreach (ref i; iota(0, 5)) { writeln(x[i]); ++i; } // This also compiles, but I used a different aggregate, yet represents the same thing. Because it is implemented differently, I get a completely different result. Unless I'm mistaken, when a result depends on the implementation, and the implementation doesn't state what the result is, then that's what unspecified behavior is. (unspecified, not undefined). This is different because in 0..5 ref int maps directly to variable modified, but in iota() it maps to value returned by .front property function and since it doesn't return by ref, refness is wiped out. Behavior is defined in both cases. This is an example of unspecified behavior: ... What is __limit1631 ? Doesn't compile for me. This one may http://dpaste.dzfl.pl/3faf27ba extern(C) int printf (const char*, ...); void main() { int[] x = [1, 2, 3, 4, 5]; foreach (ref i; 0 .. 5) { __limit6--; // or 5 depending on dmd version printf(%d\n, x[i]); } } 1 2 3 This is example of unspecified behavior (better undefined) due to playing with __identifiers and how dmd bug can make D code looks strange.
Re: foreach over split string
On Wednesday, 17 July 2013 at 15:26:19 UTC, John Colvin wrote: I think I can speak quite safely for the majority of the community when I say that you are only welcome here if you can keep your aggressive and disrespectful comments to yourself. I think you cannot, as nobody provided you such right and I, in particular, do object, as saying you may ask but please without obscene language is not a way how public technical newsgroup should be organized. It is pretty obvious in this case that flow of obscene language will not stop. Also, your politeness does harm in this case rather than good.
Re: UDA's for enum values?
On Sunday, 14 July 2013 at 13:38:41 UTC, Dicebot wrote: On Sunday, 14 July 2013 at 12:33:07 UTC, JS wrote: I would like to do something like ... Looks like a grammar issue. UDA's are supposed to be attached to any symbol declaration as far as I understand, which enum members definitely are. Probably worth bugzilla entry. Looks like http://d.puremagic.com/issues/show_bug.cgi?id=9701
Re: Style question
On Thursday, 11 July 2013 at 20:15:52 UTC, Namespace wrote: The whole situation looks strange. If you can change both files, than it is unclear what made you to write such inconsistent code. If you can change only one of them, then it should be adjusted to another (meaning importing external file and using that enum instead of trying to define different type and passing it). Besides the problem of changing existing API: If you change only one of those modules and use the enum from the other file, every user have to look into the file which declares the enum, to see which member the enum has. This argument can be applied to virtually any peice of code of any language which has import or #include. This is almost same as direct cast in #2. Instead of making test2() accept B or (u)int consider making it static void test2 (MyClass.A a) and wipe out enum B entirely. That's the problem I tried to describe above. If you have those two modules as in my example code, the one file without the enum depends on the one with the enum. Isn't that a bad situation? Any file importing map depens on std.algorithm. Isn't that a bad situation? A possible solution would be to change one of those functions which accepts different enums, that it accept an uint - nothing else is an enum (in this case). Well if you consider that this is a best option nothing stops you from doing this. In such case you can't mark functions as @safe and may run into bugs when some integer value placed into enum does not fit into allowed values. This problem is tackled by final switches. By the way, in your case base type is int, not uint.
Re: Can templated functions be used in interfaces?
On Thursday, 11 July 2013 at 12:03:10 UTC, Jakob Ovrum wrote: However, in my opinion, it's a bug that you're allowed to declare a function template (when using the shortcut syntax) without defining it, whether in an interface or not. This is a rather natural bug though, due to the nature of function templates: void a()(); is equivalent of: template a() { void a(); } Perhaps it makes sense to allow the declaration without definition when the template and function are explicitly separated (can anyone think of a case where this is useful? Maybe mixin-related?), but when using the former syntax - the function template syntax - I don't think it makes any sense. It is possible in current implementation to split template declaration and definition in different modules but in such case list of potential template arguments is limited. Disabling this option in general would disable D ability to hide template implementation (like libraries and external functions). But in this particular case I agree that this should be an error like in situation with static functions.
Re: A purity change
On Thursday, 11 July 2013 at 15:25:10 UTC, bearophile wrote: This used to compile (probably dmd 2.060): struct Foo { immutable int y; void bar(TF)(TF f) pure { f(1); } void spam() pure { bar((int x) = y); } } void main() {} But now it gives: test.d(4): Error: pure function 'test.Foo.bar!(immutable(int) delegate(int x) nothrow @safe).bar' cannot call impure delegate 'f' test.d(7): Error: template instance test.Foo.bar!(immutable(int) delegate(int x) nothrow @safe) error instantiating Is it a correct error? Bye, bearophile My guess is that before 2.063 immutable int y was implicitly static, but now it is per instance data which requires context pointer which is deduced to be impure - that why compilation fails (try placing static attribute). In other words, before 2.063 this was a function and now it is a delegate. And delegates currently don't play well with constness/immutability.
Re: pointers, assignments, Garbage Collection Oh My?
On Thursday, 11 July 2013 at 17:07:18 UTC, Ali Çehreli wrote: On 07/11/2013 12:23 AM, Jacob Carlborg wrote: On 2013-07-10 20:22, Ali Çehreli wrote: And to be pedantic, length comes first: struct Array (T) { size_t length; T* ptr; } I thought ptr came first, that's the reason you could cast to the pointer type. Not that one should do that. Perhaps there's some compiler/runtime magic involved. There must be little magic and that magic should be the same as getting the .ptr property. Otherwise, the value of a struct object cannot be casted to pointer type: struct S { int *p; } auto s = S(); int *p = cast(int*)s; Error: e2ir: cannot cast s of type S to type int* Ali In context of slices cast(int*)arr is essentially s.ptr. There is no magic but accessing right field of struct.
Re: A purity change
On Thursday, 11 July 2013 at 17:59:22 UTC, bearophile wrote: Maxim Fomin: My guess is that before 2.063 immutable int y was implicitly static, but now it is per instance data which requires context pointer which is deduced to be impure - that why compilation fails (try placing static attribute). In other words, before 2.063 this was a function and now it is a delegate. And delegates currently don't play well with constness/immutability. I think you are right. So is it right to ask D to infer such delegate as pure? Bye, bearophile I think delegate here can be allowed to be pure. However, I wouldn't expect this issue to be fixed soon since it touches a general problem of delegates vs. immutability problem. There were many discussions and DIP but there is still no solution.
Re: A purity change
On Thursday, 11 July 2013 at 18:03:14 UTC, bearophile wrote: Maxim Fomin: My guess is that before 2.063 immutable int y was implicitly static, Yet, in the code I used to initialize y in the normal constructor of Foo. If now I tag y as static, that's not possible any more (Error: can only initialize static const member scale inside static constructor), so I don't understand again. Bye, bearophile The reason it worked in normal constructor prior the change was probably the same bug. This docs covers the issue - http://dlang.org/changelog.html#staticfields
Re: Style question
On Thursday, 11 July 2013 at 18:22:11 UTC, Namespace wrote: I have a style question, because a friend of mine has a similar problem currently and I have no good advice for him. Let's assume we have this classes: The whole situation looks strange. If you can change both files, than it is unclear what made you to write such inconsistent code. If you can change only one of them, then it should be adjusted to another (meaning importing external file and using that enum instead of trying to define different type and passing it). class MyClass { public: enum A { Foo = 0, Bar = 1 } private: A _a; public: this(A a) { this._a = a; } void test1() { MyStaticClass.test2(this._a); } } // enum B { Foo = 0, Bar = 1 } final abstract class MyStaticClass { public: static void test2(B b) { } } void main() { } Prints: Error: function enum_problem.MyStaticClass.test2 (B b) is not callable using argument types (A) What should he do? Judging by MyStaticClass.test2(this._a) it seems that the first imports the second which is also suspicious - you are importing module which contains main function. From where does the code come from? As far as I can see he has 3 options: 1. An external file with the enum information. Both classes would import it and could use the same enum. But he cannot change the API, so this is no real option. It would be good to clarify which file cannot be modified, although it does not really matter - just use one version of enum. 2. Change test1 into this: void test1() { B b = cast(B) this.a; MyStaticClass.test2(b); } This works fine. But is it safe? And is it good style? It is safe but not @safe (you will have complains if try to mark function as @safe). Of course this is a bad style, the whole case is strange. And how is this cast converted? Is it cheap? Essentially nothing special is done. Of course it is cheap. 3. Change test2 so that it accepts (even) (u)int. But then he lose the Type safety. This is almost same as direct cast in #2. Instead of making test2() accept B or (u)int consider making it static void test2 (MyClass.A a) and wipe out enum B entirely.
Re: pointers, assignments, Garbage Collection Oh My?
On Wednesday, 10 July 2013 at 18:22:24 UTC, Ali Çehreli wrote: And to be pedantic, length comes first: struct Array (T) { size_t length; T* ptr; } Which is actually property-like because assigning to length does pretty complex stuff. So the member cannot be named as 'length': struct Array (T) { size_t length_; T* ptr; } Anyway... :) Ali To be pedantic dynamic arrays are implemented in D simply as struct Array { size_t length; void* ptr; } and there is no type parametrization since such arrays handling is opaque for users (in druntime they are treated as void[]). Parametrization can be useful in user side since performing any operations with structure above (void*) will lead to errors. But in user side there is no point in manipulating the structure directly, as it can be done using usual properties/druntime without template bloat. By the way, the style ABI page is written, allows implementation to have more fields.
Re: Allocating a slice object
On Thursday, 4 July 2013 at 12:02:16 UTC, monarch_dodra wrote: This is a pretty stupid question, but how would you allocate an int[] on the heap? I'm not talking about the array, but the actual slice object. EG: int[]* pSlice = new int[]; //Error: new can only create structs, //dynamic arrays or class objects, not int[]'s Is there a simple idiomatic way? I'm currently doing it by allocating a struct that wraps one: struct S{int[] a;} int[]* pSlice1 = cast(int[]*) new S; int[]* pSlice2 = (new S).a; Note: This is also a neat way to allocate a static array on the heap. Yes. This is a good example of how D type system and memory allocation type are different, despite many move type system terms into memory category. Anybody have some better way? Another way: import std.stdio; void main() { int[] arr; auto x = { return arr; } ; writeln(arr); }
Re: Stop to! rounding?
On Wednesday, 3 July 2013 at 08:23:40 UTC, monarch_dodra wrote: My brother in law writes financial apps, and in that field, using floating points type is *legally* forbidden. Really? What kind of apps?
Re: Eponymous template with full template syntax
On Monday, 1 July 2013 at 18:15:06 UTC, Ali Çehreli wrote: I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof 12345); } void main() { static assert(isSmall!int); // -- the usual syntax works static assert(isSmall!int.isSmall); // -- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional? Ali I think that this probably worked as early as in the end of 2011 but I can be wrong as don't remember exactly. It seems that dmd recognizes isSmall!int.isSmall as potential UFCS property, converts isSmall!int to bool and tries to issue call isSmall(bool) and fails, because that template does not define any function.
Re: Opaque structs
On Saturday, 29 June 2013 at 08:01:17 UTC, Johannes Pfau wrote: Am Fri, 28 Jun 2013 22:16:33 +0200 schrieb Andrej Mitrovic andrej.mitrov...@gmail.com: On 6/28/13, Johannes Pfau nos...@example.com wrote: A naive question: Why isn't struct S {} enough? This should be a struct with size 0 so why do we need to disable the constructor and postblit explicitly? Because the user should never be able to use such a struct by value, in other words a user might mistakenly write code such as: S s2 = *s; // copies 1 byte But why is that legal / does that copy _one_ byte? It seems like that's totally arbitrary. Shouldn't doing anything value-related on an empty struct be invalid anyway? It copies one byte because empty structs have one byte - according to D implementation. The value can be adjusted using align() atrribute.
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 08:08:17 UTC, monarch_dodra wrote: Just in case it wasn't clear from the original explanation, this is a bug, it *should* be perfectly safe to pass as many temps as you want, and expect the right amount of destructor called in case of a throw. Original explanation lacks the word bug deliberately because this is not a bug (in a sense that dmd generates wrong code), but a language design problem. How could you do this: struct S { int i = 1; } void foo(S s) { s.i = 2; } void main() { S s; foo(s); } Currently there are two dtors, one which gets S(2) at the end of foo and second at the end of main, which gets S(1). If you move dtor from callee to caller, it would get S(1) object (struct is passed by value), but it doesn't make sense to destruct S(1) where you have S(2). One possible solution is to pass by pointer in low level, which would probably increase magnitude of problems.
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 15:17:12 UTC, monarch_dodra wrote: Should I have expected a different behavior? import std.stdio; int callme() { throw new Exception(); } struct S { int i = 0; this(int i){this.i = i; writeln(constructing: , i);} this(this){writeln(postbliting: , i);} ~this(){writeln(destroying: , i);} } void foo(S s, int i) { s.i = 2; } void main() { S s = S(1); foo(s, callme()); } Destructor for copied object is not called because it is placed in foo(). Before calling foo(), dmd makes a copy of main.s, calls postblit, then puts code to invoke callme() and code to invoke foo(). Since callme() throws, foo() is not called and destructor placed in foo() is also not called. A struct copy escapes destructor. Now, if you try fix this by putting dtor for copy not in foo(), but in main immediately after foo() invocation, you will have a problem because destructor would get S(1) object while it should destroy S(2). Any modification made in foo() is lost. This can be possible fixed by passing copy by reference which would probably create new ABI problems.