Re: opAssign and references
On 01/31/2012 06:15 PM, Nicolas Silva wrote: Hi, Works for me. Which version of the compiler are you using? Sorry, i forgot to mention: i'm using dmd 2.057 on ubuntu 32bit. I am using DMD 2.057 on Ubuntu 64bit. Are you sure that it does not work? Can anyone reproduce the error? import std.variant; struct Foo { Variant a; ref Variant refA(){ return a; } } void main(){ Foo f1; f1.refA() = 24; }
Re: floating-WTF - Compiler-BUG with 64bit
On 01/28/2012 04:56 PM, sclytrack wrote: On 01/25/2012 01:12 AM, Timon Gehr wrote: On 01/24/2012 10:28 PM, %u wrote: Shouldn't this go into 'digitalmars.D' ? It should go straight to the bug tracker. Issue 7391 - floating wtf dmd 2.057 64 Thanks!
Re: Using Clang with D
On 01/26/2012 08:44 PM, Jacob Carlborg wrote: On 2012-01-26 10:29, Jacob Carlborg wrote: I'm trying to port a simple example that uses Clang from C to D but for some reason the D version results in a segmentation fault. This is the C code: http://pastebin.com/4B2JGz9n This is the D code: http://pastebin.com/XPBsSVup The stacktrace from GDB looks like this: (gdb) r Starting program: /Users/jacob/development/d/dstep/bin/dstep NSObject.h Reading symbols for shared libraries .+.. done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0004 0x000100104139 in clang_formatDiagnostic () (gdb) bt #0 0x000100104139 in clang_formatDiagnostic () #1 0x00011648 in _Dmain () #2 0x00010001baa5 in D2rt6dmain24mainUiPPaZi7runMainMFZv () #3 0x00010001b671 in D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv () #4 0x00010001baf7 in D2rt6dmain24mainUiPPaZi6runAllMFZv () #5 0x00010001b671 in D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv () #6 0x00010001b5f4 in main () I'm using DMD 2.057 on Mac OS X compiling as 64bit. Any idea what I have done wrong? I've now found out that I only get this error when compiling as 64bit. When I compile as 32bit everything works fine. It is possibly an error in the bindings. What are the C and D declarations of the methods you are using?
Re: Invalid bounding interval [, ]
On 01/25/2012 12:28 PM, C wrote: auto chunk = new ubyte[1024]; foreach(ref x; chunk) x = uniform![](ubyte.min, ubyte.max); Thank you all for your replies. @ Timon, I have two questions: 1) How come you can omit parentheses for uniform's parameter, shouldn't it be uniform!([])(...) ? If there is only one template argument, parentheses can be omitted. 2) Does auto chunk = new ubyte[1024]; ALWAYS create a dynamic array with changeable length? That is a silly question but the syntax confuses me. Yes it does. But this works too and is probably more intuitive if you are not familiar with other C-derived languages: auto chunk = new ubyte[](1024);
Re: Invalid bounding interval [, ]
On 01/25/2012 04:50 AM, bearophile wrote: C: I want to fill a ubyte array with random data. In D ubytes are not char, they are two different types. So if you want ubytes, then use ubytes: uniform!([])(ubyte.min, ubyte.max) Regarding your error, a reduced test case: import std.random: uniform; void main() { uniform!([])(char.min, char.max); uniform!((])(char.min, char.max); } Bye, bearophile Even more reduced test case and bug report: http://d.puremagic.com/issues/show_bug.cgi?id=7367
Re: Invalid bounding interval [, ]
On 01/25/2012 04:25 AM, C wrote: I want to fill a ubyte array with random data. The code compiles with no warnings or errors. Source snippet: auto prng = Random(unpredictableSeed); ubyte[] chunk; chunk.length = 1024; fill(chunk, uniform!([])('\x00', '\xFF', prng)); Error (at runtime): object.Exception@c:\dmd2\windows\bin\..\..\src\phobos\std\random.d(971): std.random.uniform(): invalid bounding interval [ , �] 423C50 423AC7 404EA8 404EEC 404AE3 4A6109 Also I lost the URL for this forum, all I see is this nasty PHP News Reader interface. Thank you. The code wouldn't do what you intended even if it compiled. Use this: auto chunk = new ubyte[1024]; foreach(ref x; chunk) x = uniform![](ubyte.min, ubyte.max);
Re: Meaning of const
On 01/25/2012 02:29 AM, H. S. Teoh wrote: On Tue, Jan 24, 2012 at 08:01:41PM -0500, bearophile wrote: Jonathan M Davis: Now, the confusing part is the fact that unlike C++, D allows you to put the const for making the function on the _left-hand_ side of the function (C++ only lets you put it on the right). This is to increase consistency between modifers (public, override, pure, etc.) - they _all_ can go on both the right and left (which is very unfortunate in the case of const and immutable IMHO). That means that const (and immutable) always modify the function rather than the return value unless you use parens. Some time ago we have discussed this topic in an enhancement request in Bugzilla. The idea was to disallow code like: struct Foo { int x; const const(int) bar() { return 0; } } void main() {} and require the struct const, immutable to be only on the right if present. Walter shot this idea down for consistency. But I generally don't want consistency when it's just a potential source of confusion for the programmer :-) [...] How can this be consistency? For example: class A { const int x; @property const int y(); } Now you have typeof(A.x)==const(int) and typeof(A.y)==int. Seems quite inconsistent to me. But since Walter doesn't like the idea of restricting the syntax to 'int y() const', then what about making it mandatory to write: const(int) x; instead of: const int x; ? You essentially propose to remove the const/immutable/shared/inout storage classes for variables. It would break almost every D program and I don't see many benefits. Requiring the parentheses is a bit extreme, I admit, but it touches upon another area of D syntax that I don't quite like, and that is const or immutable applied to arrays: const(int)[] x; // array of const(int) const(int[]) x; // const array of int const int[] x; // ??? const array of const int? Or one // of the above? const(int[]). The storage class of a declaration applies to the whole declaration. It gets worse when you throw in ref: Ref does not change anything but the calling convention *of the function*. The reference itself cannot be rebound, there is no syntax for it. ref int f();// returns int* (I think?) ref const(int) f(); // returns const(int)* (?) ref const int f(); // ??? const ref int f(): // ??? The last line is quite bad. Is the return type const(int*) or const(int)*, or is it just int* (i.e., const applies to f not the return value)? It is int. ref const(int)[] x; // ref to array of const(int)? Note that ref can only be on a function or on a parameter. const(ref int)[] x; // array of refs to int? No such thing exists. const ref int[] x; // array of ??? const(int[]). Declaration is invalid, would have to be a parameter. const ref int[] x();// const function that returns ref int[]? It returns int[], by reference. It is equivalent to int[] x()const ref; Though most people will prefer to have 'ref' on the lhs: ref int[] x()const; It still applies to the function though. const const ref int[] x(); // const function returning what? Redundant storage class const. ref int[] x()const const; is the same thing. The more I think about this, the more confusing it becomes. It is very simple. What may be confusing you is that const/immutable/shared/inout are both type constructors and storage classes. If parentheses were mandatory after const, things would be much, much better: const(ref int) x; const(ref const(int)) x; ... etc. Much clearer to me. It is not to me. This is not valid syntax. Also, types of the general form const(...const(...)...) don't make a lot of sense. Const is transitive.
Re: Meaning of const
On 01/26/2012 12:35 AM, H. S. Teoh wrote: On Wed, Jan 25, 2012 at 11:50:57PM +0100, Timon Gehr wrote: On 01/25/2012 02:29 AM, H. S. Teoh wrote: [...] But since Walter doesn't like the idea of restricting the syntax to 'int y() const', then what about making it mandatory to write: const(int) x; instead of: const int x; ? You essentially propose to remove the const/immutable/shared/inout storage classes for variables. It would break almost every D program and I don't see many benefits. [...] It is very simple. What may be confusing you is that const/immutable/shared/inout are both type constructors and storage classes. [...] Ah, I see. This is very helpful. So what's the difference between a const int type, and an int variable with const storage class? I think this is the key issue. The syntax makes this distinction non-obvious, IMHO, which is very confusing. The syntax is clear on it: If it is followed by parentheses, it is a type constructor. Otherwise it is a storage class. This ambiguity also shows up in function definitions (allowing storage classes to appear left or right of the function name/parameters), which we discussed earlier. From what I can tell, Walter doesn't want to change this, but I have to say that this is one part of D I find unnecessarily confusing. For variables, the storage class just implies that the type will be wrapped in the respective type constructor. The storage class still 'talks' about the whole declaration though. A key application is for type deduction: immutable a = foo(); Foo may return something mutable, and a will automatically have it's type deduced to the respective immutable type. Storage classes always apply to the whole declaration they refer to. It is _not_ const intx; and const int foo; but: constint x; and const int foo(){}
Re: actors library?
On 01/24/2012 07:51 PM, xancorreu wrote: Al 24/01/12 13:37, En/na Dejan Lekic ha escrit: Xan, read this article please: http://www.informit.com/articles/article.aspx?p=1609144 You have exactly what you are looking for in the D runtime and standard library. I read it and **after** I post the question. I don't know how std.concurrency is related to actors model. Can you enlight me? Thanks, Xan. std.concurrency is an implementation of the actor model. 'Actor model' does not imply 'Object Oriented'. Example 1: import std.stdio, std.concurrency; void myActor() { try { for(;;){ receive( (int i){ writeln(Received integer: ,i); } ); } }catch(Exception e){ // cleanup } } void main() { auto actor = spawn(myActor); foreach(i;0..10) actor.send(i); } Example 2: import std.stdio, std.concurrency; import core.thread; alias Thread.sleep sleep; void ping() { Tid pong; try { for(;;){ receive( (string s){ writeln(ping received ,s); sleep(dur!seconds(1)); pong.send(ping); }, (Tid newPong){ pong = newPong; } ); } }catch(Exception e){} } void pong(Tid ping) { try { ping.send(pong); for(;;){ receive( (string s){ writeln(pong received ,s); sleep(dur!seconds(1)); ping.send(pong); } ); } }catch(Exception e){} } void main() { auto a1 = spawn(ping); auto a2 = spawn(pong,a1); a1.send(a2); sleep(dur!seconds(10)); }
Re: floating-WTF - Compiler-BUG with 64bit
On 01/24/2012 10:28 PM, %u wrote: Shouldn't this go into 'digitalmars.D' ? It should go straight to the bug tracker.
Re: for loop
On 01/23/2012 07:06 PM, bearophile wrote: Ellery Newcomer: void main(){ for ({int x=0; short y=0;} x 10; x++, y++){ } } I don't understand, is that a compiler bug? Aren't x and y in a sub-scope that ends before you use x and y? Bye, bearophile It is not a bug. ForStatement: for (Initialize Testopt ; Incrementopt) ScopeStatement Initialize: ; NoScopeNonEmptyStatement Initialize is NoScope.
Re: actors library?
On 01/23/2012 08:01 PM, Xan xan wrote: Hi. Is there any actors library in D. Spawn and etc is ok, but I want more high-level thing and actors it's the best I get, I think. I searched and nothing. I'm interested in D 2.0 or 1.0. Whatever! Thanks in advace, Xan. std.concurrency is an actors library. What exactly do you mean when you say more high-level?
Re: no-argument constructor: is this a bug?
On 01/23/2012 12:51 AM, Caligo wrote: struct A(uint samples){ float[samples] _data = void; this(float val = 0.0f){ fill(_data[], val); } } auto a = A!8(); a._data is filled with garbage instead of zeros because the no-argument constructor is called instead of the one that I've defined. structs are always default-constructible, and, as a tie-breaker, a function definition that has the exact number of arguments is considered a better match one that has to supply default-arguments to match. You could use a static opCall to make auto a = A!8() work.
Re: Passing arguments to a new thread
On 01/20/2012 03:12 PM, Mars wrote: Hello everybody. As the title states, I want to run a function in a new thread, and pass it some arguments. How would I do that? I guess I could make a class, deriving from Thread, and work with it, but out of curiosity, I'd like to know if it's possible with a simple function. Mars See std.concurrency. auto tid = spawn(function, arg1, arg2, arg3, ...);
Re: Changes for newer version...
On 01/19/2012 09:30 PM, Era Scarecrow wrote: Been a bit out of it for a while, but finding enough tools at my disposal I feel I can work on/convert a project now. I happen to have one of the first printing books (without the name on the cover), and although it may be worth millions in a few years, apparently there's been enough changes that certain features are not familiar in the discussions. So I need to ask since I don't see any obvious pages that describe it. What are the changes to D2, since the book's release? What has externally changed? (Internal implementation of features need not be mentioned if it's transparent to the programmer and user). The most important changes are probably: - inout type qualifier The type qualifier inout can be used as a wildcard to stand for any of mutable, const, immutable. Its meaning is automatically deduced and is the same throughout a certain function definition or function call. For example: inout(int)[] identity(inout(int)[] x){return x;} int[] x; immutable(int)[] y; const(int)[] z; static assert(is(typeof(identity(x)) == int[])); static assert(is(typeof(identity(y)) == immutable(int)[])); static assert(is(typeof(identity(z)) == const(int)[])); - function local imports void main(){ import std.stdio; writeln(hello world!); } - new function/delegate literal syntax (coming DMD 2.058) identifier = expression or (id1, id2) = expression or (type id1, type id2) = expression import std.stdio, std.range, std.algorithm; void main(){ writeln(some odd squares:); writeln(map!(x=x^^2)(filter!(x=x1)(iota(1,1000; }
Re: tdpl: function literals versus delegate lierals
On 01/19/2012 05:41 PM, Jerome BENOIT wrote: Hello List: On my box, the following D source, inspired by the subsection 5.6.1 of tDpl, does not work as expected: - // adhoc_06.d import std.stdio; unittest { // Tersest, most convenient code auto f = (int i) {}; writeln(typeid(f)); assert(is(f == function)); } void main() {} - I get: void delegate() core.exception.AssertError@adhoc_06.d(7): unittest failure According to the book, the assertion is true and f is a function but not a literal. What is going wrong ? Thanks in advance, Jerome Many things, actually. You are looking at both an error in TDPL and a compiler bug. The compiler bug is already fixed in git head and will not exist in the next release. See http://d.puremagic.com/issues/show_bug.cgi?id=3235 In the line: auto f = (int i) {}; f is deduced as void delegate(int) pure nothrow @safe instead of as void function(int) pure nothrow @safe. This is the compiler bug that has been fixed. In the line: assert(is(f == function)); TDPL contains an error. Is expressions can be used to query some properties of types. If an involved type is not a well-formed type the result is false. Since f is a variable and not a type, the is expression yields false. is(T == function) tests whether or not T is a function type. Therefore, the line should actually read is(typeof(*f)==function), as f is a function pointer. I am not very happy about this particular quirk of is expressions: void delegate() dg; // declares a delegate void function() fp; // declares a function _pointer_ assert( is(typeof(dg) == delegate)); assert(!is(typeof(fp) == function)); // the is expression tests whether it is a function, not whether it is a function pointer assert(is(typeof(*fp) == function)); You may want to use std.traits.IsFunctionPointer and std.traits.IsDelegate instead.
Re: Reading web pages
On 01/19/2012 04:30 PM, Xan xan wrote: Hi, I want to simply code a script to get the url as string in D 2.0. I have this code: //D 2.0 //gdmd-4.6 import std.stdio, std.string, std.conv, std.stream; import std.socket, std.socketstream; int main(string [] args) { if (args.length 2) { writeln(Usage:); writeln( ./aranya {url1,url2, ...}); return 0; } else { foreach (a; args[1..$]) { Socket sock = new TcpSocket(new InternetAddress(a, 80)); scope(exit) sock.close(); Stream ss = new SocketStream(sock); ss.writeString(GET ~ a ~ HTTP/1.1\r\n); writeln(ss); } return 0; } } but when I use it, I receive: $ ./aranya http://www.google.com std.socket.AddressException@../../../src/libphobos/std/socket.d(697): Unable to resolve host 'http://www.google.com' What fails? Thanks in advance, Xan. The protocol specification is part of the get request. ./aranaya www.google.com seems to actually connect to google. (it still does not work fully, I get back 400 Bad Request, but maybe you can figure it out)
Re: Switch and break
On 01/19/2012 10:55 PM, RenatoL wrote: Just curious: why in D we are not obligated to use break in every branch of a swicth structure? That is: switch (i) { case 1: writeln(You wrote 1); case 2: writeln(You wrote 2); case 3: writeln(You wrote 3); default: writeln(I said: 1 or 2 or 3!); } is good in D, while, for example, similar code in C# is incorrect and if you want to play with fall through you have to make some trick. Again this behaviour of D seems a bit buggy, to me. Are there design reasons? Compile with -w enabled and the compiler will complain about implicit fall-through. You can use goto case/goto default for explicit fall-through.
Re: Pure functions and delegates
On 01/18/2012 04:40 AM, H. S. Teoh wrote: So, I was quite impressed with D's pureness system, and was experimenting a bit with it. Then I discovered that delegates are impure, which seems reasonable since there's no way to know what a delegate might do. But *if* the compiler verifies that a particular delegate is (weakly) pure in the context of the function that passed it, then couldn't the function that it gets passed to be declared pure as well? The context is this: class MyCollection { ... void opApply(int delegate(const ref int n) cb) const { ... if (cb(...)) { ... } ... } ... int[] enumerate() { int[] list; foreach (n; this) { list ~= n; } return list; } } Is there a way to convince the compiler that enumerate() can be marked 'pure' even though opApply() can't, in general, be pure because it doesn't know what the delegate does? Technically, enumerate() is weakly pure, because its delegate does not touch anything outside of its scope, and given this particular delegate, opApply() also is weakly pure. In other words, opApply()'s pureness depends on the delegate passed to it. So if there was a way for the compiler to check that yes, opApply() is (weakly) pure except for the part that calls the delegate (perhaps using some kind of conditionally pure attribute?), then it should, in theory, be possible to verify that yes, the delegate that enumerate() passes to opApply() does not violate pureness, so enumerate() can be labelled 'pure'. The trouble is, given the current state of things, there is no way to implement enumerate() in a pure way, short of duplicating most of opApply()'s code and substituting the line that calls the delegate. Which is a rather ugly workaround. But otherwise, MyCollection cannot be used inside a (strongly) pure function unless it avoids using opApply() and enumerate() altogether, even if the container never escapes the pure function's scope. This is quite a major limitation IMHO. T I see two distinct issues here: 1. int foo(int delegate(int) dg,x){return dg(x);} int bar(int x)pure{foo(x=x,x);} // error but would be ok 2. int foo(int x)pure{ int x; (y=x=y)(2); // error but would be ok return x; } 1. could be resolved by a simple purity wildcard, in the lines of inout. (auto pure? =)) 2. could be resolved by extending the weakly pure rule to the context pointer of nested functions. Nested functions and delegates would need to be able to be declared 'const'. (indicating that they are not allowed to mutate anything through the context pointer.) delegate literals and nested template function instantiations would need const inference.
Re: tdpl: partial ordering of functions: conflict error
On 01/18/2012 02:32 PM, Jerome BENOIT wrote: On 18/01/12 04:36, Jonathan M Davis wrote: On Wednesday, January 18, 2012 02:33:25 Jerome BENOIT wrote: And I cannot figure why :-( http://d.puremagic.com/issues/show_bug.cgi?id=1528 As a workaround, templatize the last function by changing its signature to int[] find()(int[] longer, int[] shorter) actually it does not work either: gdmd gives an other error message now. T[] find(T, E)(T[] haystack, E needle) if (is(typeof(haystack[0] != needle) == bool)) { while (haystack.length 0 haystack[0] != needle) { haystack = haystack[1 .. $]; } return haystack; } TL[] find(TL, TS)(TL[] longer, TS[] shorter) if (is(typeof(longer[0 .. 1] == shorter) : bool)) { while (longer.length = shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer=longer[1 .. $]; } return longer; } int[] find()(int[] longer, int[] shorter) { while (longer.length = shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer=longer[1 .. $]; } return longer; } unittest { // Test the introduced overloads long[] a1 = [ 6, 1, 2, 3 ]; long[] a2 = [ 1 , 2 ]; int[] b1 = [ 6, 1, 2, 3 ]; int[] b2 = [ 1 , 2 ]; assert(find(a1, a2) == a1[1 .. $]); assert(find(a1, b2) == a1[1 .. $]); assert(find(b1, b2) == b1[1 .. $]); } void main() {} The message is now: searching_05.d:34: Error: template searching_05.find(T,E) if (is(typeof(haystack[0] != needle) == bool)) find(T,E) if (is(typeof(haystack[0] != needle) == bool)) matches more than one template declaration, searching_05.d(9):find(TL,TS) if (is(typeof(longer[0..1] == shorter) : bool)) and searching_05.d(18):find() Is partial ordering really supported ? Yes it is, and your code snippet indeed compiles on my machine. Are you maybe using an outdated version of the compiler?
Re: tdpl: partial ordering of functions: conflict error
On 01/18/2012 04:57 PM, Timon Gehr wrote: On 01/18/2012 02:32 PM, Jerome BENOIT wrote: On 18/01/12 04:36, Jonathan M Davis wrote: On Wednesday, January 18, 2012 02:33:25 Jerome BENOIT wrote: And I cannot figure why :-( http://d.puremagic.com/issues/show_bug.cgi?id=1528 As a workaround, templatize the last function by changing its signature to int[] find()(int[] longer, int[] shorter) actually it does not work either: gdmd gives an other error message now. T[] find(T, E)(T[] haystack, E needle) if (is(typeof(haystack[0] != needle) == bool)) { while (haystack.length 0 haystack[0] != needle) { haystack = haystack[1 .. $]; } return haystack; } TL[] find(TL, TS)(TL[] longer, TS[] shorter) if (is(typeof(longer[0 .. 1] == shorter) : bool)) { while (longer.length = shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer=longer[1 .. $]; } return longer; } int[] find()(int[] longer, int[] shorter) { while (longer.length = shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer=longer[1 .. $]; } return longer; } unittest { // Test the introduced overloads long[] a1 = [ 6, 1, 2, 3 ]; long[] a2 = [ 1 , 2 ]; int[] b1 = [ 6, 1, 2, 3 ]; int[] b2 = [ 1 , 2 ]; assert(find(a1, a2) == a1[1 .. $]); assert(find(a1, b2) == a1[1 .. $]); assert(find(b1, b2) == b1[1 .. $]); } void main() {} The message is now: searching_05.d:34: Error: template searching_05.find(T,E) if (is(typeof(haystack[0] != needle) == bool)) find(T,E) if (is(typeof(haystack[0] != needle) == bool)) matches more than one template declaration, searching_05.d(9):find(TL,TS) if (is(typeof(longer[0..1] == shorter) : bool)) and searching_05.d(18):find() Is partial ordering really supported ? Yes it is, and your code snippet indeed compiles on my machine. Are you maybe using an outdated version of the compiler? Nevermind, I forgot to pass the -unittest switch. It indeed gives that error. The reason it still does not compile is that the workaround proposed by Jonathan has slightly different semantics than it would have if the compiler already supported overloading of functions against function templates. If exactly one of two equally good matched functions is a templated one, the other one is chosen. Now that you have templated the second function, both are an equally good match and both are templated. If you change the last signature to int[] find(TL:int[], TS:int[])(TL longer, TS shorter) It will compile. However, if TL or TS are user-defined types with an alias this of type int[], the semantics are still different. I think this bug needs special attention.
Re: tdpl: partial ordering of functions: conflict error
On 01/18/2012 05:40 PM, Jerome BENOIT wrote: On 18/01/12 17:07, Timon Gehr wrote: On 01/18/2012 04:57 PM, Timon Gehr wrote: On 01/18/2012 02:32 PM, Jerome BENOIT wrote: On 18/01/12 04:36, Jonathan M Davis wrote: On Wednesday, January 18, 2012 02:33:25 Jerome BENOIT wrote: And I cannot figure why :-( http://d.puremagic.com/issues/show_bug.cgi?id=1528 As a workaround, templatize the last function by changing its signature to int[] find()(int[] longer, int[] shorter) actually it does not work either: gdmd gives an other error message now. T[] find(T, E)(T[] haystack, E needle) if (is(typeof(haystack[0] != needle) == bool)) { while (haystack.length 0 haystack[0] != needle) { haystack = haystack[1 .. $]; } return haystack; } TL[] find(TL, TS)(TL[] longer, TS[] shorter) if (is(typeof(longer[0 .. 1] == shorter) : bool)) { while (longer.length = shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer=longer[1 .. $]; } return longer; } int[] find()(int[] longer, int[] shorter) { while (longer.length = shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer=longer[1 .. $]; } return longer; } unittest { // Test the introduced overloads long[] a1 = [ 6, 1, 2, 3 ]; long[] a2 = [ 1 , 2 ]; int[] b1 = [ 6, 1, 2, 3 ]; int[] b2 = [ 1 , 2 ]; assert(find(a1, a2) == a1[1 .. $]); assert(find(a1, b2) == a1[1 .. $]); assert(find(b1, b2) == b1[1 .. $]); } void main() {} The message is now: searching_05.d:34: Error: template searching_05.find(T,E) if (is(typeof(haystack[0] != needle) == bool)) find(T,E) if (is(typeof(haystack[0] != needle) == bool)) matches more than one template declaration, searching_05.d(9):find(TL,TS) if (is(typeof(longer[0..1] == shorter) : bool)) and searching_05.d(18):find() Is partial ordering really supported ? Yes it is, and your code snippet indeed compiles on my machine. Are you maybe using an outdated version of the compiler? Nevermind, I forgot to pass the -unittest switch. It indeed gives that error. The reason it still does not compile is that the workaround proposed by Jonathan has slightly different semantics than it would have if the compiler already supported overloading of functions against function templates. If exactly one of two equally good matched functions is a templated one, the other one is chosen. So the D code in my first post may work and thus the workaround is not necessary. The language does not mandate the workaround, but the workaround is necessary until the compiler is fixed.
Re: Error: 'this' is only defined in non-static member functions, not parse
On 01/17/2012 06:02 PM, Matej Nanut wrote: On 17 January 2012 16:54, H. S. Teohhst...@quickfur.ath.cx wrote: This may be the cause of your trouble. If the nested class references members in the outer class, then moving it outside will break it, since it won't have an outer scope anymore. T -- Only boring people get bored. -- JM That was my guess too — but I'm not referencing the outer class. The outer class is just using instances of the inner one. Also, the line number of the error points to ‘new’ statements in the static method. (The calls which instantiate subclasses of the inner class.) If I do return null it works as well, without complaining. So it's not a referencing issue I think. As you all seem eager to help, I will copy the entire class, without subclasses, to here. I will be grateful for any comments regarding the current issue at hand or about the code in general. The ‘new’-ed Nodes are defined like ‘class CostNode : Node { ... }’. Another note, the outer class is an inner class of another class as well, if that makes a difference. Also, the outer class isn't really a class, it's a struct, but renaming that to ‘class’ doesn't change anything either. code begin class Node { static Node parse(ref string line) { string mnemonic = munch(line, A-Z); line = line.stripLeft(); auto op = mnemonic in mnemonics; if (!op) throw new Exception(Unknown mnemonic: ` ~ mnemonic ~'); final switch (*op) { case NodeType.COST: return new CostNode(line); case NodeType.PAUSE: return new PauseNode(line); case NodeType.COLDR: return new ColDrNode(line); case NodeType.COLRA: return new ColRaNode(line); case NodeType.DROP: return new DropNode(line); case NodeType.RAISE: return new RaiseNode(line); } /* Doing something like `return new Node()' doesn't work either. * Only `return null' works here. */ } enum NodeType : ubyte { COST, PAUSE, COLDR, COLRA, DROP, RAISE } static immutable NodeType[string] mnemonics; static this() { mnemonics = [ COST : NodeType.COST, PAUSE : NodeType.PAUSE, COLDR : NodeType.COLDR, COLRA : NodeType.COLRA, DROP : NodeType.DROP, RAISE : NodeType.RAISE ]; } } code end I'm quite sure that the error in your code occurs for the same reason as in the following code snippet: class C{ class D{} static make(){return new D();} // error } You can fix it by making D static: class C{ static class D{} static make(){return new D();} // ok } The reason is that non-static inner classes have an implicit 'outer' property that links to the class it was created with. Therefore, to construct them inside a member function, the implicit 'this' pointer is needed. If the 'outer' property is actually unwanted, it is best to declare inner classes as static.
Re: Constant function/delegate literal
On 01/17/2012 05:02 PM, Don Clugston wrote: On 15/01/12 20:35, Timon Gehr wrote: On 01/14/2012 07:13 PM, Vladimir Matveev wrote: Hi, Is there a reason why I cannot compile the following code: module test; struct Test { int delegate(int) f; } Test s = Test((int x) { return x + 1; }); void main(string[] args) { return; } dmd 2.057 says: test.d(7): Error: non-constant expression cast(int delegate(int))delegate pure nothrow @safe int(int x) { return x + 1; } ? The 'this' pointer in the delegate: Test((int x) { return x + 1; }); is a pointer to the struct literal, which isn't constant. You actually want it to point to variable s. The struct literal residing in static storage has a variable address? Why would the context pointer point to the struct literal anyway? It is not required. OTOH if it were a function, it should work, but it currently doesn't. It should even work for delegates. The context pointer would just be null.
Re: Error: 'this' is only defined in non-static member functions, not parse
On 01/17/2012 07:13 PM, Matej Nanut wrote: On 17 January 2012 19:07, H. S. Teohhst...@quickfur.ath.cx wrote: Andrei's book (The D Programming Language) is quite thorough in explaining these D constructs. It's a highly recommended buy if you're doing serious work in D. T -- The two rules of success: 1. Don't tell everything you know. -- YHL I've been thinking on getting that for a while now. How up to date is it? I think it is mostly in a good state. There are a few errata and some unmentioned features because D is/was somewhat of a moving/improving target. On the other hand, many recent bug fixes were targeted at making the implementation consistent with the specification in TDPL. Or does it explain such general concepts that I shouldn't be worried about that at all? I don't think you need to be worried, just be prepared that a few code samples may not compile without minimal fixes. Everyone seems to be recommending it so I don't see why I shouldn't get it. A free university period is also coming up, so that might be a great way to spend my available time. Indeed. When I read it, I have found my time well spent. It is very well written. I'm definitely serious about learning and using D. I've been impressed with it since I first saw it and I intend to do as much work with it as possible. I'm not _doing_ any serious work with it yet, though. In fact, none of the work I do could be considered very serious at all. :)
Re: Error: 'this' is only defined in non-static member functions, not parse
On 01/17/2012 06:58 PM, Matej Nanut wrote: On 17 January 2012 18:29, Timon Gehrtimon.g...@gmx.ch wrote: I'm quite sure that the error in your code occurs for the same reason as in the following code snippet: class C{ class D{} static make(){return new D();} // error } You can fix it by making D static: class C{ static class D{} static make(){return new D();} // ok } The reason is that non-static inner classes have an implicit 'outer' property that links to the class it was created with. Therefore, to construct them inside a member function, the implicit 'this' pointer is needed. If the 'outer' property is actually unwanted, it is best to declare inner classes as static. Yes! If I move the class and its subclasses out of its outer class, and declare them all static, it works! Note that your `make' function is being called within class `D' in my example, if I replace the names. However, the same thing applies. Your explanation was nice, but now I'd like to know what the difference of a non-static vs. a static class is, if they're defined top-level? Or are they then the same? Indeed they are the same. Anything top-level is implicitly static in D. I don't expect anyone to thoroughly explain things to me, but pointing out a good source, like a link or a book, would be really helpful. I don't know if there is any, but I can explain to you the difference between static and non-static nested classes in detail: class A{ int x; static class B{void echo(){writeln(x);}} // n.g. } class A{ int x; class B{void echo(){writeln(x);}} // ok } In other words, non-static nested classes can reference non-static fields of the enclosing class. In order to provide that functionality, non-static nested classes need the implicit 'outer' field. The first snippet is effectively rewritten to something like the following: class A{ int x; class B{A __outer; void echo(){writeln(__outer.x);} } Therefore, for constructing a class instance of type A.B, an instance of A must be provided as an initializer for the 'outer' field. If an instance of B is created in a member of A, the 'this' pointer gets used (and hence is required to be present), but you can also do: void main() { auto a = new A; auto b = a.new B; // construct an 'A.B' with 'a' in implicit 'outer' field a.x = 100; b.echo(); // writes '100' } This is probably one of the more obscure features of D. =) I lack general knowledge in the OOP area and must really learn more about it, as I've always been programming in C and could easily get away with it as we were doing small-ish programs at university.
Re: Could assertThrown be made safe/trusted?
On 01/17/2012 08:21 PM, H. S. Teoh wrote: On Tue, Jan 17, 2012 at 09:07:05AM -0800, Jonathan M Davis wrote: [...] Exception itself isn't @safe yet (its constructor in particular), and I don't think that AssertError is either. A number of stuff like that in druntime and Phobos still needs to be marked @safe or @trusted. [...] Just out of curiosity, why isn't it marked @safe? I looked over the source and didn't see anything immediately obvious that would preclude @safe. T The code for it was presumably written before SafeD was invented.
Re: Could assertThrown be made safe/trusted?
On 01/17/2012 11:31 PM, Jonathan M Davis wrote: On Tuesday, January 17, 2012 14:14:36 H. S. Teoh wrote: On Tue, Jan 17, 2012 at 05:04:18PM -0500, Jonathan M Davis wrote: [...] Attribute inferrence is a big step forward in making as much as possible @safe and pure, but there's still plenty to do there. [...] Funny you should mention that, I was just starting to wonder if I should start littering my code with 'pure', and whether it's possible to make the compiler infer it for me. From the little that I know, it seems that in most cases 'pure' can be automatically inferred. The compiler already distinguishes between weakly pure and strongly pure internally, so why not take it all the way? Not sure how this will affect inter-module analysis, though. But since this is apparently not yet implemented, just what *is* implemented currently when you specify 'pure'? Common subexpression factorization? Hoisting? Not (yet) memoization, apparently. _pure_ is implemented. It's @safe that isn't fully implemented. pure, @safe, and nothrow are inferred for templated functions when they're instantiated so that they can be pure (or @safe or nothrow) based on the code that's generated rather than always forcing it to be one or the other, since that would be far too restrictive. But that's completely unnecessary for normal functions. You _do_ need to mark those pure, @safe, or nothrow yourself. If attributes were inferred for normal functions, the compiler would always have to have the full source of every function. And even then, it might be an instance of the halting problem. Every function is and must be pure (or @safe or nothrow) or not when it's declared, and that's part of its signature, so it can be known even when the full source isn't. Inference works with templates only because they're generating code, and the compiler needs their full source anyway. - Jonathan M Davis I think he is interested in the state of implementation of specific compiler _optimisations_ that make use of function purity in order to prove their correctness. IIRC ldc has CSE for pure functions, but I don't know exactly.
Re: lambda template literals?
On 01/18/2012 01:35 AM, bearophile wrote: Is code vaguely like this meaningful and useful? void main() { alias (x = x ^^ 2) sqrTemplate; } Bye, bearophile Yes. The fact that your particular example does not work is a mere syntactic issue. This works: template ID(alias a){alias a ID;} void main(){ alias ID!(x = x ^^ 2) sqrTemplate; }
Re: output minimal .di files?
On 01/16/2012 09:40 PM, H. S. Teoh wrote: On Mon, Jan 16, 2012 at 09:32:57PM +0100, Alex Rønne Petersen wrote: [...] I... don't think the error messages from expanding raw object code would be very pleasant to read, if you used a template incorrectly... [...] It doesn't have to be *executable* object code; the compiler may store extra info (perhaps as debugging data?) so that it can generate nicer error messages. But like I said, this assumes the compiler is allowed to store arbitrary data inside object files, which may not be the case on some platforms. T How would your proposal help hiding implementation details of templates anyway? All information still needs to be stored. Anyone could write a object file - source file compiler for template implementations.
Re: Error: 'this' is only defined in non-static member functions, not parse
On 01/17/2012 12:49 AM, Matej Nanut wrote: Hey everyone, I, once again, have a problem with an error I can't seem to figure out! The situation: - a class, inherited by five other classes; - the class having a static function which returns one if its subclasses depending on the input of a string. Something like this: class Node { static Node parse(ref string s) { /* Get value to switch by, an enum. */ auto switchable = /* ... */; final switch (switchable) { case Blah.one: return new OneNode(s); case Blah.two: return new TwoNode(s); /* ... */ } } } And I get the mentioned error. I don't understand it: is it saying I'm using `this' in a static member function called `parse'? Am I insane; where am I referencing it? The other classes are in this form: class OneNode : Node { /* ... stuff ... */ this(ref string s) { /* Does stuff with `s'. */ } } Do you need more information? Yes; It is extremely hard to solve the problem when there is no code snippet given which exhibits the problematic behavior in question.
Re: Fixed matrix rows joining
On 01/15/2012 02:38 AM, bearophile wrote: If I have a simple fixed-size matrix and I need to linearize (flatten) it, the function join() seems to not not work: import std.array: join; void main() { int[4][4] table; join(table); } test.d(4): Error: template std.array.join(RoR,R) if (isInputRange!(RoR) isInputRange!(ElementType!(RoR)) isForwardRange!(R) is(Unqual!(ElementType!(ElementType!(RoR))) == Unqual!(ElementType!(R does not match any function template declaration test.d(4): Error: template std.array.join(RoR,R) if (isInputRange!(RoR) isInputRange!(ElementType!(RoR)) isForwardRange!(R) is(Unqual!(ElementType!(ElementType!(RoR))) == Unqual!(ElementType!(R cannot deduce template function from argument types !()(int[4u][4u]) This too doesn't work: join(table[]); This compiles: join(map!q{ a[] }(table[])); But this program shows there is something wrong (I know what's wrong), it prints: [6, 4219787, 4, 6, 4219787, 4] import std.stdio: writeln; import std.algorithm: map; import std.array: join; void main() { int[3][2] table = [[1,2,3],[4,5,6]]; int[] result = join(map!q{ a[] }(table[])); writeln(result); } This prints the right output, but it allocates lot of memory: [1, 2, 3, 4, 5, 6] import std.stdio: writeln; import std.algorithm: map; import std.array: join; void main() { int[3][2] table = [[1,2,3],[4,5,6]]; int[] result2 = join(map!q{ a.dup }(table[])); writeln(result2); } Do you have better suggestions? join(map!((int[] a)=a)(table[])) although I'd like join(map!((ref a)=a[])(table[])) to work. I'll file an enhancement. Is the function join() worth fixing/changing to improve this use case? Bye, bearophile
Re: Constant function/delegate literal
On 01/14/2012 07:13 PM, Vladimir Matveev wrote: Hi, Is there a reason why I cannot compile the following code: module test; struct Test { int delegate(int) f; } Test s = Test((int x) { return x + 1; }); void main(string[] args) { return; } dmd 2.057 says: test.d(7): Error: non-constant expression cast(int delegate(int))delegate pure nothrow @safe int(int x) { return x + 1; } ? This is simple example; what I want to do is to create a global variable containing a structure with some ad-hoc defined functions. The compiler complains that it cannot evaluate at compile time. I think this could be solved by defining a function returning needed structure, but I think this is cumbersome and inconvenient. Best regards, Vladimir Matveev. I think it should work. I have filed a bug report: http://d.puremagic.com/issues/show_bug.cgi?id=7298
Re: Get name of enum val at compile-time?
On 01/15/2012 10:02 PM, Nick Sabalausky wrote: Timon Gehrtimon.g...@gmx.ch wrote in message news:jevefv$2je6$1...@digitalmars.com... On 01/15/2012 09:34 PM, Nick Sabalausky wrote: import std.conv; enum Foo { hello } enum x = to!string(); enum x = to!string(Foo.hello); Goddamnnit, what the fuck is wrong with me? Yes that works :) I suspect a better error message would have prevented this. DMD still has some potential of improvement in that area. =)
Re: Absolute beginner
On 01/13/2012 10:34 PM, Jorge wrote: Thanks for your answer but: import std.stdio; import std.conv; void main() { write(Insert number: ); string s = readln(); auto i = to!int(s); } compiles but after i enter a number and press the enter key i get: std.conv.ConvException@.\..\..\src\phobos\std\conv.d(1595): Can't convert value ` ' of type string to type int 41DECC 41DD43 4027F3 402475 402D6C 402DB0 4029A7 4BBA79 what's wrong? readln() includes the trailing newline character in the resulting string. You can use std.string.strip to remove leading and trailing whitespace: import std.stdio; import std.conv; import std.string; void main() { write(Insert number: ); string s = readln(); auto i = to!int(strip(s)); }
Re: About implicit array cast
On 01/13/2012 02:19 AM, bearophile wrote: This code compiles, because the [0,0] dynamic array literal casts implicitly to int[2]: int[2] foo() { return [0, 0]; // OK } void main() {} And of course this too compiles: int[2] bar() { int[2] ab; return (true) ? ab : ab; // OK } void main() {} But currently this code doesn't compile: int[2] spam() { int[2] ab; return (true) ? ab : [0, 0]; // Error } void main() {} test.d(3): Error: cannot implicitly convert expression (cast(int[])ab) of type int[] to int[2u] Is this good? Bye, bearophile This is a bug.
Re: Mixin on a bunch of foreach fails.
On 01/13/2012 05:07 AM, Charles McAnany (dlang) wrote: Hi, all. So I'm trying to make some very ugly code generic. The main ugliness isn't in the code shape, it's in the running time. It's O(n^m) Eww! (don't worry, n is only about 6.) Anyhoo, Here's what I want: void foo(int size)(int[] arr){ mixin(forStart!(size)); doStuff(pos0, pos1, pos2,...); // this line is generated by another mixin that works correctly. } //Generates for loop headers. private static string forStart( int sz)(){ string forStrings = ; for(int i = 0; i sz; i++){ forStrings ~=foreach(pos~text(i)~; 0..arr.length)\n ; } return forStrings; } It is my great displeasure to report: src\hw06.d(35): found 'EOF' instead of statement src\hw06.d(18): Error: template instance hw06.tryCombinations!(5) error instantiating But here's the wacky part: I can execute this function and print it to stdout. If I do, I get... foreach(pos0; 0..arr.length) foreach(pos1; 0..arr.length) foreach(pos2; 0..arr.length) foreach(pos3; 0..arr.length) foreach(pos4; 0..arr.length) and I can copy-paste this exact code into where I currently have the mixin, and the code behaves correctly. Is there some subtle aspect of mixin that I'm missing here? Cheers, Charles. Yes. You can only mixin whole statements or expressions. The easiest way to fix your code is to join the two mixins into one using the concatenation operator. Eg: mixin(forStart!(size)~generateDoStuff(...)); By the way, you can make the code more clean by making 'int sz' a simple function parameter. (static string forStart(int sz){...})
Re: Compile-time evaluation of real expressions?
On 01/07/2012 12:37 AM, Jonathan M Davis wrote: On Saturday, January 07, 2012 00:03:39 Alex Rønne Petersen wrote: Most likely those functions are just implemented using inline assembly, therefore not usable in CTFE. Yeah, several functions in std.math use inline assembly. So, for them to be able to be used at compile time, either the compiler must be expanded to be able to run asm statements at compile time (which may or may not be planned and may or may not be reasonable), or those functions need another branch (using __cfte in an if condition) which doesn't use assembly. Or I suppose that if the extra check for __ctfe isn't considered particularly acceptable (after all, they're already using assembly) [snip.] If the if condition is a constant, there is no runtime overhead.
Re: Problem with Hiredis Binding
On 01/05/2012 07:14 PM, Joshua Reusch wrote: Am 05.01.2012 17:21, schrieb Puming Zhao: Hi, I'm new in D programming, and does not have much C experience either. After reading TDPL book and playing with some sample codes, I came to decide to try something more `practical`. I began with a Redis client binding from Hiredis C code. Hiredis is a small lib, and seems very simple to bind to D. My code on github: https://github.com/zhaopuming/dredis But I went into problems that I don't know how to solve. When running example.d I went into segment fault, and can't get redisReply from a redis command. I tried to google it but got nothing. So my question is, could some one with more knowledge in redis or C/D look into my code and see what's wrong ? Or is there already a Redis binding exists? dredis.d: redisContext* redisConnectWithTimeout(const char* ip, int port, timeval tv); example.d: redisConnectWithTimeout(127.0.0.1, 6379, timeout); D strings do not end with an \0 byte ! You can use std.string.toStringz to convert them to C's const char* -- Joshua D string literals are zero-terminated.
Re: out default argument of void
On 01/04/2012 11:19 PM, Caligo wrote: I have a function that looks something like this: bool fun(double theta, out A a, out B b, out C c){ /* ... */ } if fun() returns false, then nothing is supposed to be assigned to a, b, c. If it returns true, then values are assigned to a, b, c. Also, there are two ways to call fun(): If I'm interested in the return value only, then 1. fun(theta); otherwise, 2. fun(theta, a, b, c); Obviously, method #1 won't work because there is no such thing as: bool fun(double theta, out A a = void, out B b = void, out C c = void){ /* ... */ } is there? So, I have to lose 'out' and use pointers instead: bool fun(double theta, A* a = null, B* b = null, C* c = null){ /* ... */ } I don't want to use a variadic function for this either because it's not really a variadic function. 1. Are there any other solutions ? Yes. Use overloading. This would work: bool fun(double theta, out A a, out B b, out C c){ /* ... */ } bool fun(double theta){ A a; B b; C c; return fun(theta,a,b,c); } Or this: private bool funImpl(double theta, A* a = null, B* b = null, C* c = null){ /* ... */ } bool fun(double theta, out A a, out B b, out C c){return funImpl(theta,a,b,c); bool fun(double theta){return funImpl(theta);} 2. Would it make sense to have 'out default argument of void' in D? void initializer means uninitialized. I don't think that can do what you want.
Re: Using in with associative arrays and then indexing them (efficiency)
On 01/03/2012 12:07 PM, Jonathan M Davis wrote: On Tuesday, January 03, 2012 11:52:13 Matej Nanut wrote: Hello everyone, I would like to know whether if (symbol in symbols) return symbols[symbol]; is any less efficient than auto tmp = symbol in symbols; if (tmp !is null) return *tmp; Without optimisation, it looks like the first example searches for `symbol' twice. Of course it does. in does a search and returns a pointer to the element in the AA (or null if it isn't there). The subscript operator also does a search, returning the element if it's there and blowing up if it's not (OutOfRangeError IIRC without -release and who-knows-what with -release). So, if you use in and then the subscript operator, of course it's going to search twice. Part of the point of using in is to not have to do a double lookup (like you would be doing if AAs had a contains function and you called that prior to using the substript operator). The correct way to do it is the second way, though you should be able to reduce it to if(auto tmp = symbol in symbols) return *tmp; - Jonathan M Davis I think this is the single most ugly thing in the language. IIRC ldc will generate identical code for both code snippets.
Re: Using in with associative arrays and then indexing them (efficiency)
On 01/03/2012 12:22 PM, Jonathan M Davis wrote: On Tuesday, January 03, 2012 12:13:45 Timon Gehr wrote: On 01/03/2012 12:07 PM, Jonathan M Davis wrote: On Tuesday, January 03, 2012 11:52:13 Matej Nanut wrote: Hello everyone, I would like to know whether if (symbol in symbols) return symbols[symbol]; is any less efficient than auto tmp = symbol in symbols; if (tmp !is null) return *tmp; Without optimisation, it looks like the first example searches for `symbol' twice. Of course it does. in does a search and returns a pointer to the element in the AA (or null if it isn't there). The subscript operator also does a search, returning the element if it's there and blowing up if it's not (OutOfRangeError IIRC without -release and who-knows-what with -release). So, if you use in and then the subscript operator, of course it's going to search twice. Part of the point of using in is to not have to do a double lookup (like you would be doing if AAs had a contains function and you called that prior to using the substript operator). The correct way to do it is the second way, though you should be able to reduce it to if(auto tmp = symbol in symbols) return *tmp; - Jonathan M Davis I think this is the single most ugly thing in the language. IIRC ldc will generate identical code for both code snippets. What, declaring variables in if statements? It's fantastic IMHO. It allows you to restrict the scope of the variable to the if statement's scope and still use it in the if's condition. And yes, as far as the assembly goes, the generated code is identical. But the scoping for the variable is most definitely different - it won't exist past the if statement if it's declared in the if's condition - and it saves you a line of code. The reduced scope is the more important of the two though IMHO, as nice as saving a line of code is. - Jonathan M Davis No, I love declaring variables in if statements and would like it to be extended to while statements as well. What I meant is the fact that something called 'in' returns a pointer. And the two code snippets I was referring to were the two in Matej's post.
Re: opCast!bool
On 01/04/2012 12:31 AM, Jonathan M Davis wrote: On Tuesday, January 03, 2012 17:41:12 simendsjo wrote: I guess this is as designed, but I'll ask anyway. http://dlang.org/operatoroverloading.html#Cast says an expression is rewritten to opCast whenever a bool result is expected. This is true for if(e) somethingElse and e somethingElse , but not for other parts. assert(cast(bool)e == true); // explicit cast works assert(e == true); // Error: incompatible types for ((s) == (false)): 'S' and 'bool' is(typeof(e) : bool); // false Yeah. It's the same for built-in types. Take arrays and pointers for example. They don't implicitly convert to bool, but when you use them in a condition, they implicitly convert to bool (true if they're non-null, false if they're null). If you want implicit conversion in general, then you need to use alias this. - Jonathan M Davis The conversion is explicit. if(x) is rewritten to if(cast(bool)x) and e somethingElse is rewritten to cast(bool)e cast(bool)somethingElse.
Re: opCast!bool
On 01/03/2012 05:41 PM, simendsjo wrote: I guess this is as designed, but I'll ask anyway. http://dlang.org/operatoroverloading.html#Cast says an expression is rewritten to opCast whenever a bool result is expected. This is true for if(e) somethingElse and e somethingElse , but not for other parts. assert(cast(bool)e == true); // explicit cast works assert(e == true); // Error: incompatible types for ((s) == (false)): 'S' and 'bool' There is no 'bool result expected': The relation of the two operands in == is symmetric. You could just as well say that the result of 'true' is expected to be of type typeof(e). is(typeof(e) : bool); // false This tests whether or not typeof(e) implicitly converts to bool, which can be false even if an explicit cast would succeed.
Re: rvalue references template ?
On 01/02/2012 03:02 PM, Joshua Reusch wrote: Is it possible to create a template turning any value into a lvalue? This would be helpful if a function expects a reference but you dont need the result of the change: ///decode(S)(in S str, ref size_t index); auto c = std.utf.decode(some_string, lval!0); Yes, but I currently cannot see a full solution that does not heap-allocate.
Re: Array of array
On 01/02/2012 11:04 PM, RenatoL wrote: auto r = new int[][5]; this is ok auto r = new int[][]; this is not ok Error: new can only create structs, dynamic arrays or class objects , not int[][]'s why? What would you expect the code to do? What you are trying to achieve is similar to: class Array(T){this(size_t length){...}} auto r = new Array!(Array!int); // error: missing constructor argument
Re: Array of array
On 01/02/2012 11:21 PM, RenatoL wrote: Just curious... the answer of the compiler it's a bit unclear to me... T[] is a dynamic array of type T. T[][] is a dynamic array of T[]. But this doesn't work. Why? It does work. Why do you think it does not? T[] a; // ok T[][] b; // ok auto c = new T[5]; // ok auto d = new T[][5]; // ok auto e = new T[];// fail, nonsensical auto f = new T[][]; // fail, nonsensical
Re: Array of array
On 01/03/2012 12:03 AM, RenatoL wrote: I have: auto r = new int[][]; Error: new can only create structs, dynamic arrays or class objects , not int[][]'s while auto r = new int[][3]; is ok. new int[][3] is an alternate form of new int[][](3); new int[][3] allocates an int[][] with 3 default-initialized elements.
Re: Hole of new? (Re: Array of array)
On 01/03/2012 12:02 AM, Mafi wrote: Am 02.01.2012 23:33, schrieb Timon Gehr: On 01/02/2012 11:21 PM, RenatoL wrote: Just curious... the answer of the compiler it's a bit unclear to me... T[] is a dynamic array of type T. T[][] is a dynamic array of T[]. But this doesn't work. Why? It does work. Why do you think it does not? T[] a; // ok T[][] b; // ok auto c = new T[5]; // ok auto d = new T[][5]; // ok auto e = new T[]; // fail, nonsensical auto f = new T[][]; // fail, nonsensical Here we come to an interesting point I often thought of. How do you allocate a T[] itself (so you get a T[]*) or a ClassType reference (so you get a ClassType*) on the heap (without casting)? As far as I know it's not possible with new. new T[n] is of type T[]. new T[]* is of type T[]**. new ClassType is of type ClassType. new ClassType* is of type ClassType**. Is this a Hole of new? Mafi Yes, but you can use (new T[][1]).ptr; to allocate T[] itself (and get a T[]*). Maybe new T[] should be interpreted as allocating a T[] and give back a T[]*.
Re: Array of array
On 01/03/2012 12:46 AM, Matej Nanut wrote: On 3 January 2012 00:27, Timon Gehr timon.g...@gmx.ch mailto:timon.g...@gmx.ch wrote: On 01/03/2012 12:03 AM, RenatoL wrote: I have: auto r = new int[][]; Error: new can only create structs, dynamic arrays or class objects , not int[][]'s while auto r = new int[][3]; is ok. new int[][3] is an alternate form of new int[][](3); new int[][3] allocates an int[][] with 3 default-initialized elements. I assume `int[][] sth;` does what RenatoL wants to accomplish by `auto sth = new int[][];`. I do however have a question: is `auto sth = new int[][5];` the same as `int[][5] sth;`? If not, what is the difference? It is not the same thing. First of all, lets get rid of int[][] and use int[] for further reasoning. int[] is a data structure with two members: 'ptr' and 'length'. 'ptr' is a pointer to the first element of the array, and 'length' indicates how many elements are in the array. int[] does not carry any data on its own: it is only a reference to the data. int[5] on the other hand is a data structure that contains 5 integers with the indices 0,1,2,3,4. |ptr|length| - int[] |0|1|2|3|4| - int[5] An int[5] can be sliced to get an int[]: void main(){ int[5] arr1=[0,1,2,3,4]; int[] arr2 = arr1[]; // arr2 is now a reference to arr1's data: assert(arr2.ptr is arr1[0] arr2.length == 5); // changing arr2 changes arr1: arr2[0] = 5; assert(arr1 == [5,1,2,3,4]); // assigning int[5] to int[5] copies the data int[5] arr3 = arr1; assert(arr2.ptr !is arr1[0]); // therefore, changing arr3 lets arr1 intact arr3[0] = 0; assert(arr1 == [5,1,2,3,4]); } void main(){ int[] arr1; // creates an int[] on the stack with ptr=null and length=0 int[5] arr2; // creates in int[5] on the stack with arr2[i]=0 for i in 0,1,2,3,4 arr1 = arr2[]; // array slice lets arr1 reference the data of arr2 arr1 = new int[](5); // allocates an int[5] on the heap and lets arr1 reference the newly created data arr1 = new int[5]; // same as the above, syntax carried over from C++/Java } With this in mind, it is now possible to understand the difference between int[][5] sth and auto sth = new int[][5]: void main(){ int[][5] sth1; // creates an int[][5] on the stack (5 default-initialized int[]s) auto sth2 = new int[][5]; // creates an int[][5] on the heap and lets sth2 reference it. }
Re: do-while loops
On 12/28/2011 02:29 PM, bearophile wrote: One thing that I often find not handy in the design of do-while loops: the scope of their body ends before the while: void main() { do { int x = 5; } while (x != 5); // Error: undefined identifier x } So I can't define inside them variables that I test in the while(). This keeps the scope clean, but it's not nice looking: void main() { { int x; do { x = 5; } while (x != 5); } } Bye, bearophile I fully agree, but why does this go to D.learn?
Re: do-while loops
On 12/28/2011 04:01 PM, Andrej Mitrovic wrote: A very small cheat: void main() { if (int x = 0) do { x = 5; } while (x != 5); } Only works for this simple case though. Put your post in d.general, I totally agree with it as well. This won't work. The 'if' condition is always false.
Re: do-while loops
On 12/28/2011 06:42 PM, bearophile wrote: Timon Gehr: I fully agree, but why does this go to D.learn? Because I think there's no hope to see this situation changed :-) Bye, bearophile Why? The only D code that would get broken would be code that uses a global variable in the loop condition of the same name as a do loop local variable.
Re: do-while loops
On 12/28/2011 09:32 PM, Alex Rønne Petersen wrote: On 28-12-2011 18:50, Timon Gehr wrote: On 12/28/2011 06:42 PM, bearophile wrote: Timon Gehr: I fully agree, but why does this go to D.learn? Because I think there's no hope to see this situation changed :-) Bye, bearophile Why? The only D code that would get broken would be code that uses a global variable in the loop condition of the same name as a do loop local variable. That's still a bit of a risk to take for such a small change, IMHO. - Alex Well, do loops are the least frequently used looping constructs. Also, if you actually have code like the following import foo; // defines global symbol 'x' void main(){ do { int x; // ... }while(x2); } It is likely that it is actually buggy because the programmer assumed lookup would work differently.
Re: do-while loops
On 12/28/2011 10:45 PM, Manfred Nowak wrote: bearophile wrote: void main() { do { int x = 5; } while (x != 5); // Error: undefined identifier x } Do you mean, that the similar while-loop should also be okay? | void main() { | while (x != 5) /* uses `x' out of _following_ scope */ { | int x = 5; | }; | } -manfred No, it is not any more valid than the following code, even if condition and body are scoped together: void main() { bool _ = x != 5; int x = 5; } Related: https://github.com/D-Programming-Language/dmd/pull/342#issuecomment-3232150
Re: Reading about D: few questions
On 12/24/2011 02:02 AM, Jonathan M Davis wrote: The core problem for a number of these situations is how types are handled with regards to expressions. In an expression such as char[] arr = s ~ '.'; the type of the value being assigned is determined _before_ the assignment is done. So, even though in theory the compiler could make it work, it doesn't, because by the time it's looking at the type being assigned to, it's too late. There would need to be a fundamental change in how the language functions in order to fix issues like this. Examples of resolved issues like this: int[] foo()pure; immutable(int)[] x = foo; pure can do it when it can not because it's able to look at what the return type is and changing the result of the expression accordingly but because it has guarantees which make it so that it knows that the return value could be converted to any level of constness and still be valid. The types used in the expressions internally are generally irrelevant. So, while I completely agree that it would be an improvement if the compiler did a better job with implicit conversion when it could theoretically be done, I'm not sure how much of that we're actually going to end up seeing simply because of how the language and type system works in terms of the order of evaluation. - Jonathan M Davis I don't think this is very hard to get working.
Re: Reading about D: few questions
On 12/24/2011 07:00 PM, Andrew Wiley wrote: On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehrtimon.g...@gmx.ch wrote: On 12/24/2011 06:18 PM, Andrew Wiley wrote: 2011/12/24 Mr. Anonymousmailnew4s...@gmail.com: On 24.12.2011 19:01, Denis Shelomovskij wrote: 23.12.2011 22:51, bearophile пишет: ++a[] works, but a[]++ doesn't. Already known compiler bug. Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use instead of 'x###'): https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator. Why should it store a copy? o_O I also don't see any allocations in the code on the URL above. int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true. Not necessarily. class D{ int payload; D opUnary(string op:++)(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); } That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1); Yes, that was my point.
Re: Reading about D: few questions
On 12/24/2011 08:41 PM, Mr. Anonymous wrote: On 24.12.2011 21:22, Andrew Wiley wrote: On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehrtimon.g...@gmx.ch wrote: On 12/24/2011 07:00 PM, Andrew Wiley wrote: On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehrtimon.g...@gmx.ch wrote: On 12/24/2011 06:18 PM, Andrew Wiley wrote: 2011/12/24 Mr. Anonymousmailnew4s...@gmail.com: On 24.12.2011 19:01, Denis Shelomovskij wrote: 23.12.2011 22:51, bearophile пишет: ++a[] works, but a[]++ doesn't. Already known compiler bug. Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use instead of 'x###'): https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator. Why should it store a copy? o_O I also don't see any allocations in the code on the URL above. int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true. Not necessarily. class D{ int payload; D opUnary(string op:++)(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); } That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1); Yes, that was my point. Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array. I guess it could be argued that since arrays have hybrid value/reference semantics, no copy should be made and the original should change. Actually, looking at it from that angle, a[]++ is fundamentally ambiguous because it could have value semantics or reference semantics, so I would argue that we shouldn't have it for that reason. '++a' and 'a += 1' do not have such ambiguities. Maybe you're right, but a[]++; alone, imo, should compile. +1.
Re: Reading about D: few questions
On 12/24/2011 08:22 PM, Andrew Wiley wrote: On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehrtimon.g...@gmx.ch wrote: On 12/24/2011 07:00 PM, Andrew Wiley wrote: On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehrtimon.g...@gmx.chwrote: On 12/24/2011 06:18 PM, Andrew Wiley wrote: 2011/12/24 Mr. Anonymousmailnew4s...@gmail.com: On 24.12.2011 19:01, Denis Shelomovskij wrote: 23.12.2011 22:51, bearophile пишет: ++a[] works, but a[]++ doesn't. Already known compiler bug. Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use instead of 'x###'): https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator. Why should it store a copy? o_O I also don't see any allocations in the code on the URL above. int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true. Not necessarily. class D{ int payload; D opUnary(string op:++)(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); } That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1); Yes, that was my point. Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array. And I said: not necessarily That is because reference types have had semantics that go well with not making a copy all along, so there is no danger of making things more inconsistent. I guess it could be argued that since arrays have hybrid value/reference semantics, no copy should be made and the original should change. Actually, looking at it from that angle, a[]++ is fundamentally ambiguous because it could have value semantics or reference semantics, so I would argue that we shouldn't have it for that reason. '++a' and 'a += 1' do not have such ambiguities. I don't think a[]++ should necessarily be there either.
Re: Function overload with template alias error
On 12/24/2011 11:23 AM, André Stein wrote: Hi, I'm trying to write a template function which takes a templated alias to another type: struct test(T) { } template aliasT(T) { alias test!(T) aliasT; } void foo(T)(test!T t) { // works } void foo2(T)(aliasT!T t) { // doesn't work } int main(string[] args) { test!(int) t; aliasT!(int) t2; foo(t); foo2(t2); // error return 0; } When foo2(t2) is called which takes an alias to test!T as argument I get the following error from dmd: *(21): Error: template variant.foo2(T) does not match any function template declaration *(21): Error: template variant.foo2(T) cannot deduce template function from argument types !()(test!(int)) I thought that aliasT!T and test!T have the same internal types and the compiler would be able deduce the template parameters. Am I missing something or is this a bug in DMD? This is a reduced test case from a piece of code where I tried to write an templated overload to std.variant.Algebraic. Thanks, André IFTI can only deduce template parameters for symbols that are defined inside the template instantiation because then the symbol remembers the template parameters. IFTI cannot reverse-instantiate templates.
Re: test if object is instance of class at compile time
On 12/21/2011 09:15 PM, Elvis Maehren wrote: This works fine at runtime, but explodes in CTFE: --- bool isInstanceOf(T, O)(O o) { return (cast(T) o) !is null; } --- CTFE doesn't like !is null (cannot compare [...] at compile time). This will be fixed in the next release: http://d.puremagic.com/issues/show_bug.cgi?id=7143 Moreover, in CTFE a failed cast terminates the interpretation (cannot reinterpret class from [...] to [...] at compile time). I don't think this is filed already. Maybe you want to file a bug report? Is this somehow catchable? If so, I could do something along these lines: --- if(__ctfe) { try { auto t = cast(T) o; return true; } catch { return false; } } --- use traits(__compiles, {...}), where '...' is the exact code that fails. But that is a mere workaround. What you are doing should/will work.
Re: ctfe bug?
On 12/22/2011 10:28 AM, Jacob Carlborg wrote: On 2011-12-22 08:47, Johannes Pfau wrote: Hi, the following code is reduced from a parser generated with Ragel (http://www.complang.org/ragel/). That's also the reason why it's using pointers instead of array access, but Ragel guarantees that there won't be any out-of-bound reads. AFAIK pointers are supported in CTFE now as long as they're pointing to an array and there are no out-of-bounds reads. Still, the following code fails: ubyte[4] testCTFE() { ubyte[4] data; string input = 8ab3060e2cba4f23b74cb52db3bdfb46; auto p = input.ptr; p++; p++; data[0] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; data[1] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; data[2] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; data[3] = parse!ubyte((p-2)[0 .. 2], 16); p++; p++; return data; } enum ctfe = testCTFE(); void main() { import std.stdio; writeln(testCTFE()); //[138, 179, 6, 14] writeln(ctfe); //[138, 138, 138, 138] } Has this bug already been filed? I could possibly circumvent it by making ragel use array indexing instead of pointers, but that'd be a performance issue for runtime code as well. Why would arrays be slower than pointers? You do know that you can turn off array bounds checking? Yes but the length has to be stored and updated, therefore for example p++ is less machine instructions/memory accesses/register pressure than arr = arr[1..$].
Re: writing iterators without code duplication. inout?
On 12/21/2011 04:54 PM, pompei2 wrote: Hello. I want to add the option to iterate objects of my class using foreach. I need them to be iterable as view-only const and as mutable too. I would prefer to iterate using the return a delegate but if that's not possible, ranges are fine too. Also, I'd prefer a template-less solution over a templated one. This is what I have, which works but has severe code duplication. I hoped inout would help me here, but I just can't figure it out. I also gave a try to ranges, but same thing again: I can only get it to work if I define my things twice. (syntax highlight for the coming month: http://pastebin.com/TNmWWgsj) import std.conv, std.stdio; class Container { this(int from, int to) { while(from = to) { _arr ~= from; from++; } } // FIXME: severe code duplication for const/nonconst/ref // and I'm not even trying immutable yet int delegate(int delegate(ref int)) doIter() { writeln(calling non-const); int doTheIter(int delegate(ref int) dg) { int result = 0; foreach(ref i ; this._arr) { result = dg(i); if(result) break; } return result; } return doTheIter; } int delegate(int delegate(ref int)) doIter() const { writeln(calling const); int doTheIter(int delegate(ref int) dg) { int result = 0; foreach(i ; this._arr) { result = dg(i); if(result) break; } return result; } return doTheIter; } int[] _arr; } int main(string[] args) { Container c = new Container(1, 9); const Container cc = c; foreach(ref e ; c.doIter()) { writeln(e); e++; } foreach(e ; cc.doIter()) { writeln(e); } return 0; } Just remove the non-const overload. const member functions work with mutable, immutable and const receivers.
Re: How to mixin each element of tuple
On 12/20/2011 02:32 PM, Michal Minich wrote: My naive approach doesn't works struct Item1 (T) {} struct Item2 (T) {} struct Group (Items ...) { // how to do this? ... no static foreach :( static foreach (I; Items) mixin I!(int); } void main () { alias Group!(Item1, Item2) G; } This will do what you want: Solution 1: struct Item1(T){} struct Item2(T){} mixin template getItems(Items ...){ static if(Items.length) { private alias Items[0] _item; mixin _item!int; mixin getItems!(Items[1..$]); } } struct Group(Items...) { mixin getItems!Items; } void main(){ alias Group!(Item1, Item2) G; } Solution 2: struct Item1(T){} struct Item2(T){} struct Group(Items...) { private static string gen(){ string r; foreach(i;0..Items.length){ import std.conv; r~=`private alias Items[`~text(i)~`] _item`~text(i)~`;`; r~=`mixin _item`~text(i)~`!int;`; } return r; } mixin(gen()); } void main(){ alias Group!(Item1, Item2) G; } But I'd rather have static foreach too.
Re: newbie question: Can D do this?
On 12/20/2011 03:18 PM, clk wrote: Thank you for your quick replies. I'm impressed by the helpfulness and dedication of the D community! Here's another one. Is there a way to pass arguments to functions by keyword as in the calls to f and g below? void f(int a = 0, int b = 1) {} void g(int a) {} void main() { f(b = 1, a = 0); // compile error g(a = 0); // also compile error } No, there are no named arguments in D. Having them would sometimes be useful, but the drawback is that the parameter names become part of the public interface. On 12/19/2011 03:00 PM, digitalmars-d-learn-requ...@puremagic.com wrote: Send Digitalmars-d-learn mailing list submissions to digitalmars-d-learn@puremagic.com To subscribe or unsubscribe via the World Wide Web, visit http://lists.puremagic.com/cgi-bin/mailman/listinfo/digitalmars-d-learn or, via email, send a message with subject or body 'help' to digitalmars-d-learn-requ...@puremagic.com You can reach the person managing the list at digitalmars-d-learn-ow...@puremagic.com When replying, please edit your Subject line so it is more specific than Re: Contents of Digitalmars-d-learn digest... Today's Topics: 1. Re: newbie question: Can D do this? (Ali ?ehreli) 2. Re: newbie question: Can D do this? (Kai Meyer) 3. Re: newbie question: Can D do this? (Simen Kj?r?s) 4. Re: newbie question: Can D do this? (Ali ?ehreli) 5. Re: newbie question: Can D do this? (Jonathan M Davis) -- Message: 1 Date: Mon, 19 Dec 2011 10:41:29 -0800 From: Ali ?ehreliacehr...@yahoo.com To:digitalmars-d-learn@puremagic.com Subject: Re: newbie question: Can D do this? Message-ID:jco0gq$1ilt$1...@digitalmars.com Content-Type: text/plain; charset=UTF-8; format=flowed On 12/19/2011 08:17 AM, clk wrote: I'm a little bit intimidated by the fact that the topics in the d-learn list look rather advanced to a newbie like me. We need more newbie topics here! :) 1) Does D support something like the javascript 1.8 destructuring assigment (multiple assigment in python): [a, b] = [b, a]; No multiple assignment like that. But useful approarches exist for most needs, like the swap that simendsjo has shown. 2) D doesn't seem to support the list comprehension syntax available in python and javascript. Is this correct? [f(x) for x in list if condition] List comprehension is not part of the language. import std.algorithm; void f(int x) {} bool condition(int x) { return true; } void main() { auto list = [ 0, 1, 2 ]; map!f(filter!condition(list)); } You can define f and condition within the body of main(). It is possible to use function literals as well: import std.algorithm; void main() { auto list = [ 0, 1, 2 ]; map!((x){ /* ... this is f(x) ...*/ })(filter!((x) { return true; /* ... condition ... */ })(list)); } 3) D's slice operator apparently doesn't allow the use of a stride other than unity as is allowed with fortran and matlab. Is there a way to implement this feature so that [1, 2, 3, 4, 5][0..$:2] would refer to [1, 3, 5], etc..., where 2 is the non unit stride. Or is the find function from std.algorithm the only option to achieve the same behavior. std.range.stride does that: import std.range; // ... stride([1, 2, 3, 4, 5], 2) I find the 3 features above extremely convenient in every day coding. Thanks, -clk Ali -- Message: 2 Date: Mon, 19 Dec 2011 11:50:33 -0700 From: Kai Meyerk...@unixlords.com To:digitalmars-d-learn@puremagic.com Subject: Re: newbie question: Can D do this? Message-ID:jco11q$1lle$1...@digitalmars.com Content-Type: text/plain; charset=ISO-8859-1; format=flowed On 12/19/2011 09:17 AM, clk wrote: Hello, I'm new to this mailing list. I'm trying to learn D to eventually use it in production code. I'm a little bit intimidated by the fact that the topics in the d-learn list look rather advanced to a newbie like me. I have 3 fairly simple questions: 1) Does D support something like the javascript 1.8 destructuring assigment (multiple assigment in python): [a, b] = [b, a]; I would love multiple assignment like this, but it's tricky. But your usage isn't really multiple assignment as much as it is a swap. What I'd love is something like this: [a, b, c] = [get_a(), get_b(), get_c()]; Or [a, b, c] = [to!(int)(argv[1]), some_other_value, argv[4]); 2) D doesn't seem to support the list comprehension syntax available in python and javascript. Is this correct? [f(x) for x in list if condition] No, D's syntax is very C-ish. I don't expect syntax like this to ever show up (though what you are doing is possible with things like std.algorithm) 3) D's slice operator apparently doesn't allow the use of a stride other than unity as is
Re: Void initialization
On 12/19/2011 01:04 PM, Bear wrote: Using D1, I have a program that creates tons of float[] ; for performance reasons, I would like them to be uninitialized. I've tried replacing float[] f = new float[x]; by float[] f = cast(float[])std.gc.malloc(x*4); Unfortunately I keep running into Access violation and sometimes Array bounds error. I've tried adding setTypeInfo(typeid(float), f.ptr); and hasNoPointer(f.ptr); which didn't work. However f[] = float.nan; solved the problem, but kinda defeats the purpose of using malloc... What am I doing wrong? Are you using GDC? https://bitbucket.org/goshawk/gdc/issue/287/casting-between-array-types-is-broken If so, this is the workaround: float[] f = (cast(float[])std.gc.malloc(x*4))[0..x];
Re: Void initialization
On 12/20/2011 07:12 PM, bearophile wrote: Stewart Gordon: On 19/12/2011 12:12, bearophile wrote: Try something like this (untested): alias float TF; TF[] f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x]; snip I fail to see any real difference from the OP's code: - Why the alias? Because in that code I have used three times a type (TF), auto allows to remove only one of them. The alias is not the best solution (a better solution is to put that code into a templated function), but repeating the same generic type more than one time is usually a source of bugs. - std.gc.malloc returns the array with correct length according to my quick test, so the use of [0..x] is redundant Really? Well, as I have said I have not tested that code. Generally GC functions return a void*, so to create an array I think you need to slice it... What is the code of your quick test? - using TF.sizeof instead of 4 might fix things if on the user's platform float isn't 4 bytes long. In D I think float is always 4 bytes long. Otherwise, while using .sizeof instead of a hard-coded number is better practice, it isn't going to get rid of an AV. I don't know what an AV is. Bye, bearophile Access Violation.
Re: How to mixin each element of tuple
On 12/20/2011 07:13 PM, bearophile wrote: Michal Minich: struct Group (Items ...) { // how to do this? ... no static foreach :( static foreach (I; Items) In D if you use foreach on a typeTuple you get a static foreach. Bye, bearophile Yes, but foreach cannot be used in declaration scope. I think having static foreach would greatly benefit the language. I regularly run into cases where I have to use one of the two inferior solutions when static foreach would be just the right tool for the job.
Re: delegate, template and alias
On 12/19/2011 06:46 PM, Philippe Sigaud wrote: On Mon, Dec 19, 2011 at 15:35, Heromythbitwo...@qq.com wrote: Woo, I got it. What's the difference with your first post? He uses an eponymous template now.
Re: delegate, template and alias
On 12/19/2011 09:30 PM, Philippe Sigaud wrote: On Mon, Dec 19, 2011 at 18:49, Timon Gehrtimon.g...@gmx.ch wrote: On 12/19/2011 06:46 PM, Philippe Sigaud wrote: On Mon, Dec 19, 2011 at 15:35, Heromythbitwo...@qq.comwrote: Woo, I got it. What's the difference with your first post? He uses an eponymous template now. Ah yes, thanks. Strange, I'm pretty sure I used the eponymous trick and it didn't work, for some reason. Anyway, Heromyth, I'm slowly working on a D template tutorial. The current pdf is at: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf (click on View Raw to download). It's still incomplete. I'll work on it during the holidays and post on D.announce to get some feedback on it, but you're welcome if you want to give it a try. Philippe Looks very good. Knowing it is a work in progress, I will already give some feedback: You have a typo on page 15: static if (is(T t = U[], U)) // is T an array of U, for some type U? You probably meant to write static if (is(T t == U[], U)) // is T an array of U, for some type U? On page 18, I think your explanation why you used .power instead of power is not yet entirely accurate. The only reason why it is needed is because you are defining an eponymous template that hides the global template. Also on page 18: 'Note that this template will work not only for unary (one argument) functions but also for n-args functions,' The implementation given does not work for n-args functions because functions cannot return a tuple. Page 23: 'Note that flatten works perfectly on ranges too, but is not lazy' Ranges don't have the concatenation operator, so it will not work. Page 25: 'And due to (to my eyes) a bug in alias, you cannot alias them to a symbol: alias (a){ return a;} Id; // Error' It is a restriction that the current D grammar has. You can do this: alias ID!((a){ return a;}) Id; where ID is template ID(alias X){alias X ID;} Page 25: 'Since they are delegates, they can capture local symbols, as long as these are defined at compile-time:' They can even capture local symbols that don't have a compile-time value. For example: auto foo(alias s)(){return s();} void main() { int x = 2; writeln(foo!({return x;})()); // prints '2' } And the link is purely symbolic, no closures or the like are allocated. What the compiler effectively does is in the lines of this: void main() { int x = 2; auto dgliteral() { return x; } // {return x;} auto foo(){ return dgliteral(); } // foo!({return x}) writeln(foo()); // call template instance } This is one of the most powerful features of D templates: They are instantiated in the most local scope that is required for them to work. Page 38: 'By the way, strangely enough, though you cannot declare ‘pure’ templates inside functions, you can declare struct templates.' Do you want to file a bug report against this? This has bothered me a few times too. Page 39: Template this parameters are also useful to determine how the type of the this reference is qualified, (const/immutable/shared/inout) Page 67: 'mixin template Concatenate() { Tuple!(This, U) opBinary(string op, this This)(This u) if (op == ~) { return tuple(this, u); } Tuple!(U, This) opBinaryRight(string op, this This)(This u) if (op == ~) { return tuple(u, this); } }' I think what you meant was this: mixin template Concatenate() { Tuple!(This, U) opBinary(string op, this This)(U u) if (op == ~) { return tuple(this, u); } Tuple!(U, This) opBinaryRight(string op, this This)(U u) if (op == ~) { return tuple(u, this); } } Page 76: 'At the time of this writing, the limitations are mostly: no classes and no exceptions (and so, no enforce).' DMD 2.057 supports classes and exceptions in CTFE =) Page 82: I'd be careful with that table. Probably most of the ones you marked as 'No' are actually 'Yes' when doing some clever things with is(typeof())? Page 90: '34 Extending a Class' Maybe add a note that this does not work across module boundaries and therefore has not much practical use. Page 90: 'return; // or return void;' That looks like it was actual syntax. Page 94/95: 'Strangely, you can only use it with the is(Type identifier, ...) syntax: you must have identifier.' 'For me, the main limitation is that template tuple parameters are not accepted. Too bad.' Do you want to file the enhancement requests, or should I file them? Having those would increase the consistency of the language. Keep up the good work!
Re: Array expanding
On 12/18/2011 11:12 PM, RenatoL wrote: Reading the book from Alexandrescu we can find this (page 103-104, at least in my edition): Expanding arrays has a couple of subtleties that concern possible reallocation of the array. Consider: auto a = [87, 40, 10, 2]; auto b = a; // Now a and b refer to the same chunk a ~= [5, 17]; // Append to a a[0] = 15; // Modify a[0] assert(b[0] == 15); // Pass or fail? it seems natural that the test is ok but it is not... if we read more we find: D leaves~= the freedom of either expanding by reallocation or opportunistically expanding in place if there is enough unused memory at the end of the current array. At a first glance this seems to be a serious issue... it seems hard to accept that b can lost its connection to a in a silent mode due to a reallocation Is there a safe mode to do this for large arrays? Assuming 'safe' means preserving aliasing: No. How would you implement it? Anyway, this is not such a huge issue in practice. If you want aliasing, just don't append to the slices.
Re: Array concat quiz
On 12/17/2011 02:43 AM, bearophile wrote: A small quiz. This Python2 code: m1 = [[A', B']] print m1 m2 = m1 + [[]] print m2 Prints: [[A', B']] [[A', B'], []] What does this D2 program print? import std.stdio; void main() { string[][] m1 = [[A', B']]; writeln(m1); string[][] m2 = m1 ~ [[]]; writeln(m2); } Bye, bearophile I do not think that this is very sensible (array-array appends are more natural than array-element appends, so disambiguation should go the other way). Is it documented anywhere or is it just an implementation artefact?
Re: -D option = Embedded documentation
On 12/16/2011 06:12 PM, dune wrote: What? Sorry but I don't understand... What I posted was an example, in reality there is tons of code inside the d file. Thanks That is not what you said. Obviously you should always give an example that actually fails, especially when you claim it does. $ cat worksforme.d /** * documentation here */ module worksforme; /// program entry point void main(){} $ dmd -D worksforme $ cat worksforme.html htmlhead META http-equiv=content-type content=text/html; charset=utf-8 titleworksforme/title /headbody h1worksforme/h1 !-- Generated by Ddoc from worksforme.d -- documentation herebrbr dldtbigvoid umain/u(); /big/dt ddprogram entry pointbrbr /dd /dl hrsmallPage generated by a href=http://www.digitalmars.com/d/2.0/ddoc.html;Ddoc/a. /small /body/html
Re: Restrict access to critical functions
On 12/15/2011 06:04 PM, Jonathan M Davis wrote: On Thursday, December 15, 2011 13:57:21 deadalnix wrote: Even haskell has non pure functions (IO monad for exemple). Actually, Haskell is a 100% purely functional language. Not entirely. For example: http://users.skynet.be/jyp/html/base/System-IO-Unsafe.html Monads are completely pure. They're _how_ Haskell manages to be pure with I/O, when every functional language before them had had to be impure with regards to I/O. - Jonathan M Davis
Re: Restrict access to critical functions
On 12/14/2011 01:28 PM, Kagamin wrote: Goal would be to have a possibility to compile and let run code from random people (some of them perhaps evil minded), watch over the processes and kill them, if they take too long or use up too much memory. I believe this is what SafeD is for. SafeD eliminates the possibility of memory corruption, it does not prevent the program from messing with the system.
Re: Cartesian product of ranges?
On 12/14/2011 09:14 PM, Justin Whear wrote: I've looked through std.algorithm and std.range, but haven't found anything to compute the Cartesian product of several ranges. I have the nagging feeling that this can be accomplished by combining several of the range transformations in the standard library. What I'm after is something like this: alias Tuple!(int, string) P; assert(equal( cartesianProduct([1, 2], [a, b]), [ P(1, a), P(1, b), P(2, a), P(2, b) ] )); auto cartesianProduct(R,S)(R r, S s)if(isInputRange!R isForwardRange!S){ struct CartesianProduct{ private{R r; S s, startS;} this(R r, S s){this.r=r; this.s=s; startS=this.s.save;} @property auto front(){return tuple(r.front, s.front);} @property bool empty(){return r.empty;} void popFront(){ s.popFront(); if(s.empty){ s = startS.save; r.popFront(); } } static if(isForwardRange!R): @property auto save(){return typeof(this)(r.save, s.save);} } return CartesianProduct(r,s); }
Re: How is string from ... different from string from a file ?
On 12/12/2011 03:35 PM, ParticlePeter wrote: Hi, I have a hard time reading in a string from a file. I don't get any compile time or run time errors, but my application does not work reliably when I read a string from a file. But when I define the same string within my code, everything runs perfect, allways. The string I want to use is an OpenGL Shader, but the problem is not to be related to OpenGL as far as a I see. Are there some format strings which I need to get rid of, and how ? I tried: import std.file ; string fragString = readText( Shader.vert ) ; import std.file , std.utf ; string fragString = toUTF8( readText( Shader.vert ) ) ; import std.stdio ; string text = ; auto file = File( Shader.vert ) ; foreach( line ; file.byLine() ) string ~= strip( to!( string )( line ) ) ; What else could I try ? Cheers, ParticlePeter ! OpenGL probably wants a zero-terminated string. It works if you add the code as a literal because string literals are zero-terminated. string fragString = readText( Shader.vert ) ~ '\0'; Alternatively, you can embed the file in you executable: immutable string fragString = import( Shader.vert ); // read at compile time
Re: How is string from ... different from string from a file ?
On 12/12/2011 06:37 PM, bearophile wrote: Timon Gehr: string fragString = readText( Shader.vert ) ~ '\0'; I think using toStringz is more self-documenting. Bye, bearophile There is nothing more self-documenting than actually appending the zero. Claiming toStringz is better in that regard is like saying a+1 is less self-documenting than doAddo(a) ;) There might be other benefits of using toStringz though, (for example, it won't add the zero if it is already there, but that does not apply here).
Re: deep copy or shallow copy?
On 12/09/2011 09:32 PM, Ali Çehreli wrote: On 12/08/2011 12:52 PM, Timon Gehr wrote: On 12/08/2011 09:50 PM, RenatoL wrote: snippet 1) auto arr1 = [1,2,3]; auto arr2 = arr1; arr1[1] = 22; arr2[2] = 33; foreach (i; 0..arr1.length) write(arr1[i], ); writeln(); foreach (i; 0..arr2.length) write(arr2[i], ); output: 1 22 33 1 22 33 OK snippet 2) int[3] arr1 = [1,2,3]; int[3] arr2 = arr1; arr1[1] = 22; arr2[2] = 33; foreach (i; 0..arr1.length) write(arr1[i], ); writeln(); foreach (i; 0..arr2.length) write(arr2[i], ); output: 1 22 3 1 2 33 that's unclear to me... i agree with the behaviour of the dynamic array... but if we have a static array we have a deep copy? Both copies are 'shallow', but static arrays are value types. 'shallow' would be misleading for a fixed-length (static) array because there is nothing else but the elements for fixed-length arrays: It is not misleading since the array might be an array of references. (and if it does not contain references, shallow and deep are the same thing anyway) void main() { int[3] a; assert(cast(void*)a == cast(void*)a[0]); } Fixed-length array storage is similar to C arrays. These are different: - they don't decay to a 'pointer to first element' when passed to functions (being value types, the whole array is copied) - a.length is a convenience, equivalent to a.sizeof / a[0].sizeof So it is impossible to do anything shallow with them unless we explicitly maintain a pointer to a fixed-length array ourselves. Ali You can always slice it, of course int[3] a; int[] b = a[]; // b now is a dynamic array that aliases a's contents
Re: deep copy or shallow copy?
On 12/08/2011 09:50 PM, RenatoL wrote: snippet 1) auto arr1 = [1,2,3]; auto arr2 = arr1; arr1[1] = 22; arr2[2] = 33; foreach (i; 0..arr1.length) write(arr1[i], ); writeln(); foreach (i; 0..arr2.length) write(arr2[i], ); output: 1 22 33 1 22 33 OK snippet 2) int[3] arr1 = [1,2,3]; int[3] arr2 = arr1; arr1[1] = 22; arr2[2] = 33; foreach (i; 0..arr1.length) write(arr1[i], ); writeln(); foreach (i; 0..arr2.length) write(arr2[i], ); output: 1 22 3 1 2 33 that's unclear to me... i agree with the behaviour of the dynamic array... but if we have a static array we have a deep copy? Both copies are 'shallow', but static arrays are value types.
Re: C++ vs D aggregates
On 12/04/2011 12:00 PM, Kagamin wrote: Dejan Lekic Wrote: Do D2 aggregates behave the same, or are there notable differences? D restricts usage to static initializers only, C++ doesn't have this limitation. This works: struct S{int x;} void main(){ int a; S x = {a}; } What does not?
Re: Why is align() on structures not allowed within unit-test code blocks?
On 12/04/2011 03:01 PM, GrahamC wrote: Is there a good reason why align() applied to structure definitions is not allowed on the struct definition line within unit-test code blocks? E.g.: unittest { align(1) struct Foo { char c; int i; } void Bar() { Foo f; } } int main() { return 0; } fails to compile. The error message is: found 'align' instead of statement The error message is the same for both DMD and GDC. If you take the align(1) out it compiles OK. If you move the structure definition out of the unit-test block but leave the align(1) in place it compiles OK. If you put the align(1) on each member variable definition instead of the struct line it compiles OK. If the structure type is only used within the unit-test code then I would think it ought to be possible to define it (including it's alignment attribute) within that unit-test code block. The reason is that it is parsed as function-local and that DMD's parser for some strange reason uses different grammar rules for declarations when inside a function body. You could maybe file a bug report. A possible workaround is to take the declaration out of the unittest block and wrap it into a version(unittest) block like this: version(unittest) { align(1) struct Foo { char c; int i; } } unittest { void Bar() { Foo f; } } int main() { return 0; } It invades the namespace of the module when compiling with -unittest though.
Re: Non-atomic ops allowed on shared variables?
On 12/03/2011 09:49 PM, Jonathan M Davis wrote: On Saturday, December 03, 2011 21:41:45 Andrej Mitrovic wrote: On 12/3/11, Jonathan M Davisjmdavisp...@gmx.com wrote: That page says that reads and writes are guaranteed to be atomic for shared. It does _not_ say that something like ++threadsCount is guaranteed to be atomic. Woops, sorry it was a typo. I meant page 411, not 413. It says it's an error there. Btw, I never said ++ was atomic, I've asked whether something has changed. IOW I thought perhaps this used to be an error but maybe it was changed to make increment/decrement to be atomic on shared variables. That's not the case of course.. Ah, okay. I had completely forgotten about that. That seems _very_ restrictive to me, and for it to work correctly, I would expect the compiler to have to be smart enough to realize when a synchronized block is in use or a mutex is in use, and I don't see how it can be that smart across function calls (since if it isn't that smart, it forces you to use atomicOp even when it's completely unnecessary), so I don't see how that could possibly work without unnecessarily requiring you to use atomicOp all over the place. I have no idea what the plan on this is at this point, and I'm very surprised that such a requirement was ever suggested. It's the kind of question that you may have to bring up in the main newsgroup if you want a good answer for it though, since the number of people who pay attention to d-learn is much lower, and I don't know if any of the key devs who _would_ know pay attention here. - Jonathan M Davis cast()
Re: Non-atomic ops allowed on shared variables?
On 12/03/2011 11:30 PM, Jonathan M Davis wrote: On Saturday, December 03, 2011 22:56:41 Timon Gehr wrote: On 12/03/2011 09:49 PM, Jonathan M Davis wrote: On Saturday, December 03, 2011 21:41:45 Andrej Mitrovic wrote: On 12/3/11, Jonathan M Davisjmdavisp...@gmx.com wrote: That page says that reads and writes are guaranteed to be atomic for shared. It does _not_ say that something like ++threadsCount is guaranteed to be atomic. Woops, sorry it was a typo. I meant page 411, not 413. It says it's an error there. Btw, I never said ++ was atomic, I've asked whether something has changed. IOW I thought perhaps this used to be an error but maybe it was changed to make increment/decrement to be atomic on shared variables. That's not the case of course.. Ah, okay. I had completely forgotten about that. That seems _very_ restrictive to me, and for it to work correctly, I would expect the compiler to have to be smart enough to realize when a synchronized block is in use or a mutex is in use, and I don't see how it can be that smart across function calls (since if it isn't that smart, it forces you to use atomicOp even when it's completely unnecessary), so I don't see how that could possibly work without unnecessarily requiring you to use atomicOp all over the place. I have no idea what the plan on this is at this point, and I'm very surprised that such a requirement was ever suggested. It's the kind of question that you may have to bring up in the main newsgroup if you want a good answer for it though, since the number of people who pay attention to d-learn is much lower, and I don't know if any of the key devs who _would_ know pay attention here. - Jonathan M Davis cast() Sure, you could cast away shared, but there's something seriously wrong with shared if you have to constantly cast it away in order to use a shared object. - Jonathan M Davis There is nothing wrong with shared. The type system is just not expressive enough to allow some perfectly fine code without casting to and away from shared now and then. Making it expressive enough would make the language more complex. And that system still would quite certainly be more conservative than necessary.
Re: Abstract functions in child classes
On 12/02/2011 05:05 PM, Adam wrote: To step back a bit, what is the *benefit* of not requiring a class to be declared abstract if it does not override an abstract member? It introduces implicit behavior and the potential for an additional test case (in *what* sane world should I even HAVE to test that something is instantiable?) for the sake of not typing 8 characters in a Class definition A second possible use case: class C(T): T{ // some declarations } Now you really want that template to be instantiable with T being either an abstract or a concrete class. Anything else is bound to become extremely annoying.
Re: Abstract functions in child classes
On 12/02/2011 08:10 PM, Adam wrote: A second possible use case: class C(T): T{ // some declarations } Now you really want that template to be instantiable with T being either an abstract or a concrete class. Anything else is bound to become extremely annoying. Could you expand on this case a bit? I'm not sure I follow the point one way or another. This is an useful pattern. I don't have a very useful example at hand, but this one should do. It does similar things that can be achieved with traits in Scala for example. import std.stdio; abstract class Cell(T){ abstract void set(T value); abstract const(T) get(); private: T field; } class AddSetter(C: Cell!T,T): C{ override void set(T value){field = value;} } class AddGetter(C: Cell!T,T): C{ override const(T) get(){return field;} } class DoubleCell(C: Cell!T,T): C{ override void set(T value){super.set(2*value);} } class OneUpCell(C: Cell!T,T): C{ override void set(T value){super.set(value+1);} } class SetterLogger(C:Cell!T,T): C{ override void set(T value){ super.set(value); writeln(cell has been set to ',value,'!); } } class GetterLogger(C:Cell!T,T): C{ override const(T) get(){ auto value = super.get(); writeln(',value,' has been retrieved!); return value; } } class ConcreteCell(T): AddGetter!(AddSetter!(Cell!T)){} class OneUpDoubleSetter(T): OneUpCell!(DoubleCell!(AddSetter!(Cell!T))){} class DoubleOneUpSetter(T): DoubleCell!(OneUpCell!(AddSetter!(Cell!T))){} void main(){ Cell!string x; x = new ConcreteCell!string; x.set(hello); writeln(x.get()); Cell!int y; y = new SetterLogger!(ConcreteCell!int); y.set(123); // prints: cell has been set to '123'! y = new GetterLogger!(DoubleCell!(ConcreteCell!int)); y.set(1234); y.get(); // prints '2468' has been retrieved! y = new AddGetter!(OneUpDoubleSetter!int); y.set(100); writeln(y.get()); // prints 202 y = new AddGetter!(DoubleOneUpSetter!int); y.set(100); writeln(y.get()); // prints 201 // ... }
Re: Abstract functions in child classes
On 12/02/2011 09:05 PM, Timon Gehr wrote: On 12/02/2011 08:10 PM, Adam wrote: A second possible use case: class C(T): T{ // some declarations } Now you really want that template to be instantiable with T being either an abstract or a concrete class. Anything else is bound to become extremely annoying. Could you expand on this case a bit? I'm not sure I follow the point one way or another. This is an useful pattern. I don't have a very useful example at hand, but this one should do. It does similar things that can be achieved with traits in Scala for example. import std.stdio; abstract class Cell(T){ abstract void set(T value); abstract const(T) get(); private: T field; } class AddSetter(C: Cell!T,T): C{ override void set(T value){field = value;} } class AddGetter(C: Cell!T,T): C{ override const(T) get(){return field;} } class DoubleCell(C: Cell!T,T): C{ override void set(T value){super.set(2*value);} } class OneUpCell(C: Cell!T,T): C{ override void set(T value){super.set(value+1);} } class SetterLogger(C:Cell!T,T): C{ override void set(T value){ super.set(value); writeln(cell has been set to ',value,'!); } } class GetterLogger(C:Cell!T,T): C{ override const(T) get(){ auto value = super.get(); writeln(',value,' has been retrieved!); return value; } } class ConcreteCell(T): AddGetter!(AddSetter!(Cell!T)){} class OneUpDoubleSetter(T): OneUpCell!(DoubleCell!(AddSetter!(Cell!T))){} class DoubleOneUpSetter(T): DoubleCell!(OneUpCell!(AddSetter!(Cell!T))){} void main(){ Cell!string x; x = new ConcreteCell!string; x.set(hello); writeln(x.get()); Cell!int y; y = new SetterLogger!(ConcreteCell!int); y.set(123); // prints: cell has been set to '123'! y = new GetterLogger!(DoubleCell!(ConcreteCell!int)); y.set(1234); y.get(); // prints '2468' has been retrieved! y = new AddGetter!(OneUpDoubleSetter!int); y.set(100); writeln(y.get()); // prints 202 y = new AddGetter!(DoubleOneUpSetter!int); y.set(100); writeln(y.get()); // prints 201 // ... } Oh, forgot to mention: This would not compile, if an explicit 'abstract' declaration on template class definitions was required.
Re: Abstract functions in child classes
On 12/02/2011 09:27 PM, Adam wrote: So this pattern allows you to provide partial implementations of an abstract, and use template specialization to provide a sort of multiple inheritance rather than strict class definition / extension. That's important in Scala because of the lack of multiple inheritance (as I understand it). Am I understanding this correctly - that the point of this approach is to replicate composition by multiple inheritance? You can do that, but templates provide you with a lot more power. Note that some of my examples cannot be expressed as nicely in terms of multiple inheritance. That is because they rely on the order in which the classes are composed. This is sometimes discouraged in Scala afaik. I think, because there the type of an object does not depend on the trait mixin order. (not an issue here) Parameterizing on the base class has quite some applications, its applications in C++ even have an own wikipedia page: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Re: Profile DMD
On 12/01/2011 07:42 PM, Nick Sabalausky wrote: Is there an easy way to profile DMD similar to how DMD itself has the -profile switch? Use DMC, I guess. http://www.digitalmars.com/ctg/trace.html
Re: idea for variant improvement
On 11/30/2011 07:53 PM, bioinfornatics wrote: Variant is very usefull but a function who take a variant as parameter do not works whithout a cast. but You can assign a value form any type in statement Variant v = 2u. the code below explain well the problem --- import std.string; import std.stdio; import std.variant; void func( Variant param ){ writeln( it works ); } void func2( T )( T param ){ Variant a = cast(Variant) param; writeln( it works ); } void main( string[] args ){ Variant a = 2u; // works func( a ); //func( 2u ); // does not works func2( 2u ); } -- It will be great if function func work in all case Vote here: http://d.puremagic.com/issues/show_bug.cgi?id=7019
Re: idea for variant improvement
On 11/30/2011 11:55 PM, bioinfornatics wrote: Le mercredi 30 novembre 2011 à 22:19 +0100, Timon Gehr a écrit : On 11/30/2011 07:53 PM, bioinfornatics wrote: Variant is very usefull but a function who take a variant as parameter do not works whithout a cast. but You can assign a value form any type in statement Variant v = 2u. the code below explain well the problem --- import std.string; import std.stdio; import std.variant; void func( Variant param ){ writeln( it works ); } void func2( T )( T param ){ Variant a = cast(Variant) param; writeln( it works ); } void main( string[] args ){ Variant a = 2u; // works func( a ); //func( 2u ); // does not works func2( 2u ); } -- It will be great if function func work in all case Vote here: http://d.puremagic.com/issues/show_bug.cgi?id=7019 yes thanks i will do. And you you do not vote for this feature? I already have =). http://d.puremagic.com/issues/votes.cgi?action=show_bugbug_id=7019
Re: Make a variable single-assignment?
On 12/01/2011 12:08 AM, Stewart Gordon wrote: On 21/11/2011 20:06, Jesse Phillips wrote: What you are describing is Head Const, and is not available. http://www.d-programming-language.org/const-faq.html#head-const It will not be added as it doesn't provide any guarantees about the code that is useful to the compiler. It can't be added to the existing system without complicating the type system even more, which outweighs the benefits. snip Guarantees about the code don't need to be useful to the compiler - they can be just useful to the programmer. After all, this is the main point of DbC. And it doesn't need to be a full-fledged head const. At the simplest, a single-assignment variable could just be an rvalue - something of which the address cannot be taken and so the absence of head const becomes irrelevant. That said, it isn't much complexity to allow the address to be taken of such a thing final T data; auto ptr = data; with the following rules: - if T is a value type, immutable(something)[] or immutable(something)*, then data is an immutable(T)* - otherwise, data is a const(T)*. Once upon a time there was const/final/invariant. What exactly did final do back then? Stewart. Here is some documentation from that time: http://www.digitalmars.com/d/final-const-invariant.html It did indeed mean head const, like in Java. I wonder why it was removed from the design though, it gives extra expressiveness at no cost. (maybe because then people will start pushing for readonly (tail const)? :))
Re: Overhead of synchronized class used in unshared situation
On 11/28/2011 07:37 AM, breezes wrote: Thanks. It seems that I have to write two classes, one synchronized and one is not. Of course the synchronized one should be the wrapper. However, all members of a synchronized class are also shared. So I can not use the un-synchronized class in the synchronized wrapper class directly. I found two ways to overcome this problem: 1. Cast away shared whenever using the wrapped un-synchronized object. 2. Define the wrapped un-synchronized object as __gshared. Which way if more preferred? The first one. You manually ensure, by locking, that the object is actually unshared during that particular time frame and that there are memory fences. Casting away shared makes that information available to the compiler.
Re: Make a variable single-assignment?
On 11/21/2011 03:04 PM, Alex Rønne Petersen wrote: Hi, Is there any way to make a variable single-assignment, regardless of its type? I.e.: void foo() { some magical keyword? int i = 0; i = 2; // Error: i cannot be reassigned } I realize const and immutable will do this, but they are transitive and infect the type, which I do *not* want. I simply want the variable to be single-assignment. Is it possible? - Alex How should that be possible without infecting the type? void main(){ magical keyword int i = 0; auto a = i; *a = 2; // oops... }
Re: Mutable enums
On 11/17/2011 03:19 PM, Steven Schveighoffer wrote: On Wed, 16 Nov 2011 17:39:16 -0500, Timon Gehr timon.g...@gmx.ch wrote: On 11/16/2011 10:56 PM, Steven Schveighoffer wrote: On Wed, 16 Nov 2011 16:16:48 -0500, Timon Gehr timon.g...@gmx.ch wrote: On 11/16/2011 09:00 PM, Steven Schveighoffer wrote: On Wed, 16 Nov 2011 14:26:57 -0500, Timon Gehr timon.g...@gmx.ch wrote: On 11/16/2011 02:22 PM, Steven Schveighoffer wrote: On Tue, 15 Nov 2011 13:45:02 -0500, Timon Gehr timon.g...@gmx.ch wrote: Note that this is an explicit allocation: int[] a = [1,2,3]; // just as explicit as a NewExpression Only the enums hide it sometimes, but actually you should know the involved types. As I've said, there are already ways to explicitly allocate memory. A suggested replacement for this is: int[] a = array(1, 2, 3); And you could always do: int[] a = [1, 2, 3].dup; Nobody complains about having to do: char[] a = hello.dup; I don't see why we couldn't do the same for all array literals. Because 'immutable' behaves nicely on built-in value types, but not on arbitrary reference types. string is a reference type. We hear no complaints about strings being stored in ROM and the type of literals being immutable. string is not an immutable type. It is immutable(char)[] and char is a built-in value type. static assert(isMutable!string); It fits my definition of a valid enum reference type (immutable or implicitly castable to immutable). The point is that the data referenced is stored in ROM and therefore a) immutable and b) fully defined at compile-time. Indeed. But fact is, the data that is qualified with immutable is not of reference type therefore it behaves nicely. And you don't get that in the general case. In the general case, there is always a library function for construction. In other words, what the compiler currently does for array literals can be done in a library. But a library cannot create ROM space. The compiler-based features (and CTFE in general) should be helping us create things at compile time, not at run time. We already have the tools to construct arrays at runtime. I am looking for something like this: template writeln(T...)(T){ alias writelnImpl!(writelnInferConst!T) writeln; } (it is even trivial to parse, unlike normal function definitions!) What does writelnInferConst!T do? I'm afraid I'm not getting what you are saying. I was thinking writeln should do this: void writeln(T...)(const T args) {...} As you pointed out, this cannot print types that have a non-const toString method (caching the result could be a perfectly valid reason for that.) writelnInferConst finds out which parameters can be treated as const and still be printed so that the correct version of writeln may be called. For example: class Foo{ // can be printed if const string toString()const{return Foo;} } class Bar{ // cannot be printed if const string cache; string toString(){return cache!is null?cache:(cache=Bar);} } template hasConstToString(T){ enum hasConstToString = is(typeof((const T t){return t.toString();})); } template writelnInferConstImpl(T...){ static if(!T.length) alias T X; else static if(hasConstToString!(T[0])){ alias T[0] _; alias TypeTuple!(const(_),writelnInferConst!(T[1..$])) X; }else alias TypeTuple!(T[0],writelnInferConst!(T[1..$])) X; } template writelnInferConst(T...){alias writelnInferConstImpl!T.X writelnInferConst;} // (bug 6966) static assert(is(writelnInferConst!(Foo,Bar,Foo,Foo,Bar)==TypeTuple!(const(Foo),Bar,const(Foo),const(Foo),Bar))); The real thing would also do stuff like actual argument immutable(Foo[])[] = formal argument const(Foo[][]). In order to get rid of bloat created by pointless instantiations of writelnImpl. I have an enhancement request in for intercepting IFTI (not sure if it applies here): http://d.puremagic.com/issues/show_bug.cgi?id=4998 It has a complexity of at least 2^numparams and probably all kinds of odd implications for the compiler internals that would lead to a buggy implementation. I'm not a compiler writer, but I don't see how this is the case. There were/are quite a few error gagging related bugs. I guess this would be similar. I think this is a better solution: void foo2(T: ParameterTypeTuple!foo[0])(T t){foo(t);} Then it is just a matter of applying proper value range propagation for IFTY: void bar(T: short)(T t){...} void main(){ bar(1); // ok } The issue with all this is, IFTI doesn't work that way: void foo(T: short)(T t) {} void main() { foo(1); } testifti.d(5): Error: template testifti.foo(T : short) does not match any function template declaration testifti.d(5): Error: template testifti.foo(T : short) cannot deduce template function from argument types !()(int) IFTI decides the types of literals before trying to find a proper template to instantiate. Any possibility to intercept the decision of literal type
Re: Using __traits(getMember...) in alias statement
On 11/17/2011 06:12 PM, Tobias Pankrath wrote: It would be cool, if the following would be possible. immutable string MemberID = M; struct A {} struct B { alias A M; } template Member(T) { static if(__traits(hasMember, T, MemberID)) { alias __traits(getMember, T, MemberID) Member; } else alias TypeTuple!() Member; } void main() { alias Member!(B) M; } Currently dmd will print basic type expected, not __traits. Why isn't traits allowed here and if we allow __traits there, would this introduce any ambiguities? This works: alias TypeTuple!(__traits(getMember, T, MemberID)) Member; It is a mere grammar issue. The aliased symbol must look like a valid type. I'd like that to change too. This helps a lot with the current state of affairs: template ID(alias x){alias x ID;} It will even allow funny things like this: alias ID!((a,b){return a+b;}) add; static assert(add(1,2) == 3);
Re: Using __traits(getMember...) in alias statement
On 11/17/2011 06:41 PM, Timon Gehr wrote: On 11/17/2011 06:12 PM, Tobias Pankrath wrote: It would be cool, if the following would be possible. immutable string MemberID = M; struct A {} struct B { alias A M; } template Member(T) { static if(__traits(hasMember, T, MemberID)) { alias __traits(getMember, T, MemberID) Member; } else alias TypeTuple!() Member; } void main() { alias Member!(B) M; } Currently dmd will print basic type expected, not __traits. Why isn't traits allowed here and if we allow __traits there, would this introduce any ambiguities? This works: alias TypeTuple!(__traits(getMember, T, MemberID)) Member; This only works if the __traits gets you a TypeTuple back. (It won't work in this case, it will create a one-element tuple). Better use ID from below. It is a mere grammar issue. The aliased symbol must look like a valid type. I'd like that to change too. This helps a lot with the current state of affairs: template ID(alias x){alias x ID;} It will even allow funny things like this: alias ID!((a,b){return a+b;}) add; static assert(add(1,2) == 3);
Re: Mutable enums
On 11/17/2011 07:23 PM, Steven Schveighoffer wrote: On Thu, 17 Nov 2011 12:31:58 -0500, Timon Gehr timon.g...@gmx.ch wrote: On 11/17/2011 03:19 PM, Steven Schveighoffer wrote: What does writelnInferConst!T do? I'm afraid I'm not getting what you are saying. I was thinking writeln should do this: void writeln(T...)(const T args) {...} As you pointed out, this cannot print types that have a non-const toString method (caching the result could be a perfectly valid reason for that.) Caching string representation IMO is not a significant use case. Not only that, but toString should be deprecated anyways in favor of a stream-based system. writelnInferConst finds out which parameters can be treated as const and still be printed so that the correct version of writeln may be called. For example: class Foo{ // can be printed if const string toString()const{return Foo;} } class Bar{ // cannot be printed if const string cache; string toString(){return cache!is null?cache:(cache=Bar);} } template hasConstToString(T){ enum hasConstToString = is(typeof((const T t){return t.toString();})); } template writelnInferConstImpl(T...){ static if(!T.length) alias T X; else static if(hasConstToString!(T[0])){ alias T[0] _; alias TypeTuple!(const(_),writelnInferConst!(T[1..$])) X; }else alias TypeTuple!(T[0],writelnInferConst!(T[1..$])) X; } template writelnInferConst(T...){alias writelnInferConstImpl!T.X writelnInferConst;} // (bug 6966) static assert(is(writelnInferConst!(Foo,Bar,Foo,Foo,Bar)==TypeTuple!(const(Foo),Bar,const(Foo),const(Foo),Bar))); If your goal is to reduce template bloat, I think this is not the solution. But also note that this still does not guarantee const. I don't really see the point of doing all these templates if you aren't going to guarantee writeln doesn't modify the data. The issue with all this is, IFTI doesn't work that way: void foo(T: short)(T t) {} void main() { foo(1); } testifti.d(5): Error: template testifti.foo(T : short) does not match any function template declaration testifti.d(5): Error: template testifti.foo(T : short) cannot deduce template function from argument types !()(int) IFTI decides the types of literals before trying to find a proper template to instantiate. Any possibility to intercept the decision of literal type or of instantiation would be useful. I think that it's better suited to the constraints, because there is more power there. But I'm not sure. If you can find a more straightforward way, I'm all for it. In any case, I need to update the bug report, because the general case is if foo has an overload. For instance: foo(short s); foo(wstring w); foo2 should be able to call both with 1 and hello without issue. My driving use case to create the enhancement was creating a wrapper type that intercepted function calls. I planned to use opDispatch, but it didn't quite work with literals. Ok, I see the problem. My proposed IFTI template mechanism would save the day. It would look like this (static foreach would have to be replaced by a recursive mixin template because Walter encountered implementation difficulties). template OverloadsOf(alias symbol){ // should this be in std.traits? alias TypeTuple!(__traits(getOverloads, __traits(parent,symbol), __traits(identifier,symbol))) OverloadsOf; } auto wrapper(alias foo)(ParameterTypeTuple!foo args){ return foo(args); } template opDispatch(string op,T...)(T){ static foreach(foo; OverloadsOf!(mixin(op))){ alias wrapper!foo opDispatch; } static if(OverloadsOf!(mixin(op)).length==0) { // we are dealing with a template function auto opDispatch(T args){ return foo(args); } } } Pardon my saying so, but this looks horrendous. Not to mention that I don't think it would work. Oh, it would certainly work. IFTI instantiates templates, it does not look inside instantiated templates for overloads. This works, does this solve the confusion?: void foo(int){writeln(foo!);} void bar(double){writeln(bar!);} template merge(){ alias foo qux; alias bar qux; } alias merge!().qux qux; void main(){ qux(1); // calls foo qux(1.0); // calls bar } BTW, your proposed IFTI template mechanism, do you have it stated anywhere? Maybe it fixes the problem I mentioned. Not yet, I will file a bugzilla enhancement request and post a link here. What it does is quite simple: 1. Apply normal IFTI instantiation rules to the IFTI template, as if it was a function template. 2. Instantiate the IFTI template with the deduced arguments. 3. The result of the instantiation must be callable with the original arguments. Call it. This allows the function that is called to have a different (albeit compatible) signature from what IFTI would give you. Seems rather odd you should have to jump through these hoops to get the compiler to use ROM space. But I concede that I did not know of this trick. It does not sway my opinion that CTFE should produce ROM-stored references, and library function
Re: Mutable enums
On 11/16/2011 02:22 PM, Steven Schveighoffer wrote: On Tue, 15 Nov 2011 13:45:02 -0500, Timon Gehr timon.g...@gmx.ch wrote: On 11/15/2011 04:53 PM, Steven Schveighoffer wrote: Yes, but this is spelled out because copying a static array requires moving data. However, this does *not* require a hidden allocation (even though it does do a hidden allocation currently). I'm not worried about copying data as much as I am about hidden allocations. Hidden allocations are a huge drag on performance. Every time you allocate, you need to take a global GC lock, and it's an unbounded operation (doing one allocation could run a collection cycle). You don't actually _need_ a global GC lock. It is just how it is implemented in this case. This is all fine in theory. I haven't seen any implementations. But memory allocations are not cheap, even without a GC lock. Note that this is an explicit allocation: int[] a = [1,2,3]; // just as explicit as a NewExpression Only the enums hide it sometimes, but actually you should know the involved types. As I've said, there are already ways to explicitly allocate memory. A suggested replacement for this is: int[] a = array(1, 2, 3); And you could always do: int[] a = [1, 2, 3].dup; Nobody complains about having to do: char[] a = hello.dup; I don't see why we couldn't do the same for all array literals. Because 'immutable' behaves nicely on built-in value types, but not on arbitrary reference types. That is the idea. Get rid of the hidden allocation. Writeln *is* const correct, it can certainly print immutable(int)[]. Well, there is a function called writeln that can do that. That is a different function. But the one that gets actually called is not const correct as well. This is writeln: // Most general instance void writeln(T...)(T args) if (T.length 1 || T.length == 1 !is(typeof(args[0]) : const(char)[])) { stdout.write(args, '\n'); } = writeln([1,2,3]); // modulo IFTY: writeln!(int[])([1,2,3]); // const correct? writeln!(int[])([1,2,3].idup); // nope! Error: cannot implicitly convert expression (_adDupT( _D11TypeInfo_Ai6__initZ,[1,2,3])) of type immutable(int)[] to int[] I'm not sure what this means. If [1, 2, 3] is typed as immtuable(int)[], it will compile. Simple test: immutable(int)[] a = [1, 2, 3]; writeln(a); works with 2.056. That is like saying void foo(int[] a){...} // prints a void bar(immutable(int)[] a){...} // prints a int[] a = [1,2,3]; immutable(int)[] b = [1, 2, 3]; foo(a); bar(b); = Oh, bar is const correct because I can call foo with mutable data and bar with immutable data. foo is writeln!(int[]) bar is writeln!(immutable(int)[]) in effect, if you do: writeln(hello.dup); The compiler cannot assume that the IFTI'd writeln!(char[]) will not change the argument, ergo it cannot optimize away the .dup, even though it would be a valid transformation as long as the programmer does not make the program semantics depend on the identity relation on immutable references (doing so defeats the purpose of immutability). The issue is not writeln, it's what the type of the array literal/enum is. Technically, an array literal is equivalent to an enum, and should follow the same rules. Remember that immutable is transitive. That can really get in your way in this case. If the data is stored in ROM, it should be typed as immutable. If it's not, then it could be modified. The only other option is heap allocation and construction on use, which I've already said is undesirable. If we start from all array literals and enums that contain references store the referenced data in ROM, then we will find ways to deal with any inconveniences. It's all a matter of what's more important in a system language, performance or convenience. Both are more important. It is D. Everything you need to do is make the enum static immutable instead. D is also a scripting language and an application programming language. auto a = [new Foo, new Bar, new Qux]; // I want that to work.
Re: Mutable enums
On 11/16/2011 08:26 PM, Timon Gehr wrote: auto a = [new Foo, new Bar, new Qux]; // I want that to work. (It currently does, if that was unclear)