Re: Source code annotations alla Java
On Thursday, 20 January 2011 at 18:19:21 UTC, Jacob Carlborg wrote: On 2011-01-20 14:47, Justin Johansson wrote: Not long ago the Java Language people introduced the idea of annotations together with an annotation processing tool (apt). Now perhaps the idea of source code annotations is not actually a Java invention per se, however for someone learning D is there any equivalent idiom [of Java annotations] in the D language? Depending on what you want to do you can create a template mixin that accepts string(s)/alias(es). For example: for the serialization library (http://dsource.org/projects/orange) I'm working on the following syntax is used: class Foo { int x; int y; int z; mixin NonSerialized!(z); } The above mixin indicates that the z instance variable shouldn't be serialized. This is (currently) achieved by defining a field in the mixed in template (which will be added to the class) which is a struct containing the string of the filed which shouldn't be serialized. Then I iterate over all the fields in the class with .tupleof and collects all mixed in fields in a list. Then I know what fields to skip later during the serialization. let's assume you are building a web application and you want to keep that controller only for the logged in users. in java you can create an annotation class called @RequireLogin and put your logic there. mixins are not the way for this.
Reference parent type
Suppose I have class A { mixin t!A; } is there a way to replace the mixin template's dependence on the class name? e.g., class A { mixin t!This; // This turns in to A } (so, for example, renaming the above class only has to rename one place instead of two)
Re: core.stdc.config
On Thursday, 30 January 2014 at 03:28:57 UTC, Craig Dillabaugh wrote: So, there is a module core.stdc.config (referenced here): http://dlang.org/interfaceToC.html That is presumably part of the D Standard library. I am curious to know why no mention of this library is included at: http://dlang.org/phobos/index.html Is it not part of Phobos? Are there standard modules in D that are not included in Phobos? If so, where would one find the list of these modules. The way i see what's available is to take a look at the files installed by the compiler. The directory is different for all operating systems but it's great to look at the source code of all the different modules. For example on Mac OSX 10.8.5 'core.stdc.config' is located at '/usr/share/dmd/src/druntime/src/core/stdc/config.d'. There you can see how the types are constructed and what they represent. For Linux just type 'locate config.d' in the terminal. For Windows it's all in 'C:\d' i think.
Re: Reference parent type
On Thursday, 30 January 2014 at 09:03:17 UTC, Frustrated wrote: mixin t!(typeof(this))
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 09:14:43 UTC, Cooler wrote: Please stop explain me how fun3() works. I know that. One of the main idea of D is that things must work as planned, or would not compile at all. First and second variants follow this idea. But fun3() can work not as planned on the caller side (depends on fun3() body's implementation). The question again - may be prohibit fun3() variant? If we prohibit it, what use cases we could not implement with fun1() and fun2()? Goodness... You've been shown this use case like a zillion times already: the caller manages her buffer, fun3() is allowed to change contents, but not reallocate caller's buffer. fun1() can't provide that (const), fun2() cannot either, because it explicitly allows reallocation (ref). This behavior is only provided by fun3(). So it's either that, or indeed cases of I don't care about this array, which Maxim Fomin has mentioned.
Re: Keywords: How to trick the compiler?
On Wednesday, 29 January 2014 at 17:12:57 UTC, Stanislav Blinov wrote: On Wednesday, 29 January 2014 at 17:11:32 UTC, Ary Borenszweig wrote: Yes, as there are other ways for body: _body, _body, Body, HtmlBody, etc. But body is the best one. torso? ;) offspring = document.createElement(div); document.torso.addOffspring(div);
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: Keywords: How to trick the compiler?
On Thursday, 30 January 2014 at 10:15:10 UTC, Chris wrote: offspring = document.createElement(div); document.torso.addOffspring(div); Looks great! :D
Question about dynamic arrays and slices
Hi, I just read this nice article about slices: http://dlang.org/d-array-article.html So I tried this code to see if I understood it correctly: --- import std.stdio; void main() { auto a = new int[5]; auto b = a; a[0] = 1; for(auto i = 0; i 100; i++) { a ~= 0; } a[0] = 2; writefln(a[0] = %d, a[0]); writefln(b[0] = %d, b[0]); } --- This prints: a[0] = 2 b[0] = 1 That is, a was resized to a point where it needed to reallocate its contents. b still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change. Is this expected behaviour? How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data?
Re: Question about dynamic arrays and slices
This prints: a[0] = 2 b[0] = 1 That is, a was resized to a point where it needed to reallocate its contents. b still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change. Is this expected behaviour? That's how it is. How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data? I don't understand your exact requirements. Do you want to make sure that everyone sees the updates to the array, even after a relocation?
Re: Array as an argument, ambiguous behaviour.
Cooler: Again - stop consider current state of D implementation. Consider how we can make D better. I think fun3() push programmers to make errors. I think functions like void fun(int[] a){} are bug prone, because you seem to change the length of the array inside the function, or if you perform an append you modify a new memory zone, but such changes are invisible from the caller. Some times this is what you want, and in some cases this is a programmer mistake (this bug happened to me several times). But I don't know what to change and if this situation can be improved now. Perhaps all that's left to improve is to add tests to a D lint that warns against this possible source of bugs. Bye, bearophile
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
Interfaces allow member definitions?
I was, I think, able to call an interface's method. I had the code like the following interface A { void foo(); } class B : A { void foo() { writeln(Hey); } } class C : A { void foo() { writeln(You); } } yet, when I called a.foo(); I did not get any output. (A being of type A) Now, I was doing some weird stuff but either in the vtable for A, there are empty functions that do nothing or I just happen to call bogus memory that did not throw an exception. The real question is, do interface methods actually support function definitions? Is there anything that stops us from actually doing interface A { void foo() { writeln(What up!!); } } internally? I know member functions require a this but in this case foo does not require this so it any this would work. Basically, does the vtable contain storage for the interface's members but blocks us from using them due to the issue with this? If so, then shouldn't we be able to create functions in an interface as long as they do not reference this? (basically static functions that can be overriden as dynamic functions in the class) e.g., interface A { // default behavior for foo and bar void foo() { writeln(asdasdfasdfasdf); } void bar() { writeln(1234); } } class B : A { void foo() { writeln(help); } } void main() { A a = new B; a.foo(); // prints help a.bar(); // prints 1234 B b = new B; b.foo(); // prints help b.bar(); // prints 1234 } This would allow one to sort of add default behavior to an interface(limited since no fields could be used but properties help with it). basically the vtable just needs an extra spot for the interface methods and calls them with null or the object it contains for this... which doesn't matter since this is never used in the body of the function.
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 11:19:58 UTC, Frustrated wrote: I was, I think, able to call an interface's method. I had the code like the following interface A { void foo(); } class B : A { void foo() { writeln(Hey); } } class C : A { void foo() { writeln(You); } } yet, when I called a.foo(); I did not get any output. (A being of type A) Now, I was doing some weird stuff but either in the vtable for A, there are empty functions that do nothing or I just happen to call bogus memory that did not throw an exception. The real question is, do interface methods actually support function definitions? Is there anything that stops us from actually doing interface A { void foo() { writeln(What up!!); } } internally? I know member functions require a this but in this case foo does not require this so it any this would work. Basically, does the vtable contain storage for the interface's members but blocks us from using them due to the issue with this? If so, then shouldn't we be able to create functions in an interface as long as they do not reference this? (basically static functions that can be overriden as dynamic functions in the class) e.g., interface A { // default behavior for foo and bar void foo() { writeln(asdasdfasdfasdf); } void bar() { writeln(1234); } } class B : A { void foo() { writeln(help); } } void main() { A a = new B; a.foo(); // prints help a.bar(); // prints 1234 B b = new B; b.foo(); // prints help b.bar(); // prints 1234 } This would allow one to sort of add default behavior to an interface(limited since no fields could be used but properties help with it). basically the vtable just needs an extra spot for the interface methods and calls them with null or the object it contains for this... which doesn't matter since this is never used in the body of the function. You can already do this using the Non-virtual interface ideom interface Foo { final void bar() { writeln(Something); } void baz() { writeln(Something Else); } } Note the final keyword it is imortant here. This will make bar simply be a non-virutal method in Foo. If you want to provide some basic implementation but still forward to a base class you can do something like this. interface Foo2 { final void bar(uint i) { // Does some basic stuff here. bar_impl(i); } protected void bar_impl(uint i); } class A : Foo2 { protected void bar_impl(uint i) { //Do some specific stuff here. } } This pattern allows you to do some basic stuff in bar and more specialized stuff in bar_impl. It does require that you overload bar_impl though which may not be what you want.
Re: N-body bench
On Wednesday, 29 January 2014 at 18:05:41 UTC, Stanislav Blinov wrote: Yep, doesn't seem to be simd-related: struct S(T) { T v1, v2; } void main() { alias T = double; // integrals and float are ok :\ version (workaround) { S!T[1] p = void; } else { S!T[1] p; } } Anyway, here's the revised (and bugfixed :o)) code, if anyone's interested: http://dpaste.dzfl.pl/52d9e1fdc0fd On my machine, dmd -release -O -inline -noboundscheck is only 6 times slower than that C++ version :D I'll try to get around to making it work with ldc on the weekend.
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 14:34:54 UTC, Cooler wrote: Here is ambiguity. void fun3(int[] x){ x ~= 5; ... } auto a = new int[10]; fun3(a); // Here content of a may be changed or may be not changed. Depends on the buffer size that system will allocate for a array. You use very subjective meaning for ambiguity, one that is never normally used in programming language context. Normally term ambiguity is applied only when _compiler_ can't reliably decide meaning of the code snippet and needs to resort to special casing. You are correct in notion that you can't make any reasonable judgement yourself about content of a after `fun3` call but same applies to `fun2` - it can be or not be modified. It is expected - to express all semantics of function body in function signature one would have needed to make it of comparable length and complexity. In practice you need always to assume the worst - everything is modified and nothing can be trusted unless explicitly qualified other way around.
Re: Question about dynamic arrays and slices
On Thursday, 30 January 2014 at 12:50:34 UTC, John Colvin wrote: On Thursday, 30 January 2014 at 10:43:55 UTC, Ary Borenszweig wrote: Hi, I just read this nice article about slices: http://dlang.org/d-array-article.html So I tried this code to see if I understood it correctly: --- import std.stdio; void main() { auto a = new int[5]; auto b = a; a[0] = 1; for(auto i = 0; i 100; i++) { a ~= 0; } a[0] = 2; writefln(a[0] = %d, a[0]); writefln(b[0] = %d, b[0]); } --- This prints: a[0] = 2 b[0] = 1 That is, a was resized to a point where it needed to reallocate its contents. b still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change. Is this expected behaviour? How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data? pass the array by ref, or make a wrapper struct that holds a pointer to a slice, or a wrapper class that holds the slice. Alternatively, make a wrapper struct that disallows the append operator and always use std.array.refAppender woops, sorry that last one doesn't help.
Re: Question about dynamic arrays and slices
On Thursday, 30 January 2014 at 10:43:55 UTC, Ary Borenszweig wrote: Hi, I just read this nice article about slices: http://dlang.org/d-array-article.html So I tried this code to see if I understood it correctly: --- import std.stdio; void main() { auto a = new int[5]; auto b = a; a[0] = 1; for(auto i = 0; i 100; i++) { a ~= 0; } a[0] = 2; writefln(a[0] = %d, a[0]); writefln(b[0] = %d, b[0]); } --- This prints: a[0] = 2 b[0] = 1 That is, a was resized to a point where it needed to reallocate its contents. b still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change. Is this expected behaviour? How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data? pass the array by ref, or make a wrapper struct that holds a pointer to a slice, or a wrapper class that holds the slice. Alternatively, make a wrapper struct that disallows the append operator and always use std.array.refAppender
Re: Question about dynamic arrays and slices
On Thu, 30 Jan 2014 05:43:55 -0500, Ary Borenszweig a...@esperanto.org.ar wrote: Hi, I just read this nice article about slices: http://dlang.org/d-array-article.html So I tried this code to see if I understood it correctly: --- import std.stdio; void main() { auto a = new int[5]; auto b = a; a[0] = 1; for(auto i = 0; i 100; i++) { a ~= 0; } a[0] = 2; writefln(a[0] = %d, a[0]); writefln(b[0] = %d, b[0]); } --- This prints: a[0] = 2 b[0] = 1 That is, a was resized to a point where it needed to reallocate its contents. b still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change. Is this expected behaviour? Yes, it is intrinsic on how slices and arrays work. How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data? You can't. Why is that important? The use case (or case that you are troubled by) would help to explain I think. -Steve
Re: Interfaces allow member definitions?
Compiling with DMD 2.064, I am NOT able to get any function in interfaces accepted unless they are final. This means you cannot provide default behavior in the interface, at least not in the ways shown above.
Re: Array as an argument, ambiguous behaviour.
kOn Wed, 29 Jan 2014 05:55:56 -0500, Cooler kul...@hotbox.ru wrote: Consider 3 functions taking array as an argument: void fun1(in int[] x){...} void fun2(ref int[] x){...} void fun3(int[] x){...} auto a = new int[10]; fun1(a); // Guaranteed that a will not be changed fun2(a); // Guaranteed that we will see any change to a, made in fun2() fun3(a); // Changes to a in fun3() may be or may be not visible to the caller In case of fun3() we have ambiguous behaviour, depending on the body of the function. Am I right? Yes. Is that intentional? Yes. I read the rest of the discussion. Arrays are hard to understand in D, especially if you have preconceived notions from other languages. But I would point out that fun2 does not guarantee anything more than fun3: void fun2(ref int [] x) { fun3(x); } It is an intrinsic property of slices that they do not own the data pointed at. You cannot guarantee that one slice's changes will affect another slice, AS LONG AS one slice is increasing its length. If you avoid increasing the length, then the results are deterministic. As I said in the article, avoid increasing the length, and THEN changing the original data. If you do that, you should have quite predictable results. If your code must do otherwise, explain in the documentation what should happen (i.e. don't use the passed-in slice after the function), and use some of the tricks to avoid it (use ref, or return the new slice data). -Steve
Re: core.stdc.config
On Thursday, 30 January 2014 at 07:26:51 UTC, Jacob Carlborg wrote: On 2014-01-30 05:42, Mike Parker wrote: All of the core.* modules are part of DRuntime, not Phobos. Unfortunately none of the core.stdc.* modules are documented. It's understandable that duplicating the documentation of the C library is not done since that would require extra work. But it would be nice to at least see which modules and declarations are available. I agree. Even if they are part of DRuntime, and even if there is no desire to write full documentation for them, people looking through the D site's Library Reference should at least be made aware of their existence.
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 13:43:49 UTC, Casper Færgemand wrote: Compiling with DMD 2.064, I am NOT able to get any function in interfaces accepted unless they are final. This means you cannot provide default behavior in the interface, at least not in the ways shown above. Yes the void baz() method is incorrect. The rest should be fine though.
Re: core.stdc.config
On Thursday, 30 January 2014 at 09:03:47 UTC, Gary Willoughby wrote: On Thursday, 30 January 2014 at 03:28:57 UTC, Craig Dillabaugh wrote: So, there is a module core.stdc.config (referenced here): http://dlang.org/interfaceToC.html That is presumably part of the D Standard library. I am curious to know why no mention of this library is included at: http://dlang.org/phobos/index.html Is it not part of Phobos? Are there standard modules in D that are not included in Phobos? If so, where would one find the list of these modules. The way i see what's available is to take a look at the files installed by the compiler. The directory is different for all operating systems but it's great to look at the source code of all the different modules. For example on Mac OSX 10.8.5 'core.stdc.config' is located at '/usr/share/dmd/src/druntime/src/core/stdc/config.d'. There you can see how the types are constructed and what they represent. For Linux just type 'locate config.d' in the terminal. For Windows it's all in 'C:\d' i think. I did as you suggested and had a look through what was on my system. Having done so I now think that the documentation at: http://dlang.org/phobos/index.html is out of date. If you look at the section under Imports, this appears to be describing what is available under from C, but it appears to suggest that you use std.c.config - or at least that is how I would have read it.
Re: N-body bench
Ok, didn't need to wait for the weekend :) Looks like both dmd and ldc don't optimize slice operations yet, had to revert to loops (shaved off ~1.5 seconds for ldc, ~9 seconds for dmd). Also, my local pull of ldc had some issues with to!int(string), reverted that to atoi :) Here's the code: http://dpaste.dzfl.pl/4b6df0771696 C++ version compiled with the provided flags. dmd -release -O -inline -noboundscheck ldc2 -release -O3 -disable-boundscheck -vectorize -vectorize-loops Here are the results on my machine (i3 2100 @3.1GHz): time ./nbody-cpp 5000: -0.169075164 -0.169059907 0:05.20 real, 5.18 user, 0.00 sys, 532 kb, 99% cpu time ./nbody-ldc 5000: -0.169075164 -0.169059907 0:07.84 real, 7.82 user, 0.00 sys, 1324 kb, 99% cpu time ./nbody-dmd 5000: -0.169075164 -0.169059907 0:23.35 real, 23.29 user, 0.00 sys, 1184 kb, 99% cpu
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 11:29:55 UTC, TheFlyingFiddle wrote: On Thursday, 30 January 2014 at 11:19:58 UTC, Frustrated wrote: I was, I think, able to call an interface's method. I had the code like the following interface A { void foo(); } class B : A { void foo() { writeln(Hey); } } class C : A { void foo() { writeln(You); } } yet, when I called a.foo(); I did not get any output. (A being of type A) Now, I was doing some weird stuff but either in the vtable for A, there are empty functions that do nothing or I just happen to call bogus memory that did not throw an exception. The real question is, do interface methods actually support function definitions? Is there anything that stops us from actually doing interface A { void foo() { writeln(What up!!); } } internally? I know member functions require a this but in this case foo does not require this so it any this would work. Basically, does the vtable contain storage for the interface's members but blocks us from using them due to the issue with this? If so, then shouldn't we be able to create functions in an interface as long as they do not reference this? (basically static functions that can be overriden as dynamic functions in the class) e.g., interface A { // default behavior for foo and bar void foo() { writeln(asdasdfasdfasdf); } void bar() { writeln(1234); } } class B : A { void foo() { writeln(help); } } void main() { A a = new B; a.foo(); // prints help a.bar(); // prints 1234 B b = new B; b.foo(); // prints help b.bar(); // prints 1234 } This would allow one to sort of add default behavior to an interface(limited since no fields could be used but properties help with it). basically the vtable just needs an extra spot for the interface methods and calls them with null or the object it contains for this... which doesn't matter since this is never used in the body of the function. You can already do this using the Non-virtual interface ideom interface Foo { final void bar() { writeln(Something); } void baz() { writeln(Something Else); } } Note the final keyword it is imortant here. This will make bar simply be a non-virutal method in Foo. If you want to provide some basic implementation but still forward to a base class you can do something like this. interface Foo2 { final void bar(uint i) { // Does some basic stuff here. bar_impl(i); } protected void bar_impl(uint i); } class A : Foo2 { protected void bar_impl(uint i) { //Do some specific stuff here. } } This pattern allows you to do some basic stuff in bar and more specialized stuff in bar_impl. It does require that you overload bar_impl though which may not be what you want. But this is not what I am talking about. Obviously one could use a multitude of ways to accomplish the same task but nothing is simple, direct, and elegant. Do you realize you have to define two functions in the interface? I'm not asking about a work around but if what I am talking about can actually be done(does the vtable support this or can made to support it?)
Re: N-body bench
On Thursday, 30 January 2014 at 14:17:16 UTC, Stanislav Blinov wrote: Forgot one slice assignment in toDobule2(). Now the results are more interesting: time ./nbody-cpp 5000: -0.169075164 -0.169059907 0:05.20 real, 5.18 user, 0.00 sys, 532 kb, 99% cpu time ./nbody-ldc 5000: -0.169075164 -0.169059907 0:05.94 real, 5.92 user, 0.00 sys, 1320 kb, 99% cpu time ./nbody-dmd 5000: -0.169075164 -0.169059907 0:19.62 real, 19.57 user, 0.00 sys, 1188 kb, 99% cpu :)
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 09:18:40 -0500, Cooler kul...@hotbox.ru wrote: Forgot to mention :) I read the rest of the discussion. Arrays are hard to understand in D, especially if you have preconceived notions from other languages. But I would point out that fun2 does not guarantee anything more than fun3: void fun2(ref int [] x) { fun3(x); } But I would point out that fun2 does not guarantee anything more than fun3: - fun2() cannot guarantee anything because it calls fun3() which in turn cannot guarantee anything. Right, but you said this: fun2(a); // Guaranteed that we will see any change to a, made in fun2() Which is false. That was my point. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 09:07:14 -0500, Cooler kul...@hotbox.ru wrote: If I don't want that fun() will change my array, i have to use fun1() variant. If I want fun() will change my array, i have to use fun2() variant. What fun2() do with it's argument inside it's body - not my business. No. You can use fun3 variant as well: void fun3(int[] x) { x[] = 0; // guaranteed to be seen by caller. } 1. For example somebody already implemented fun1() and fun2() variants, as in my first post. This variants understandable and predictable. What can push me to ask another person for fun3() implementation, while it result is unpredictable, until you know fun3() body? The only reason to have both fun2 and fun3 variants is if you want to handle both l-value and r-value options differently. There would be very few use cases which make sense AND return void. You usually want one or the other. 2. You wrote If your code must do otherwise, explain in the documentation what should happen. That exactly what I am trying to discuss here. Instead of writing some documentation, just warn (and may be prohibit in far-far future) about such possible unpredictability during compilation. No, because you are not understanding the effect of the attributes, and who is responsible for what. 1. Banning such signatures does NOT accomplish what you want. 2. Such signatures do NOT guarantee what happens inside the function. Having the compiler ban the problem where you expect the caller to see your changes, but they don't, is akin to just making the compiler able to detect all logic bugs. It's not possible (NP complete). The compiler just doesn't know what you really want to do. -Steve
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 14:31:05 UTC, Frustrated wrote: I'm not asking about a work around but if what I am talking about can actually be done(does the vtable support this or can made to support it?) It would work if you changed the interface to an abstract class.
Re: Interfaces allow member definitions?
On Thu, 30 Jan 2014 09:31:05 -0500, Frustrated c1514...@drdrb.com wrote: I'm not asking about a work around but if what I am talking about can actually be done(does the vtable support this or can made to support it?) Yes. Interfaces have no concrete vtable. Only classes do. A concrete class can decide what the vtable has in it, and if you had a default implementation, the compiler could stick that in there. Note that the default implementation only can call other member functions within the interface or module-level functions, interfaces cannot access any derived data or members. Whether such a change would be accepted? No clue. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 10:24:14 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 14:40:36 UTC, Dicebot wrote: On Thursday, 30 January 2014 at 13:42:53 UTC, Cooler wrote: If I use fun2() I expect that fun2() will change the content of my array, and all changes I will see. If I don't want any change to my array, I will use fun1(). What should I want to use fun3()? For changes to content of array but not array itself. I agree. I just want that the case can be expressed in language syntax more obvious - something like fun(int[] const x){} to emphasize that I understand that fun() can change content of array, and cannot change the {pointer,size} pair. That's what fun(int[] x) does :) -Steve
Re: N-body bench
Stanislav Blinov: Forgot one slice assignment in toDobule2(). Now the results are more interesting: Is the latest link shown the last version? I need the 0.13.0-alpha1 to compile the code. I am seeing a significant performance difference between C++ and D-ldc2. Bye, bearophile
Re: Array as an argument, ambiguous behaviour.
On Thursday, 30 January 2014 at 15:49:35 UTC, Cooler wrote: I agree. I just want that the case can be expressed in language syntax more obvious - something like fun(int[] const x){} to emphasize that I understand that fun() can change content of array, and cannot change the {pointer,size} pair. That's what fun(int[] x) does :) -Steve Again... void fun(int[] x){ x ~= 5; } auto a = new int[10]; fun(a); // Can you predict the content of 'a'? It's [0, 0, 0, 0, 0, 0, 0, 0, 0, 0].
How to call opCall as template?
Here: http://dlang.org/operatoroverloading.html#FunctionCall is this example: import std.stdio; struct F { int opCall() { return 0; } int opCall(int x, int y, int z) { return x * y * z; } } void main() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = f.opCall(3,4,5); } And it works of course. But what if I want to templatize opCall? How can I call it? import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable
import expression with paths
This does not compile on Windows, but does compile on Mac: --- module main; void main() { import std.path; enum bar = import(`dir` ~ dirSeparator ~ `bar.txt`); } --- The docs say: http://dlang.org/expression.html#ImportExpression Implementations may restrict the file name in order to avoid directory traversal security vulnerabilities. A possible restriction might be to disallow any path components in the file name. So, I suppose it's valid code. But it's still surprising to encounter. Should it not simply be disallowed completely?
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 10:49:34 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 15:29:50 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 10:24:14 -0500, Cooler kul...@hotbox.ru wrote: On Thursday, 30 January 2014 at 14:40:36 UTC, Dicebot wrote: I agree. I just want that the case can be expressed in language syntax more obvious - something like fun(int[] const x){} to emphasize that I understand that fun() can change content of array, and cannot change the {pointer,size} pair. That's what fun(int[] x) does :) -Steve Again... void fun(int[] x){ x ~= 5; } auto a = new int[10]; fun(a); // Can you predict the content of 'a'? I suspect you mean: void fun(int[] x) {x.length += 1; x[0] = 5;} I cannot predict what the caller will see. But this is not a problem of *signatures*. The caller will not see ANY changes to {pointer,size} pair of x. That is the point -- it's passed by value. Note that this implementation is completely predictable: void fun(int[] x) {x[0] = 5; x.length += 1;} I want to stress that just because you can find an implementation that has a bug doesn't mean that there is an opportunity for the compiler to detect that bug, especially a logic bug. The compiler simply cannot know what you are thinking. In your case: void fun(int[] x){ x = [1, 2]; } // Compilation ok. Implementation's error. The fun() implementer made error and think that caller will get new array. But it will get it only at runtime! If we for example (just for example) have void fun(int[] const x){ x = [1, 2]; } // Compilation error. I see very little value in that. We don't need to obliterate a tremendous amount of slice usage (not mentioning how much code will have to be updated) in order to help newbies understand how slices work. -Steve
Re: How to call opCall as template?
void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable f.opCall!float(6, 7, 8);
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote: void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable f.opCall!float(6, 7, 8); ... Yes, of course. But where is the sense to use opCall if I need to call it explicitly?
Re: N-body bench
Stanislav Blinov: You mean with your current version of ldc? Yes. The older version of LDC2 doesn't even compile the code. I need to use 0.13.0-alpha1. Your D code with small changes: http://codepad.org/xqqScd42 Asm generated by G++ for the advance function (that is the one that uses most of the run time): http://codepad.org/tApRNsVy Asm generated by ldc2: http://codepad.org/jKSJcOAZ With N = 5_000_000 my timings on an old CPU are 2.23 seconds for ldc2 and 1.83 seconds for g++. So there's some performance difference. I have tried to unroll manually the loop in the D code, but I see worse performance. I'll try some more later. Bye, bearophile
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 16:28:42 UTC, Namespace wrote: On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote: void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable f.opCall!float(6, 7, 8); ... Yes, of course. But where is the sense to use opCall if I need to call it explicitly? Could you not use opDispatch? Not sure if you can templatize it or not though...
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 16:47:46 UTC, Frustrated wrote: On Thursday, 30 January 2014 at 16:28:42 UTC, Namespace wrote: On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote: void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable f.opCall!float(6, 7, 8); ... Yes, of course. But where is the sense to use opCall if I need to call it explicitly? Could you not use opDispatch? Not sure if you can templatize it or not though... Example? I did not know how.
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 15:28:24 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 09:31:05 -0500, Frustrated c1514...@drdrb.com wrote: I'm not asking about a work around but if what I am talking about can actually be done(does the vtable support this or can made to support it?) Yes. Interfaces have no concrete vtable. Only classes do. A concrete class can decide what the vtable has in it, and if you had a default implementation, the compiler could stick that in there. Note that the default implementation only can call other member functions within the interface or module-level functions, interfaces cannot access any derived data or members. Whether such a change would be accepted? No clue. -Steve Basically I see no reason why the compiler can't treat the interface as a class and allow default methods. (it would have to allow multiple inheritance on that class though) All it would do is make it easy to provide a default implementation(more of a static implementation but allows it to be overriden, which makes it useful). For example, when creating a design you would no longer have to specifically create a corresponding class to use for the interface. You could just provide some default implementations of everything(throw errors, write stuff, etc...) I think it would be probably rather easy to do by extending the vtable to have one lower level, the interface methods, which, in fact, could use this(so you could have a this in them but only reference other members of the interface). Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. Of course, maybe this just creates the diamond problem for interfaces: which default implementation to use... which I'm not sure if it's a problem?
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 15:59:28 UTC, Namespace wrote: Here: http://dlang.org/operatoroverloading.html#FunctionCall is this example: import std.stdio; struct F { int opCall() { return 0; } int opCall(int x, int y, int z) { return x * y * z; } } void main() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = f.opCall(3,4,5); } And it works of course. But what if I want to templatize opCall? How can I call it? import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable This is probably a bug. You should file it in Bugzilla.
Re: N-body bench
On Thursday, 30 January 2014 at 16:53:22 UTC, bearophile wrote: Yes. The older version of LDC2 doesn't even compile the code. I need to use 0.13.0-alpha1. Hmm. Your D code with small changes: http://codepad.org/xqqScd42 That won't compile with dmd (at least, with 2.064.2): it expects constants as initializers for vectors. :( That's why I rolled up that toDouble2() function. With N = 5_000_000 my timings on an old CPU are 2.23 seconds for ldc2 and 1.83 seconds for g++. So there's some performance difference. What about 50_000_000? I have tried to unroll manually the loop in the D code, but I see worse performance. I'll try some more later. I'm also fiddling :)
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 11:48:50 -0500, Cooler kul...@hotbox.ru wrote: Please understand - I am not against void foo(int[] x){} From an earlier post by you: May be just prohibit at language level the case of fun3() function, to do not allow unpredictable behavior? I thought that this meant you were against it? I am for predictability of behavior. 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. You cannot eradicate all errors. The intentions of a function are not apparent to the compiler. Maybe the intention is to use the argument as a buffer, and the caller should not care what happens to the buffer inside the function. Adding yet another attribute is going to increase language complexity for almost no benefit. It does not guarantee unambiguity because you have no idea what the author of the function is going to do. The D principle - The program compile and runs as expected, or not compile at all. This is a fantasy. The compiler cannot know what you expect. 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. Not sure if something is mixed up there. I think void fun(int[] x) is sufficient to describe what you say. The function cannot alter x's array bounds at all, and can alter it's data. I see very little value in that. We don't need to obliterate a tremendous amount of slice usage (not mentioning how much code will have to be updated) in order to help newbies understand how slices work. Any idea can be rejected by this sentence. No, only ideas that force people to change millions of lines of code, and provide scant benefits instead of taking 5 minutes to explain no, just use x[0..2] = [1, 2] or just use ref int[] x depending on the goal. -Steve
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 12:07:07 -0500, Cooler kul...@hotbox.ru 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! Difference is here. void foo(int x){} - the caller will NEVER see any change to 'x'. void foo(int[] x){} - the caller MAY or MAY NOT see changes to 'x'. This is incorrect: foo(int[] x){} - The caller will see changes to data 'x' references. A slice is a reference type, it references a specific block of data. It's more akin to a pointer than an int. I could change my example: void foo(int *x) { int n = 3; x = n; } hey, why doesn't x now point to 3? Should be illegal! -Steve
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: Interfaces allow member definitions?
On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated c1514...@drdrb.com wrote: Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. -Steve
Re: core.stdc.config
On Thursday, 30 January 2014 at 14:10:37 UTC, Craig Dillabaugh wrote: I did as you suggested and had a look through what was on my system. Having done so I now think that the documentation at: http://dlang.org/phobos/index.html is out of date. If you look at the section under Imports, this appears to be describing what is available under from C, but it appears to suggest that you use std.c.config - or at least that is how I would have read it. The 'std.c.*' modules are just publicly importing 'core.stdc.*' modules and AFAIK discouraged as it gives the impression they are part of Phobos. Using 'core.stdc.*' is informing other developers this is core runtime stuff. Forget 'std.c.*', use 'core.stdc.*'. And you are right, the documentation needs a big update!
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 17:11:24 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated c1514...@drdrb.com wrote: Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. -Steve Right, this was my original point and why I thought there was already entries for the interface in the vtable(since I seemed to have called some function that did nothing when it should have). It seems so simple and offers some benefit(would at the very least stop requiring one to implement a class every time they want test a design. When programming to interfaces and using some type of factory it makes even more sense. It then could also be used to test is something is implemented(possibly for versioning). e.g., interface A { void hasSomeFeature() { assert(0, Not implemented yet); } } Someone can come along and implement the feature and you(the interface) knows it's implemented if it doesn't assert, set a flag, or whatever. Are you 100% sure no default space is created for the vtable? (trying to reconcile why that case I mentioned worked. I'll try to throw an example up... may have just been coincidence I didn't get a segfault)
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 16:53:33 UTC, Namespace wrote: On Thursday, 30 January 2014 at 16:47:46 UTC, Frustrated wrote: On Thursday, 30 January 2014 at 16:28:42 UTC, Namespace wrote: On Thursday, 30 January 2014 at 16:24:00 UTC, Stanislav Blinov wrote: void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable f.opCall!float(6, 7, 8); ... Yes, of course. But where is the sense to use opCall if I need to call it explicitly? Could you not use opDispatch? Not sure if you can templatize it or not though... Example? I did not know how. doesn't seem to work with templates, I suppose you could try and add it as a feature request? module main; import std.stdio; interface A { void foo(); static final New() { } } class B : A { void foo() { writeln(this is B.foo); } void opDispatch(string s, T)(int i) { writefln(C.opDispatch('%s', %s), s, i); } } void main() { B a = new B; //a.foo(); a.test!int(3); // any *good* reason why this shouldn't work? }
Re: Interfaces allow member definitions?
On Thu, 30 Jan 2014 12:30:04 -0500, Frustrated c1514...@drdrb.com wrote: On Thursday, 30 January 2014 at 17:11:24 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated c1514...@drdrb.com wrote: Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. -Steve Right, this was my original point and why I thought there was already entries for the interface in the vtable(since I seemed to have called some function that did nothing when it should have). I think your original example should not have happened. Either there was a bug in the runtime, compiler, or your memory :) It seems so simple and offers some benefit(would at the very least stop requiring one to implement a class every time they want test a design. When programming to interfaces and using some type of factory it makes even more sense. This is a misunderstanding, you still need to declare a class, because an interface is not a concrete type. But if there are default implementations for all the interface functions, you don't need to implement any of them! It then could also be used to test is something is implemented(possibly for versioning). e.g., interface A { void hasSomeFeature() { assert(0, Not implemented yet); } } Someone can come along and implement the feature and you(the interface) knows it's implemented if it doesn't assert, set a flag, or whatever. Are you 100% sure no default space is created for the vtable? (trying to reconcile why that case I mentioned worked. I'll try to throw an example up... may have just been coincidence I didn't get a segfault) I didn't write the compiler, so I'm not 100%, but I'm 99% sure :) -Steve
Re: N-body bench
Stanislav Blinov: That won't compile with dmd (at least, with 2.064.2): it expects constants as initializers for vectors. :( That's why I rolled up that toDouble2() function. I see. Then probably I will have to put it back... With N = 5_000_000 my timings on an old CPU are 2.23 seconds for ldc2 and 1.83 seconds for g++. So there's some performance difference. What about 50_000_000? First let me try to fiddle with the code some more :-) Once done, this should go somewhere (like the wiki) as a simple example of SIMD usage in D. Bye, bearophile
Re: How to call opCall as template?
Also, http://dlang.org/operatoroverloading.html#Dispatch and possible solution to your problem: http://www.digitalmars.com/d/archives/digitalmars/D/opDispatch_and_template_parameters_117095.html Couldn't get code to compile though... but if it did, it should solve your problem.
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 16:55:01 UTC, Meta wrote: On Thursday, 30 January 2014 at 15:59:28 UTC, Namespace wrote: Here: http://dlang.org/operatoroverloading.html#FunctionCall is this example: import std.stdio; struct F { int opCall() { return 0; } int opCall(int x, int y, int z) { return x * y * z; } } void main() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = f.opCall(3,4,5); } And it works of course. But what if I want to templatize opCall? How can I call it? import std.stdio; struct F { T opCall(T = int)(int a, int b, int c) { return cast(T)(a * b * c); } } void main() { F f; int i = f(3,4,5); float f_ = f!float(6, 7, 8); } Does not work, it fails with: Error: template instance f!float f is not a template declaration, it is a variable This is probably a bug. You should file it in Bugzilla. Ok, done: https://d.puremagic.com/issues/show_bug.cgi?id=12043
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 12:38:57 -0500, Cooler kul...@hotbox.ru wrote: The D principle - The program compile and runs as expected, or not compile at all. This is a fantasy. The compiler cannot know what you expect. The language is needed to express your intentions to the compiler. Anything that the compiler cannot enforce is just documentation. Does it matter whether the documentation is in a comment or part of the signature? The language should be expressive as possible. My point is to push programmers to write correct software. I just ask these forum to think about topic. If everybody satisfied by void fun(int[] x){} behavior, then I just go... I'm not trying to be a bully or anything, but you are not understanding that what you want is a guarantee of logic, that the compiler cannot possibly enforce. Your example (setting a variable to another value) being rejected is easy to work around, just use another variable that doesn't have that restriction. There are so many examples of behavior-enforcing features that result in something that the creator of the feature didn't want or expect. Keep in mind there are years of projects that have been written assuming that you can use a standard slice in the signature of a function, we don't want to invalidate all that code just because programmers sometimes write buggy code. But I encounter a bug in my program that was due to my misusing of such signature. Here's where the gray area is. If you make this error once or twice, but never again, is it worth changing the language over? Probably not. But if you make this error every day, even KNOWING what will happen, it's worth looking into. But any changes have to avoid a negative impact on existing code as much as possible. Think of the person who knows how slices work, who very seldom makes this mistake, and who now has to go through all his code and make this change, never finding an instance where it makes a difference. At this point, I'm not sure what you are proposing, but I don't think there is much value in changing the way slice passing works. 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. Not sure if something is mixed up there. I think void fun(int[] x) is sufficient to describe what you say. The function cannot alter x's array bounds at all, and can alter it's data. Here is the reason why i post the topic on this forum. You think one way, I think another way. I wanted to discuss what think other people. But looks like still nobody can understand my point, or may be I cannot express it... By mixed up, I meant that you seemed to be valuing the int[] x version over the int[] const x version. Other than that, what I stated is an indisputable fact -- the function cannot alter x's bounds. -Steve
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 17:46:19 UTC, Frustrated wrote: Also, http://dlang.org/operatoroverloading.html#Dispatch and possible solution to your problem: http://www.digitalmars.com/d/archives/digitalmars/D/opDispatch_and_template_parameters_117095.html Couldn't get code to compile though... but if it did, it should solve your problem. opDispatch is called if you try to call a non existing member. But in this case you don't call a member. ;)
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 18:11:49 UTC, Frustrated wrote: BTW, a() is replaced with a.opCall() and you can use opDispatch on it. an opCall is a member. Either approach should work if you can get that archive example to compile. I am sure that the error is thrown before. But please show me your attempts.
Re: Interfaces allow member definitions?
On Thu, 30 Jan 2014 13:06:30 -0500, Frustrated c1514...@drdrb.com wrote: On Thursday, 30 January 2014 at 17:38:26 UTC, Steven Schveighoffer wrote: This is a misunderstanding, you still need to declare a class, because an interface is not a concrete type. But if there are default implementations for all the interface functions, you don't need to implement any of them! No, the point is, if all methods are defined, there is no need to create the class. Why create an empty class to instantiate it when the compiler can do it for you and you can instantiate the interface? This is what I mean by treating the interface as a class because for all purposes it is. (an interface is just an abstract container but it doesn't have to be) Again, all this could be done by the compiler internally by creating a class to back an interface and add it to the vtable. Instantiating the interface just returns that class. Calling a member on the interface's object calls the member of that class, who's body is provided in the interface definition. I can do this now, the whole point is I don't like code duplication! ;) interface A { void foo() { writeln(me); } void bar(); } class _A // created internally by compiler { void foo() { writeln(me); } // added by compiler copied from A void bar() { assert(0, error); } // added by compiler } http://dlang.org/phobos/std_typecons.html#.BlackHole -Steve
Re: Interfaces allow member definitions?
On Thu, 30 Jan 2014 13:16:21 -0500, Steven Schveighoffer schvei...@yahoo.com wrote: http://dlang.org/phobos/std_typecons.html#.BlackHole Sorry, black hole just does nothing. it's white hole you want: http://dlang.org/phobos/std_typecons.html#.WhiteHole -Steve
Re: N-body bench
Stanislav Blinov: That won't compile with dmd (at least, with 2.064.2): it expects constants as initializers for vectors. :( That's why I rolled up that toDouble2() function. Few more changes, but this version still lacks the toDouble2: http://codepad.org/SpMprWym Bye, bearophile
Re: N-body bench
On Thursday, 30 January 2014 at 18:29:42 UTC, bearophile wrote: I see you're compiling with ldmd2 -wi -O -release -inline -noboundscheck nbody.d Try ldc2 -release -O3 -disable-boundscheck -vectorize -vectorize-loops
Re: N-body bench
Stanislav Blinov: Looks like both dmd and ldc don't optimize slice operations yet, had to revert to loops It's a very silly problem for a statically typed language. The D type system knows the static length of those arrays, but it doesn't use such information. (Similarly several algorithms in Phobos force to throw away this very precious compile-time information requiring dynamic arrays in input.) I have just suggested a fix for ldc2: http://forum.dlang.org/thread/qeytzeqnygxpocywy...@forum.dlang.org I have a similar enhancement request since some time in Bugzilla: https://d.puremagic.com/issues/show_bug.cgi?id=10523 https://d.puremagic.com/issues/show_bug.cgi?id=10305 Bye, bearophile
Re: Array as an argument, ambiguous behaviour.
On Thu, 30 Jan 2014 13:58:55 -0500, Cooler kul...@hotbox.ru wrote: The D principle - The program compile and runs as expected, or not compile at all. This is a fantasy. The compiler cannot know what you expect. The language is needed to express your intentions to the compiler. Anything that the compiler cannot enforce is just documentation. Does it matter whether the documentation is in a comment or part of the signature? Why we need const keyword, while we can just put I promise do not change it in the documentation? const is only useful in cases where references are involved. In this case, you want to make the *copied* data constant, in hopes that you then can't accidentally stop referencing the original. In another example, there is little to be gained from a signature such as: void foo(const int x); What does this say about foo? Nothing. I can pass in a mutable, const, or immutable int, because a copy is made. It doesn't provide any more guarantees to the caller than: void foo(int x); Likewise, your proposed int[] const would not guarantee anything extra to the caller beyond int[], because both are copies put onto the stack. The function has no access to the original values. Arrays in D are hard to understand. They don't behave like arrays in most other languages. But they foster a different mindset I think, that results in some of the fastest code on the planet. But one has to understand the semantics of syntax if they want to properly use the language. For functions which append/extend and then write data to the prior piece (the only non-deterministic case), special care has to be taken to explain this to the caller. I would think a mechanism to attempt detecting this and flagging it would be a worthy lint tool feature. But not a language or compiler feature. There is just simply no way to say that is always bad or that you know what the intentions of the author are. The other case you specified, when the author re-assigns a slice and expects it to be a memcpy or to re-bind the calling parameter, the result is deterministically the wrong result, and the coder will notice it right away (and hopefully correct their understanding). I don't think we need a language feature for that, just documentation (which I think we have). Let me also suggest you use scope statements to verify at runtime that the case you intend to prevent doesn't actually happen: void foo(int[] x) { const origx = x; scope(exit) assert(origx.ptr == x.ptr); ... } While not perfect, and not static, it should at least avoid subtle bugs (and can be turned off in release mode). -Steve
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 17:11:24 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated c1514...@drdrb.com wrote: Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. -Steve But what if you want to provide some default behavior? We are not dealing with abstract classes here. Since there is currently no way to do what I am saying no solution will be adequate unless it fulfills the behavior. (again, it's not like we can't accomplish basically the same thing, the point is mainly about simplification) The question was about if there was any innate reason why this type of behavior couldn't be accomplish using the vtable. I'm assuming there is none and it could easily be done? (the compiler just has to reserve the space and setup the pointers to the functions?)
Re: N-body bench
On Thursday, 30 January 2014 at 18:43:02 UTC, bearophile wrote: It's a very silly problem for a statically typed language. The D type system knows the static length of those arrays, but it doesn't use such information. I agree. Unrolling everything except the loop in energy() seems to have squeezed the bits neede to outperform c++, at least on my machine :) http://dpaste.dzfl.pl/45e98e476daf (I'm sticking to atoi because my copy of ldc seems to have an issue in std.conv). time ./nbody-cpp 5000: -0.169075164 -0.169059907 0:05.15 real, 5.14 user, 0.00 sys, 532 kb, 99% cpu time ./nbody-ldc 5000: -0.169075164 -0.169059907 0:04.41 real, 4.40 user, 0.00 sys, 1308 kb, 99% cpu time ./nbody-dmd 5000: -0.169075164 -0.169059907 0:15.39 real, 15.34 user, 0.00 sys, 1192 kb, 99% cpu
Re: Idiomatic D?
On Thursday, 30 January 2014 at 20:05:11 UTC, Tofu Ninja wrote: I hear it thrown around a lot but what does it actually mean? What does the ideal D code look like? What kind of things should some one think about if they are trying to do idiomatic D? There is no official idiomatic style like, for example, in python. When I speak about idiomatic D I usually think about style Phobos is written in (omitting legacy modules) as it is the code that gets most attention from most experienced D developers.
Idiomatic D?
I hear it thrown around a lot but what does it actually mean? What does the ideal D code look like? What kind of things should some one think about if they are trying to do idiomatic D?
Re: Is continuously seeding a random number generator performance intensive?
On Tuesday, 21 January 2014 at 19:00:32 UTC, Jeroen Bollen wrote: On Tuesday, 21 January 2014 at 17:51:44 UTC, monarch_dodra Is that your actual code? MersenneTwisterEngine(seed) is not valid code, you have to provide the template arguments. I meant to answer to this by the way, sorry. (in need of edit feature :P ) https://d.puremagic.com/issues/show_bug.cgi?id=11960 Now resolved fixed.
Re: Interfaces allow member definitions?
On Thu, 30 Jan 2014 14:58:42 -0500, Frustrated c1514...@drdrb.com wrote: On Thursday, 30 January 2014 at 17:11:24 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated c1514...@drdrb.com wrote: Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. -Steve But what if you want to provide some default behavior? We are not dealing with abstract classes here. Since there is currently no way to do what I am saying no solution will be adequate unless it fulfills the behavior. (again, it's not like we can't accomplish basically the same thing, the point is mainly about simplification) The question was about if there was any innate reason why this type of behavior couldn't be accomplish using the vtable. I'm assuming there is none and it could easily be done? (the compiler just has to reserve the space and setup the pointers to the functions?) The interface defines the vtable, the class contains a value for that vtable. If you imagine an interface vtable like this: interface A { void foo(); } = struct A_vtbl { void function() foo; } Note the default value is NULL. When you create a class that inherits, it's class info contains an A_vtbl: class B : A { void foo() {writeln(hi;} } = struct B_typeinfo { A_vtbl a_interface = {B.foo}; } And when you call foo on an instance of A, it uses the vtable, knowing that the layout is A_vtbl. (this is simplistic, the real thing is more complex to explain, it's somewhere on the docs). What I'm saying is, if you give a default to the function foo, then our straw-man A_vtbl looks like this: struct A_vtbl { void function() foo = A.default_foo; } And when you create B_typeinfo, if you haven't defined foo, it just points at that default foo (of course, you have to fill in B.foo, and for that, you actually have to do a thunk to convert to the interface I think, but this is not hard). But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at. -Steve
Re: How to call opCall as template?
import std.stdio; struct B { template opCall(T) { void opCall(T x) { writeln(x); } } } template a(T) { } void main() { B a; a(3); // works because template parameter can be deduced from arguments a.opCall!(int)(3); // same as about but explicit a!(int)(3); // works but calls template because a! refers to a template // no way to use the above syntax to initiate an opCall on a because it is template notation. // at most one might get away with a.!(int)(3) but this is invalid } You'll never be able to do a!()() for the reasons give above. At most it would have to be implemented the compiler and I doubt it will ever happen. (for example, one could have the opExclamation but then one has ambiguity, which is why ! was chosen to avoid in the first place) I think for your example, the first case works fine using deduction.
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 20:17:23 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 14:58:42 -0500, Frustrated c1514...@drdrb.com wrote: On Thursday, 30 January 2014 at 17:11:24 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated c1514...@drdrb.com wrote: Essentially what it boils down to is treating interfaces like classes that have no fields). To avoid the diamond problem simply always choose the method that is not from the interface(since it is default), which is done naturally with the vtable. It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. -Steve But what if you want to provide some default behavior? We are not dealing with abstract classes here. Since there is currently no way to do what I am saying no solution will be adequate unless it fulfills the behavior. (again, it's not like we can't accomplish basically the same thing, the point is mainly about simplification) The question was about if there was any innate reason why this type of behavior couldn't be accomplish using the vtable. I'm assuming there is none and it could easily be done? (the compiler just has to reserve the space and setup the pointers to the functions?) The interface defines the vtable, the class contains a value for that vtable. If you imagine an interface vtable like this: interface A { void foo(); } = struct A_vtbl { void function() foo; } Note the default value is NULL. When you create a class that inherits, it's class info contains an A_vtbl: class B : A { void foo() {writeln(hi;} } = struct B_typeinfo { A_vtbl a_interface = {B.foo}; } And when you call foo on an instance of A, it uses the vtable, knowing that the layout is A_vtbl. (this is simplistic, the real thing is more complex to explain, it's somewhere on the docs). What I'm saying is, if you give a default to the function foo, then our straw-man A_vtbl looks like this: struct A_vtbl { void function() foo = A.default_foo; } And when you create B_typeinfo, if you haven't defined foo, it just points at that default foo (of course, you have to fill in B.foo, and for that, you actually have to do a thunk to convert to the interface I think, but this is not hard). But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at. -Steve But what I think you are failing to realize is that regardless that foo is defined in an interface, since foo does not use this, it does not depend on the object, so it does not need an object(for all practical purposes it is a static function but of course must take an object as the first parameter so it is compatible as a member function). Also, regardless that it is an interface, doesn't mean it can't have a concrete vtable to work with. The fact is that a vtable is more complex because it has the ability to call functions defined in a base class. In this case a base interface. Just because something doesn't exist there now doesn't mean it can't exist. Answer me this class A { void foo() { } } class B : A { } B b = new B; b.foo(); are you telling me there are actually two foo functions? or does b actually call A's foo passing it the object b e.g., the call made is actually foo(b); If so, then what if A is an interface? (by interface, I am talking about one that has a vtable created for it's members) interface A { void foo() { } } class B : A { } B b = new B; b.foo(); Whats the difference? Absolutely nothing but your interpretation of what an interface is. This is all about semantics. If you want to think of an interface as some idealized abstract compile time object that doesn't exist at run time and has no vtable then so be it. But that doesn't mean it has to be and I'm just saying it is limiting. Obviously the difference between the two above is that the compiler does not allow multiple inheritance w.r.t, to classes, and does not allow fields in interfaces, etc... but these rules can still be enforced on a class THAT HAS A VTABLE. I think you still keep trying to fit the square peg in the round hole. I'm not talking about what the compiler does... we know the above code as I intend it does not work.
Re: N-body bench
Stanislav Blinov: Unrolling everything except the loop in energy() seems to have squeezed the bits neede to outperform c++, at least on my machine :) That should be impossible, as I remember from my old profilings that energy() should use only an irrelevant amount of run time. http://dpaste.dzfl.pl/45e98e476daf While I benchmark some variants of this program I am seeing a large variety of problems, limitations, bugs and regressions. You latest D code crashes my ldc2 V.0.12.1, while 0.13.0-alpha1 compiles it. My older version of your D code runs with both compiler versions, but V.0.12.1 generates faster code. Plus you can't make those double2 immutable, you can't use vector ops (because of performance, and also because they aren't nothrow in V.0.12.1). I was also experimenting with (note the align): align(16) struct Body { double[3] x, v; double mass; } struct NBodySystem { private: __gshared static Body[5] bodies = [ // Sun. Body([0., 0., 0.], [0., 0., 0.], solarMass), ... But this improves the code for V.0.12.1 and worsens it for 0.13.0-alpha1. Also I think the __gshared is ignored in V.0.12.1, but this bug could be fixed in more recent versions of ldc2. (I'm sticking to atoi because my copy of ldc seems to have an issue in std.conv). My version seems to use to!() correctly. If ldc2 developers are reading this thread there is enough strange stuff here to give one or two headaches :-) Now I don't know what final version should I keep of this program :-) Bye, bearophile
Re: N-body bench
Stanislav Blinov: ldc2 -release -O3 -disable-boundscheck -vectorize -vectorize-loops All my versions of ldc2 don't even accept -vectorize :-) ldc2: Unknown command line argument '-vectorize'. Try: 'ldc2 -help' ldc2: Did you mean '-vectorize-slp'? And -vectorize-loops should be active on default on recent versions of ldc2 (including V.0.12.1), and indeed I see no performance difference in using it. Bye, bearophile
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 21:16:05 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 15:57:06 -0500, Frustrated c1514...@drdrb.com wrote: On Thursday, 30 January 2014 at 20:17:23 UTC, Steven Schveighoffer wrote: But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at. But what I think you are failing to realize is that regardless that foo is defined in an interface, since foo does not use this, it does not depend on the object, so it does not need an object(for all practical purposes it is a static function but of course must take an object as the first parameter so it is compatible as a member function). But what if it does need an object? interface A { void foo() { bar();} // need 'this' to call bar void bar(); } I've said many times that the functions could not use this. If you are going to go that far then why not allow interfaces to have fields? In this case they would not be any different from classes. Also, regardless that it is an interface, doesn't mean it can't have a concrete vtable to work with. The fact is that a vtable is more complex because it has the ability to call functions defined in a base class. In this case a base interface. Just because something doesn't exist there now doesn't mean it can't exist. Keep in mind that an interface vtable exists as part of an object. The compiler knows this, and performs thunks when necessary. Answer me this class A { void foo() { } } class B : A { } B b = new B; b.foo(); are you telling me there are actually two foo functions? or does b actually call A's foo passing it the object b e.g., the call made is actually foo(b); There is one function, but two vtables, one for A, and one for B. Both point at the same function. Yes, and they could point to the function defined in the interface. When they call it, they would pass themselves as this. The methods in the interface do not use this, so it doesn't matter (they could potentially use it but it would require that it always be valid) If so, then what if A is an interface? (by interface, I am talking about one that has a vtable created for it's members) interface A { void foo() { } } class B : A { } B b = new B; b.foo(); Whats the difference? Absolutely nothing but your interpretation of what an interface is. The difference is, now there is only one vtable, and one interface vtable inside B. A has no vtables. If you do this: A a = new B; a now points at the interface struct *inside B's object*. When you call a.foo, it does this: 1. It looks up in the interface vtable for A that's specific for B (accessed via the interface struct in the object itself) to get the function to call. 2. Included in the interface vtable struct is an offset to add so the 'this' pointer actually points at the object itself instead of the interface struct. Who says A doesn't have a vtable? That's something that you are forcing on it. You have to get off that if we are ever to make any headway. This is all about semantics. If you want to think of an interface as some idealized abstract compile time object that doesn't exist at run time and has no vtable then so be it. But that doesn't mean it has to be and I'm just saying it is limiting. An interface instance and an object instance are two VERY different things, and are handled differently by the compiler. -Steve Again, you have to get off of what has been defined. You have the mentality exactly the same as those that thought the earth was flat, imaginary numbers were nonsense/useless, man couldn't go to the moon. If you define your knowledge on what you already know what is the point? You just run around in circles nothing changes you'll just continue believing the earth is flat...
Re: Array as an argument, ambiguous behaviour.
On Wednesday, 29 January 2014 at 10:55:57 UTC, Cooler wrote: Consider 3 functions taking array as an argument: void fun1(in int[] x){...} void fun2(ref int[] x){...} void fun3(int[] x){...} auto a = new int[10]; fun1(a); // Guaranteed that a will not be changed fun2(a); // Guaranteed that we will see any change to a, made in fun2() fun3(a); // Changes to a in fun3() may be or may be not visible to the caller In case of fun3() we have ambiguous behaviour, depending on the body of the function. Am I right? Is that intentional? I believe what you are asking for is head const. D does not do this, search for head const dlang and you'll probably find some discussion in it.
Symbol undefined
I'm starting to use D out of curiousity. I've used both Eclipse + DDT and Visual Studio + visualD and both give the same error in my second test program (second to Hello World of course...) using the Transmogrifier/CardboardBox example from TDPL : Error 42: Symbol Undefined _D1a14Transmogrifier12transmogrifyMFZv (void a.Transmogrifier.transmogrify()) Am I not linking module a (containing Transmogrifier and CardboardBox)? How can I get either or both IDE's running my test program?
Re: Interfaces allow member definitions?
Simple question. What are the difference between an interface and a class? I'm not talking about what the compiler does with them. I'm talking about what they were created to do, how they came about etc. If you have to explain to someone what a class is and what an interface is, then you diff that, what is your answer? vtables should not show up in your explanation(they would if I didn't mention it and it shows that you are stuck on the implementation aspect and can't see the forest).
Re: N-body bench
On Thursday, 30 January 2014 at 21:04:06 UTC, bearophile wrote: Stanislav Blinov: Unrolling everything except the loop in energy() seems to have squeezed the bits neede to outperform c++, at least on my machine :) That should be impossible, as I remember from my old profilings that energy() should use only an irrelevant amount of run time. I meant that if I unroll it, it's not irrelevant anymore :) While I benchmark some variants of this program I am seeing a large variety of problems, limitations, bugs and regressions... :) You latest D code crashes my ldc2 V.0.12.1, while 0.13.0-alpha1 compiles it. :)) My older version of your D code runs with both compiler versions, but V.0.12.1 generates faster code. :))) Plus you can't make those double2 immutable, you can't use vector ops (because of performance, and also because they aren't nothrow in V.0.12.1). Well, not being able to make them immutable is not *that* big of a problem now, is it? What would be actually cool to have are those slice operations. I was also experimenting with (note the align): align(16) struct Body { double[3] x, v; double mass; } struct NBodySystem { private: __gshared static Body[5] bodies = [ // Sun. Body([0., 0., 0.], [0., 0., 0.], solarMass), Yeah... I've even thrown away that filler in the latest version :o) But this improves the code for V.0.12.1 and worsens it for 0.13.0-alpha1. %| (I'm sticking to atoi because my copy of ldc seems to have an issue in std.conv). My version seems to use to!() correctly. I'm using the git head (704ab3, last commit Sun Jan 26 00:00:21). I haven't tried the release yet. If ldc2 developers are reading this thread there is enough strange stuff here to give one or two headaches :-) Indeed. Now I don't know what final version should I keep of this program :-) I was going to compare the asm listings, but C++ seems to have unrolled and inlined the outer loop right inside main(), and now I'm slightly lost in it :)
Re: Symbol undefined
On 01/30/2014 01:28 PM, Martijn Pot wrote: I'm starting to use D out of curiousity. I've used both Eclipse + DDT and Visual Studio + visualD and both give the same error in my second test program (second to Hello World of course...) using the Transmogrifier/CardboardBox example from TDPL : Error 42: Symbol Undefined _D1a14Transmogrifier12transmogrifyMFZv (void a.Transmogrifier.transmogrify()) Am I not linking module a (containing Transmogrifier and CardboardBox)? How can I get either or both IDE's running my test program? You must include a.d on the build line. dmd a.d main.d ... Ali
Re: How to call opCall as template?
I think for your example, the first case works fine using deduction. Sure but this is not always possible. ;) It seems that the problem occurs also with opIndex and so probably with all op* methods. See: http://forum.dlang.org/thread/bug-1204...@https.d.puremagic.com%2Fissues%2F#post-lcegar:241ld2:241:40digitalmars.com
Re: Symbol undefined
On Thursday, 30 January 2014 at 21:28:08 UTC, Martijn Pot wrote: Error 42: Symbol Undefined _D1a14Transmogrifier12transmogrifyMFZv (void a.Transmogrifier.transmogrify()) Typically that means the function isn't implemented, e.g. this: void transmogrify(); instead of this: void transmogrify() { } The NVI examples in TDPL don't really work, as private functions in D are currently not virtual. You could try pasting example code of what you're trying to build to show you exactly what goes wrong.
Re: N-body bench
Stanislav Blinov: I meant that if I unroll it, it's not irrelevant anymore :) If a function takes no time to run, and you tweak it, your program is not supposed to go faster. I was going to compare the asm listings, but C++ seems to have unrolled and inlined the outer loop right inside main(), and now I'm slightly lost in it :) Try using -fkeep-inline-functions. Bye, bearophile
Re: Interfaces allow member definitions?
On Thu, 30 Jan 2014 16:23:55 -0500, Frustrated c1514...@drdrb.com wrote: Again, you have to get off of what has been defined. You have the mentality exactly the same as those that thought the earth was flat, imaginary numbers were nonsense/useless, man couldn't go to the moon. OK, then. With that, I shall retire from this discussion :) -Steve
Re: N-body bench
On Thursday, 30 January 2014 at 21:33:38 UTC, bearophile wrote: If a function takes no time to run, and you tweak it, your program is not supposed to go faster. Right. I was going to compare the asm listings, but C++ seems to have unrolled and inlined the outer loop right inside main(), and now I'm slightly lost in it :) Try using -fkeep-inline-functions. Thanks. G++: http://codepad.org/oOZQw1VQ LDC: http://codepad.org/5nHoZL1k LDC basically generated something that I can only call one straight *whsh*... This reminds me Andrei's talk on (last years?) GoingNative (more instructions is not always slower code).
Re: N-body bench
Stanislav Blinov: G++: http://codepad.org/oOZQw1VQ LDC: http://codepad.org/5nHoZL1k You seem to have a quite recent CPU, as the G++ code contains instructions like vmovsd. So you can try to do the same with ldc2, and use AVX or AVX2. There are the switches: -march=string- Architecture to generate code for: -mattr=a1,+a2,-a3,...- Target specific attributes (-mattr=help for details) -mcpu=cpu-name - Target a specific cpu type (-mcpu=help for details) LDC basically generated something that I can only call one straight *whsh*... :-) Bye, bearophile
Re: Symbol undefined
On 1/30/14, Martijn Pot martijnpo...@gmail.com wrote: Indeed, making them public solved the problem. Is there more stuff in the book that isn't working? Check the errata page[1], which coincidentally seems to be down. I'll CC Andrei. [1]: http://erdani.com/tdpl/errata/index.php?title=Main_Page Another more-recent book (and a free one) is this: http://ddili.org/ders/d.en/index.html
Re: N-body bench
On Thursday, 30 January 2014 at 21:54:17 UTC, bearophile wrote: You seem to have a quite recent CPU, An aging i3? as the G++ code contains instructions like vmovsd. So you can try to do the same with ldc2, and use AVX or AVX2. Hmm... This is getting a bit silly now. I must have some compile switches for g++ wrong: g++ -Ofast -fkeep-inline-functions -fomit-frame-pointer -march=native -mfpmath=sse -mavx -mssse3 -flto --std=c++11 -fopenmp nbody.cpp -o nbody-cpp time ./nbody-cpp 5000: -0.169075164 -0.169059907 0:05.09 real, 5.07 user, 0.00 sys, 1140 kb, 99% cpu ldc2 -release -O3 -disable-boundscheck -vectorize -vectorize-loops -ofnbody-ldc -mattr=+avx,+ssse3 nbody.d time ./nbody-ldc 5000: -0.169075164 -0.169059907 0:04.02 real, 4.01 user, 0.00 sys, 1304 kb, 99% cpu
Re: Symbol undefined
On 1/30/14, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: On 1/30/14, Martijn Pot martijnpo...@gmail.com wrote: Indeed, making them public solved the problem. Is there more stuff in the book that isn't working? Check the errata page[1], which coincidentally seems to be down. I'll CC Andrei. [1]: http://erdani.com/tdpl/errata/index.php?title=Main_Page Another more-recent book (and a free one) is this: http://ddili.org/ders/d.en/index.html I CC'ed the wrong address, re-sending.
Re: How to call opCall as template?
On Thursday, 30 January 2014 at 21:33:09 UTC, Namespace wrote: I think for your example, the first case works fine using deduction. Sure but this is not always possible. ;) It seems that the problem occurs also with opIndex and so probably with all op* methods. See: http://forum.dlang.org/thread/bug-1204...@https.d.puremagic.com%2Fissues%2F#post-lcegar:241ld2:241:40digitalmars.com Yes, because they all are implicit. It looks like you are calling a template. D could figure this out but I think it will end up having similar issues as has in C++. Is it an a templated op* on an object or is it template function call?
Re: N-body bench
Stanislav Blinov: An aging i3? My CPU is older, it doesn't support AVX2 and AVX. This is getting a bit silly now. I must have some compile switches for g++ wrong: g++ -Ofast -fkeep-inline-functions -fomit-frame-pointer -march=native -mfpmath=sse -mavx -mssse3 -flto --std=c++11 -fopenmp nbody.cpp -o nbody-cpp time ./nbody-cpp 5000: -0.169075164 -0.169059907 0:05.09 real, 5.07 user, 0.00 sys, 1140 kb, 99% cpu ldc2 -release -O3 -disable-boundscheck -vectorize -vectorize-loops -ofnbody-ldc -mattr=+avx,+ssse3 nbody.d time ./nbody-ldc 5000: -0.169075164 -0.169059907 0:04.02 real, 4.01 user, 0.00 sys, 1304 kb, 99% cpu Now the ldc2-compile runs in 4 seconds, this sounds correct. If you have paid for a CPU with AVX2 or AVX, it's right to use that :-) Bye, bearophile
Re: Interfaces allow member definitions?
On Thursday, 30 January 2014 at 21:42:39 UTC, Steven Schveighoffer wrote: On Thu, 30 Jan 2014 16:23:55 -0500, Frustrated c1514...@drdrb.com wrote: Again, you have to get off of what has been defined. You have the mentality exactly the same as those that thought the earth was flat, imaginary numbers were nonsense/useless, man couldn't go to the moon. OK, then. With that, I shall retire from this discussion :) -Steve It would be nice if you could understand what I'm getting at but it's like I keep telling you the earth and you don't believe me ;) Almost surely we are arguing about different things. Mine is more syntax substitution and yours is more implementation. In any case, it doesn't matter because it will never be implemented the way I think it could be so we are just wasting our time(or I'm wasting yours, how ever you want to see it ;)
Re: Idiomatic D?
On Thursday, 30 January 2014 at 20:10:01 UTC, Dicebot wrote: On Thursday, 30 January 2014 at 20:05:11 UTC, Tofu Ninja wrote: I hear it thrown around a lot but what does it actually mean? What does the ideal D code look like? What kind of things should some one think about if they are trying to do idiomatic D? There is no official idiomatic style like, for example, in python. When I speak about idiomatic D I usually think about style Phobos is written in (omitting legacy modules) as it is the code that gets most attention from most experienced D developers. Got any tips?
Re: N-body bench
Since my post someone has added a Fortran version based on the algorithm used in the C++11 code. It's a little faster than the C++11 code and it's much nicer looking: http://benchmarksgame.alioth.debian.org/u32/program.php?test=nbodylang=ifcid=5 pure subroutine advance(tstep, x, v, mass) real*8, intent(in) :: tstep real*8, dimension(4,nb), intent(inout) :: x, v real*8, dimension(nb), intent(in) :: mass real*8 :: r(4,N),mag(N) real*8 :: distance, d2 integer :: i, j, m m = 1 do i = 1, nb do j = i + 1, nb r(1,m) = x(1,i) - x(1,j) r(2,m) = x(2,i) - x(2,j) r(3,m) = x(3,i) - x(3,j) m = m + 1 end do end do do m = 1, N d2 = r(1,m)**2 + r(2,m)**2 + r(3,m)**2 distance = 1/sqrt(real(d2)) distance = distance * (1.5d0 - 0.5d0 * d2 * distance * distance) !distance = distance * (1.5d0 - 0.5d0 * d2 * distance * distance) mag(m) = tstep * distance**3 end do m = 1 do i = 1, nb do j = i + 1, nb v(1,i) = v(1,i) - r(1,m) * mass(j) * mag(m) v(2,i) = v(2,i) - r(2,m) * mass(j) * mag(m) v(3,i) = v(3,i) - r(3,m) * mass(j) * mag(m) v(1,j) = v(1,j) + r(1,m) * mass(i) * mag(m) v(2,j) = v(2,j) + r(2,m) * mass(i) * mag(m) v(3,j) = v(3,j) + r(3,m) * mass(i) * mag(m) m = m + 1 end do end do do i = 1, nb x(1,i) = x(1,i) + tstep * v(1,i) x(2,i) = x(2,i) + tstep * v(2,i) x(3,i) = x(3,i) + tstep * v(3,i) end do end subroutine advance Bye, bearophile
Re: Magic infinite loop inside foreach
On Thursday, 30 January 2014 at 22:56:46 UTC, MrSmith wrote: I have some function which does some matrix calculations and prints them. It is actually calculationg determinant of the matrix and i need to call those functions several times in the loop, until i get the final result. Here is the code. void solveAndPrint(T : CoeffMatrix!(ElementType, ElementType), ElementType)(T _matrix) { auto matrix = _matrix; TempMatrix!ElementType temp; foreach(_; 0..3) //3 is just for debug { writeln(matrix); temp = makeTemp(matrix); writeln(temp); matrix = solveTemp(temp); writeln(done1); stdout.flush(); } writeln(done2); stdout.flush(); } The problem is that after 'done1' is printed it is running infinitely consuming all the processor just like if has infinite loop inside. done2 is never printed. Somehow if i comment out //matrix = solveTemp(temp); it works, but this method works fine, and after it done1 is printed. Strange.
Re: Magic infinite loop inside foreach
On 01/30/2014 03:08 PM, MrSmith wrote: On Thursday, 30 January 2014 at 22:56:46 UTC, MrSmith wrote: I have some function which does some matrix calculations and prints them. It is actually calculationg determinant of the matrix and i need to call those functions several times in the loop, until i get the final result. Here is the code. void solveAndPrint(T : CoeffMatrix!(ElementType, ElementType), ElementType)(T _matrix) { auto matrix = _matrix; TempMatrix!ElementType temp; foreach(_; 0..3) //3 is just for debug { writeln(matrix); temp = makeTemp(matrix); writeln(temp); matrix = solveTemp(temp); Does that mutate temp in any way? If so, probably the change is affecting how solveTemp() works the next time. writeln(done1); stdout.flush(); } writeln(done2); stdout.flush(); } The problem is that after 'done1' is printed it is running infinitely consuming all the processor just like if has infinite loop inside. done2 is never printed. Somehow if i comment out //matrix = solveTemp(temp); it works, but this method works fine, and after it done1 is printed. Strange. Ali
Re: N-body bench
On Thursday, 30 January 2014 at 22:45:45 UTC, bearophile wrote: Since my post someone has added a Fortran version based on the algorithm used in the C++11 code. It's a little faster than the C++11 code and it's much nicer looking: Yup, I saw it. They're cheating, they almost don't have to explicitly handle any SSE business :o) I'm wondering how our little code could perform on that machine. It looks nice too, by the way: http://dpaste.dzfl.pl/a81a475bbcf6 I've rearranged some bits, brought back to!int (turned out there wasn't any issues, it's just that ldc generated errors regarding to! when there were other compiler errors %\), replaced TypeTuples with your Iota... the works :)
Re: Magic infinite loop inside foreach
On 31/01/14 00:08, MrSmith wrote: Somehow if i comment out //matrix = solveTemp(temp); it works, but this method works fine, and after it done1 is printed. Strange. That does rather suggest that it's that method that is causing things to get stuck. Can you share what's inside it? And when you say this method works fine, do you mean that you've manually tested it with the temp variable that goes in before it hangs? Could it be that whatever printout you're doing of variables like matrix is missing some tiny differences -- floating-point rounding errors? -- that are responsible for the transformations inside makeTemp or solveTemp behaving wrongly and therefore (in the latter case) getting stuck?
Re: Idiomatic D?
On Friday, 31 January 2014 at 00:08:02 UTC, Meta wrote: On Thursday, 30 January 2014 at 22:40:24 UTC, Tofu Ninja wrote: Got any tips? Ranges, templates and structs. ~= CTFE ~ UFCS