parallelFuture
I've created an alpha release of parallelFuture, a high-level parallelization library for D2. Right now, it has a task pool, futures, parallel foreach, and parallel map. Here's the (IMHO) coolest example: auto pool = new ThreadPool(); // Assuming we have a function isPrime(), print all // prime numbers from 0 to uint.max, testing for primeness // in parallel. auto myRange = iota(0, uint.max); foreach(num; pool.parallel(myRange)) { if(isPrime(num)) { synchronized writeln(num); } } The interface is there and it seems to work, although it has not been extensively stress tested yet. Some of the implementation details could admittedly use some cleaning up, and I would appreciate help from some threading gurus on improving my queue (right now it's a naive synchronized singly-linked list) and getting condition mutexes to work properly. (Right now, I'm using atomic polling followed by sleeping for 1 millisecond in a lot of places. It's a kludge, but it seems to work reasonably well in practice.) The code is at: http://dsource.org/projects/scrapple/browser/trunk/parallelFuture/parallelFuture.d The docs are at: http://cis.jhu.edu/~dsimcha/parallelFuture.html
Re: parallelFuture
dsimcha wrote: I've created an alpha release of parallelFuture, a high-level parallelization library for D2. Right now, it has a task pool, futures, parallel foreach, and parallel map. Here's the (IMHO) coolest example: auto pool = new ThreadPool(); // Assuming we have a function isPrime(), print all // prime numbers from 0 to uint.max, testing for primeness // in parallel. auto myRange = iota(0, uint.max); foreach(num; pool.parallel(myRange)) { if(isPrime(num)) { synchronized writeln(num); } } The interface is there and it seems to work, although it has not been extensively stress tested yet. Some of the implementation details could admittedly use some cleaning up, and I would appreciate help from some threading gurus on improving my queue (right now it's a naive synchronized singly-linked list) and getting condition mutexes to work properly. (Right now, I'm using atomic polling followed by sleeping for 1 millisecond in a lot of places. It's a kludge, but it seems to work reasonably well in practice.) The code is at: http://dsource.org/projects/scrapple/browser/trunk/parallelFuture/parallelFuture.d The docs are at: http://cis.jhu.edu/~dsimcha/parallelFuture.html Nice. About the tasks: In .Net a worker thread is created for each cpu core. Each worker thread has its own local queue of tasks which it initially retrieves from the global queue but if the tasks creates new tasks it adds to its local queue directly for less contention. When it finishes completing a task it takes the next from the back of its local queue to take advantage of cache (like a stack). The tasks at the front of the queue can be stolen from another worker thread if its local queue and the global queue are both empty to maximize cpu usage. Also the task's wait for complete is only considered complete if all of the tasks it created too are complete (kinda like recursion). What is the implementation or plans like for this.
Re: static arrays becoming value types
Tue, 20 Oct 2009 16:25:05 -0400, Robert Jacques thusly wrote: On Tue, 20 Oct 2009 15:19:15 -0400, language_fan f...@bar.com.invalid wrote: Real tuple types do not have a special type tag which gets injected implicitly with structs. So every time you try to do something lightweight by emulating tuples, you need to refer to the global Tuple type or bang your head to the wall. Or use a templated opAssign mixin to allow two desperate types to be assigned to each other. Wow, you need templates to implement == for built-in values types, nice.. Besides, I think you're comparing apples to oranges. In the SOL example, you use the same declaration for all types. Shouldn't the SOL example be: val a = (1,2) : [Int,Int] val b = (1,2) : [Int,Int] val c = (2,3) : MyCustomTupleType[Int,Int] which would probably generate: assert(a == b); // ok assert(a != c); // Error: incompatible types for ((a) != (b)) If you have built-in tuple literals, there is no way you can build a MyCustomTupleType without resorting to other language features. There are no apples and oranges, cause they both are seen as (Int,Int) by the equivalence checker. Do you understand how equivalence works in structural typing system (http://en.wikipedia.org/wiki/ Structural_type_system) vs nominal typing? In structural equivalence there are no names attached to the types (well there might be, but those are omitted in the comparison), only their internal structure matters. Why would anyone want to create two incompatible tuples by default as you still would have 'typedef' and 'struct' for implementing just that.
Re: stack frame optimization problem
On Wed, 21 Oct 2009 00:55:26 +0300, sprucely timber...@gmail.com wrote: To try to be sure I had the correct syntax I tried the -S option of g++ along with a switch for intel syntax to output the assembly. However the portion corresponding to the inline assembly was still in ATT syntax. For my resulting D executable I tried using hte, but it would abort after mentioning something about a nonexistent htcfg file. I didn't find much info after a cursory search. I gave up easily because I wasn't sure if I would be able to make proper use of it. Maybe I should take an x86 assembly course. I believe DMD comes with a Linux binary of obj2asm. For Windows you can use the free version of IDA. -- Best regards, Vladimir mailto:thecybersha...@gmail.com
Re: Proposed D2 Feature: = for anonymous delegates
Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something?
Re: Proposed D2 Feature: = for anonymous delegates
Wed, 21 Oct 2009 12:35:41 +0200, Pelle Månsson thusly wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? No, in this context the exact type can be inferred unambiguously without worrying about overloading. From the error message test.d(5): basic type expected, not auto test.d(5): found 'auto' when expecting ')' test.d(5): semicolon expected following function declaration test.d(5): found 'x' when expecting ',' test.d(5): expression expected, not ')' test.d(5): found '{' when expecting ',' test.d(5): expression expected, not 'return' test.d(5): found 'x' when expecting ',' test.d(5): found ';' when expecting ',' test.d(5): expression expected, not '}' I can see that the compiler does not even support this on syntactic level.
Re: Revamping associative arrays
Piotrek wrote: Bill Baxter pisze: On Sun, Oct 18, 2009 at 1:12 PM, Piotrek star...@tlen.pl wrote: Bill Baxter pisze: I think the default should be to iterate over whatever 'in' looks at. I was almost convinced, because that rule has a sense. But treating normal arrays and associative array has more sense to me. fun (SomeObject object) { foreach (element;object.arr1){ //normal, but how do I know at first look //just do something with element } foreach (element;object.arr2){ // assoc, but how do I know at first look //just do something with element hopefully not index } That sounds like an argument that there should be no default, because either way it's not clear whether you're iterating over keys or values. Really?! That wasn't my intention :) In both cases I wish it were values ;) Just get rid of the the one-argument foreach over AAs altogether and force the user to be explicit about it. I wouldn't do so. Would anybody do an error by thinking that foreach (elem,table) should iterate over keys? Maybe I'm not thinking correctly but for me an assoc array is just an array with additional key (index) features thanks to which I save space and/or have more indexing method than only integers. e.g. Normal array No. Item 0George 1Fred 2Dany 3Lil Index/key is infered from position (offset) Now Assoc array: No.Item 10Lindsey 21Romeo 1001C-Jay Or No.Item firstEurope secondSouth America thirdAustralia Or Names occurrence frequency: No. Item Andy21 John23 Kate12 And the only difference is the need for using a hash function for value lookup (calculate position) which should not bother a user when he doesn't care. Then when you ask somebody to iterate over the tables, what he will do almost for certain? If it would be me, you know... values all the time. Even for last example most important values are those numbers (despite in this case they're meaningless without keys). Cheers Piotrek Put it this way: Is there any time you are interested in the values without the keys? Is there any time you are interested in the keys without the values? If you're not interested in the keys, the real question would be why you are using an associative array instead of just an array. I can think of at least one example of when you want key iteration, which would be when using a bool[T] as a set.
Re: Proposed D2 Feature: = for anonymous delegates
language_fan wrote: Wed, 21 Oct 2009 12:35:41 +0200, Pelle Månsson thusly wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? No, in this context the exact type can be inferred unambiguously without worrying about overloading. The program should be roughly equivalent with: int f(int delegate(int) g) { return g(13); } auto __fun(T)(T x) { return x+13; } void main() { f(__fun); } which fails with Internal error: e2ir.c 644 :o) In brief, an untyped function literal should be considered an unbound template, and as long as type deduction can figure out the types (no Hindley-Milner, sorry) things should hold water. Andrei
Re: Proposed D2 Feature: = for anonymous delegates
Andrei Alexandrescu wrote: Pelle Månsson wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? Dropping the auto should yield a compilable program. Please report that to bugzilla (http://d.puremagic.com/issues/enter_bug.cgi) or let me know and I'll do so. Thanks! Andrei I'm afraid I do not understand, simply omitting the auto does not compile either. Which one is the bug? I'm putting this on the bugzilla now.
Re: Proposed D2 Feature: = for anonymous delegates
Pelle Månsson wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? Dropping the auto should yield a compilable program. Please report that to bugzilla (http://d.puremagic.com/issues/enter_bug.cgi) or let me know and I'll do so. Thanks! Andrei I'm afraid I do not understand, simply omitting the auto does not compile either. Which one is the bug? I'm putting this on the bugzilla now. The version with auto shouldn't compile, the one without should. Thanks! Andrei
Re: Proposed D2 Feature: = for anonymous delegates
Andrei Alexandrescu wrote: language_fan wrote: Wed, 21 Oct 2009 12:35:41 +0200, Pelle Månsson thusly wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? No, in this context the exact type can be inferred unambiguously without worrying about overloading. The program should be roughly equivalent with: int f(int delegate(int) g) { return g(13); } auto __fun(T)(T x) { return x+13; } void main() { f(__fun); } which fails with Internal error: e2ir.c 644 :o) Can't reproduce that. It doesn't ICE for me. Tried on several DMD versions. (Doesn't compile, though). In brief, an untyped function literal should be considered an unbound template, and as long as type deduction can figure out the types (no Hindley-Milner, sorry) things should hold water. Andrei
Re: Proposed D2 Feature: = for anonymous delegates
Don wrote: Andrei Alexandrescu wrote: language_fan wrote: Wed, 21 Oct 2009 12:35:41 +0200, Pelle Månsson thusly wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? No, in this context the exact type can be inferred unambiguously without worrying about overloading. The program should be roughly equivalent with: int f(int delegate(int) g) { return g(13); } auto __fun(T)(T x) { return x+13; } void main() { f(__fun); } which fails with Internal error: e2ir.c 644 :o) Can't reproduce that. It doesn't ICE for me. Tried on several DMD versions. (Doesn't compile, though). Sorry, it's the emacs paste buffer being different from Thunderbird's that's the problem. Please try this. int f(int delegate(int) g) { return g(13); } void main() { auto __fun(T)(T x) { return x+13; } f(cast(int delegate(int)) __fun); } On my machine: __fun(T) Internal error: e2ir.c 644 FWIW this should work too: int f(int delegate(int) g) { return g(13); } void main() { auto __fun(T)(T x) { return x+13; } int delegate(int) __tmp = __fun; f(__tmp); } That doesn't compile with: ./test.d(31): Error: __fun(T) is not an lvalue ./test.d(31): Error: cannot implicitly convert expression ((__fun(T))) of type void* to int delegate(int) Andrei
Re: Proposed D2 Feature: = for anonymous delegates
Andrei Alexandrescu wrote: Don wrote: Andrei Alexandrescu wrote: language_fan wrote: Wed, 21 Oct 2009 12:35:41 +0200, Pelle Månsson thusly wrote: Andrei Alexandrescu wrote: Pelle Månsson wrote: Jason House wrote: Andrei Alexandrescu Wrote: Jason House wrote: Am I the only one that has trouble remembering how to write an inline anonymous delegate when calling a function? At a minimum, both Scala and C# use (args) = { body; } syntax. Can we please sneak it into D2? We have (args) { body; } Andrei Somehow, I missed that. What kind of type inference, if any, is allowed? Scala and C# allow omiting the type. Lately I'm doing a lot of (x) = { return x.foo(7); } in C# and it's nice to omit the amazingly long type for x. The IDE even knows the type of x for intellisense... I think scala would allow x = foo(7), or maybe even = _.foo(7) or even _.foo(7). I haven't written much scala, so I may be way off... Recent experiments by myself indicate you cannot omit the type and you cannot use auto for the type, so you actually need to type your VeryLongClassName!(With, Templates) if you need it. I sort of miss automatic type deduction. Actually, full type deduction should be in vigor, but it is known that the feature has more than a few bugs. Feel free to report any instance in which type deduction does not work in bugzilla. Andrei int f(int delegate(int) g) { return g(13); } void main() { f((auto x) { return x+13; }); } This does not compile in D v2.034. Am I missing something? No, in this context the exact type can be inferred unambiguously without worrying about overloading. The program should be roughly equivalent with: int f(int delegate(int) g) { return g(13); } auto __fun(T)(T x) { return x+13; } void main() { f(__fun); } which fails with Internal error: e2ir.c 644 :o) Can't reproduce that. It doesn't ICE for me. Tried on several DMD versions. (Doesn't compile, though). Sorry, it's the emacs paste buffer being different from Thunderbird's that's the problem. Please try this. int f(int delegate(int) g) { return g(13); } void main() { auto __fun(T)(T x) { return x+13; } f(cast(int delegate(int)) __fun); } On my machine: __fun(T) Internal error: e2ir.c 644 Yup. I've created bug 3432 with a reduced test case.
Re: d3 ?
Stewart Gordon дµ½: Jason House wrote: dolive Wrote: will appear d3 ? What are the tasks ? it's not backward compatible with D2 ? What major changes ? My understanding is that there will be a significant gap between the finalization of D2 and the start of D3. Bartosz's ownership scheme may be part of D3. snip It would be really good if this is going to happen. It might even mean that D1 is going to be finished first. What sparked this subject, anyway? Stewart. Read the sparked of this paste: D and open development model,and Andrei Alexandrescu initiated the discussion of the many grammatical.. I'm Looking forward to d2 stability as soon as possible. thank you re me ! dolive
Re: Revamped concurrency API (Don can you contact Bartosz ?)
Don, el 21 de octubre a las 09:46 me escribiste: Nick B wrote: Don wrote: Don, are you able to contact Bartosz, re the details of this test case. Nick B Bartosz has sent it to me. I can reproduce the error. It's my top priority, but it'll take a while -- it's nasty. Don - thanks for filing this. I did try to contact you, via bugzilla email (which bounced back)and via Skype,(no reply), without success. Nick B All my public email addresses are fake. Bugzilla is just spam bait. It clearly comes from a more innocent age. I once made the mistake of submitting a bug to gcc. Although the GCC Bugzilla hides the email in the submitter field, the idiots include the real email address in the 100% useless 'X-Ref' line. Two weeks later, my email address was dead. I've never made that mistake again. I am contactable through my dsource account. You don't even use a real account for personal e-mails! That's odd. I couldn't reply your private e-mail about changing the title of the bugzilla report because the From address were fake. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Hoy estuvimos en el museo de antropología, pero yo voy a volver para estar por lo menos un día ahí adentro... es una locura, como Disney pero de indigenas -- Carla Lucarella (10/2008 contando de su viaje a México)
Re: static arrays becoming value types
Yigal Chripun, el 21 de octubre a las 07:18 me escribiste: On 21/10/2009 05:48, Robert Jacques wrote: On Tue, 20 Oct 2009 23:30:48 -0400, Leandro Lucarella llu...@gmail.com wrote: Robert Jacques, el 20 de octubre a las 21:06 me escribiste: Now, if SOL allowed tuples to do things you can't do today in D, like assign a tuple to a struct with the same signature, then this might be a point. But that wasn't the example given. Yes, that's another thing that can be done without real tuple support in the language. Anyway, I guess I was a little exaggerated with '*way far* from ideal', but I'm convinced there is plenty of room for improvements. =) Would you happen to know of a language which does tuples well already? pick any functional language.. my favorite is ML Or Python ;) -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- HACIA NEUQUEN: EL JUEVES SALDRA CARAVANA CON PERROS DESDE CAPITAL EN APOYO AL CACHORRO CONDENADO A MUERTE -- Crónica TV
d2 stability ?
Hope that will not be compatible with the syntax changes are put to realize d3, d2 as soon as possible to stabilize the full fix bugs and development of phobos library . thanks to all ! dolive
Re: static arrays becoming value types
On Wed, 21 Oct 2009 02:23:09 -0400, language_fan f...@bar.com.invalid wrote: Tue, 20 Oct 2009 16:25:05 -0400, Robert Jacques thusly wrote: On Tue, 20 Oct 2009 15:19:15 -0400, language_fan f...@bar.com.invalid wrote: Real tuple types do not have a special type tag which gets injected implicitly with structs. So every time you try to do something lightweight by emulating tuples, you need to refer to the global Tuple type or bang your head to the wall. Or use a templated opAssign mixin to allow two desperate types to be assigned to each other. Wow, you need templates to implement == for built-in values types, nice.. Unlike C++, D templates don't require a PhD to use. And it's definitely better that banging your head against the wall. Besides, I think you're comparing apples to oranges. In the SOL example, you use the same declaration for all types. Shouldn't the SOL example be: val a = (1,2) : [Int,Int] val b = (1,2) : [Int,Int] val c = (2,3) : MyCustomTupleType[Int,Int] which would probably generate: assert(a == b); // ok assert(a != c); // Error: incompatible types for ((a) != (b)) If you have built-in tuple literals, there is no way you can build a MyCustomTupleType without resorting to other language features. There are no apples and oranges, cause they both are seen as (Int,Int) by the equivalence checker. Do you understand how equivalence works in structural typing system (http://en.wikipedia.org/wiki/ Structural_type_system) vs nominal typing? In structural equivalence there are no names attached to the types (well there might be, but those are omitted in the comparison), only their internal structure matters. Why would anyone want to create two incompatible tuples by default as you still would have 'typedef' and 'struct' for implementing just that. My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.)
Re: static arrays becoming value types
Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: On Wed, 21 Oct 2009 02:23:09 -0400, language_fan f...@bar.com.invalid wrote: Tue, 20 Oct 2009 16:25:05 -0400, Robert Jacques thusly wrote: On Tue, 20 Oct 2009 15:19:15 -0400, language_fan f...@bar.com.invalid wrote: Real tuple types do not have a special type tag which gets injected implicitly with structs. So every time you try to do something lightweight by emulating tuples, you need to refer to the global Tuple type or bang your head to the wall. Or use a templated opAssign mixin to allow two desperate types to be assigned to each other. Wow, you need templates to implement == for built-in values types, nice.. Unlike C++, D templates don't require a PhD to use. And it's definitely better that banging your head against the wall. Besides, I think you're comparing apples to oranges. In the SOL example, you use the same declaration for all types. Shouldn't the SOL example be: val a = (1,2) : [Int,Int] val b = (1,2) : [Int,Int] val c = (2,3) : MyCustomTupleType[Int,Int] which would probably generate: assert(a == b); // ok assert(a != c); // Error: incompatible types for ((a) != (b)) If you have built-in tuple literals, there is no way you can build a MyCustomTupleType without resorting to other language features. There are no apples and oranges, cause they both are seen as (Int,Int) by the equivalence checker. Do you understand how equivalence works in structural typing system (http://en.wikipedia.org/wiki/ Structural_type_system) vs nominal typing? In structural equivalence there are no names attached to the types (well there might be, but those are omitted in the comparison), only their internal structure matters. Why would anyone want to create two incompatible tuples by default as you still would have 'typedef' and 'struct' for implementing just that. My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I see opImplicitCast, introspection done with templates and all kinds of other voodoo to be ugly hacks. This is nothing more than one of the basic value types without any special semantics, for $deity's sake. If you like the hacky approach so much, why don't all built-in types (like static arrays etc.) use the same method? Implementation wise tuples are much simpler than D's arrays or AAs, still they are treated like some 2nd class citizen from some notorious 3rd world country. Why is it so damn hard to change the 90% correctly implemented built-in tuples to work like in any other tuple supporting language. Do you somehow fancy verbose syntax for C++ compatibility reasons (ah, the good old std::tr1::make_tupleint, int, makes me want to wank every time..) Try Ruby, try python, try *ML etc. They all somehow got it right.
Re: static arrays becoming value types
language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? I see opImplicitCast, introspection done with templates and all kinds of other voodoo to be ugly hacks. This is nothing more than one of the basic value types without any special semantics, for $deity's sake. If you like the hacky approach so much, why don't all built-in types (like static arrays etc.) use the same method? Implementation wise tuples are much simpler than D's arrays or AAs, still they are treated like some 2nd class citizen from some notorious 3rd world country. How and why are they treated badly? Why is it so damn hard to change the 90% correctly implemented built-in tuples to work like in any other tuple supporting language. Do you somehow fancy verbose syntax for C++ compatibility reasons (ah, the good old std::tr1::make_tupleint, int, makes me want to wank every time..) Try Ruby, try python, try *ML etc. They all somehow got it right. What exactly didn't D's tuples get right? Andrei
Re: static arrays becoming value types
On Wed, Oct 21, 2009 at 8:48 AM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? I see opImplicitCast, introspection done with templates and all kinds of other voodoo to be ugly hacks. This is nothing more than one of the basic value types without any special semantics, for $deity's sake. If you like the hacky approach so much, why don't all built-in types (like static arrays etc.) use the same method? Implementation wise tuples are much simpler than D's arrays or AAs, still they are treated like some 2nd class citizen from some notorious 3rd world country. How and why are they treated badly? Why is it so damn hard to change the 90% correctly implemented built-in tuples to work like in any other tuple supporting language. Do you somehow fancy verbose syntax for C++ compatibility reasons (ah, the good old std::tr1::make_tupleint, int, makes me want to wank every time..) Try Ruby, try python, try *ML etc. They all somehow got it right. What exactly didn't D's tuples get right? Well, auto-flattening is a colossally bad idea to be sure. --bb
Re: static arrays becoming value types
Bill Baxter wrote: Well, auto-flattening is a colossally bad idea to be sure. Well that I agree with. I wonder if we need to fix it for D2. If we don't, we risk to live with it like with a chronic cough. Andrei
this() not executing code on structs
Today, structs can't write their own this(). There aren't very solid reasons for that except that it makes language implementation more difficult. I wonder how much of a problem that could be in practice. I realized today that the Counted example - a classic C++ primer example featuring a struct that counts its own instances - cannot be implemented in D. In C++ the counted example looks like this: struct Counted { static unsigned count; unsigned myCount; Counted() { myCount = count++; } Counted(const Counted rhs) { myCount = count++; } Counted operator=(const Counted rhs) { // no writing to myCount return *this; } ~Counted() { --count; } } In D there's no chance to write Counted because you can always create Counted objects without executing any code. struct Counted { static uint count; uint myCount; this() { myCount = count++; } // ERROR this(this) { myCount = count++; } ref Counted opAssign(Counted rhs) { // no writing to myCount return this; } ~this() { --count; } } This being a toy example, I wonder whether there are much more serious examples that would be impossible to implement within D. Andrei
d optimization: delegates vs. mixin
Can the compiler optimize the delegates (foo) to form an inline code, or the mixin version is prefered? module a; import std.stdio; void foo2( string s )() { for( int i = 0 ; i 10; i++ ) { mixin( s ); } } void foo( void delegate(int) pDg ) { for( int i = 0 ; i 10; i++ ) { pDg( i ); } } void main() { foo( (int a){ writeln( a ); } ); foo2!(writeln( i );)(); } Thank you 1
Re: static arrays becoming value types
Wed, 21 Oct 2009 10:48:34 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? Using tuples in D is a major pain in the ass. In fact it has been made so hard that people start avoiding the feature like plague. I wrote some test code to reveal how inconsistent their semantics are. Note that you need the built-in tuples for some stuff, like assigning and mixed value/ type tuples. Stuples can only be used as values and when the auto- flattening is not desired. STARTS HERE template Tuple(T...) { alias T Tuple; } struct STuple(T...) { T t; } void main() { Tuple!(int,int) a; // typeof(this) *is* the official tuple type STuple!(int,int) b; // this is actually a struct a = Tuple!(1,1); // ok // Tuple!(int,int) a2 = Tuple!(1,1); // WTF? Error: cannot implicitly convert expression (tuple(1,1)) of type (int, int) to int auto a3 = Tuple!(1,1); // ok b = STuple!(int,int)(1,1); // no easier way? make_tuple!(1,1) ? STuple!(int,int) b2 = STuple!(int,int)(1,1); // ok, but very verbose auto e1 = a[0]; // ok //auto e2 = b[0]; // nope auto e3 = b.t[0]; // this is how it works - you could possibly define opIndex but how would it work with different types then writefln(%s, a); // we get.. 1 !? but.. writefln(%s, typeof(a).stringof); // (int, int) writefln(%s, b); // STuple!(int,int)(1, 1) - rather verbose, but suffices //auto retTest() { return STuple!(int,int)(1,1); } // no identifier for declarator retTest STuple!(int,int) retTest2() { return STuple!(int,int)(1,1); }; // ok, but a bit too verbose int d,e; Tuple!(d,e) = Tuple!(10,20); // ok // but how to discard an unnecessary value? e.g. (a, _) = (1, 2) // Tuple!(d,e) = STuple!(10,20); // nope, not interchangeable // b = STuple!(a); // same here a = a; // ok b = b; // ok // a = b; // Error: a is not an lvalue -- interesting! Tuple!(d,b) = Tuple!(1, retTest2()); // awesome, with the Tuple I can even assign Tuples of STuples! //Tuple!(d,a) = Tuple!(1, a); // but Tuples don't help when assigning Tuples of Tuples //test.d(12): Error: expression _a_field_0 is not a valid template value argument //test.d(12): Error: expression _a_field_1 is not a valid template value argument //test.d(47): Error: template instance test.Tuple! (1,_a_field_0,_a_field_1) error instantiating // LET'S MAKE ARRAYS! int[] a1; // ok int[][] a2; // ok auto a1b = [1,2,3]; // ok auto a2b = [[1],[2],[3]]; // ok //Tuple!(int,int)[] a4; // Error: can't have array of (int, int) -- WHY NOT - it's simple, try e.g. ML STuple!(int,int)[] a5; // ok auto a3b = [Tuple!(1,1)]; // works, but hey did you know this is an array of ints! auto a4b = [STuple!(int,int)(1,1)]; // ok // int[Tuple!(int,int)] a6; // Error: can't have associative array key of (int, int) int[STuple!(int,int)] a7; // ok a7[STuple!(int,int)(1,1)] = 5; // ok Tuple!(int,Tuple!(int,int)) a8; // this isn't a (int, (int,int)) tuple - it's (int,int,int) ! STuple!(int,STuple!(int,int)) a9; // ok //auto a10 = [ Tuple!(1,1) : 2 ]; // Error: can't have associative array key of (int, int) -- Why did this work in array literal then?! auto a11 = [ STuple!(int,int)(1,1) : 2 ]; // ok alias Tuple!(int, 5) foo; // alias STuple!(int, 5) foo2; // parameters can only be types }
Re: static arrays becoming value types
Wed, 21 Oct 2009 16:54:22 +, language_fan thusly wrote: Wed, 21 Oct 2009 10:48:34 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? Using tuples in D is a major pain in the ass. In fact it has been made so hard that people start avoiding the feature like plague. I wrote some test code to reveal how inconsistent their semantics are. Note that you need the built-in tuples for some stuff, like assigning and mixed value/ type tuples. Stuples can only be used as values and when the auto- flattening is not desired. I forgot to say that you need two kinds of tuple literals in your standard library in D: one with value semantics, and one that is a wrapper around the alias tuple since auto-flattening happens.
Re: this() not executing code on structs
Andrei Alexandrescu Wrote: Today, structs can't write their own this(). There aren't very solid reasons for that except that it makes language implementation more difficult. If the new operator for the class is redesigned to have multiply allocation types (allocate on heap, allocate on stack, etc.?), there is no main drawback of using classes instead of structs for small objects( like vec2, vec3) as well. For function parameters, use the reference for in/out and, use a copy of the original for value parameters ( personally I hate codes where they change the input parameters when they are value types - for larger codes it's hard to track what's going on in the function, and whether it's the original or the modified value...) I don't think if there's any reason to use struct with member functions from that point, use class instead. And hence struct can be the good old plain data structures again, to give some semantics to a block of memory. But if the scoped allocation is gone, the struct will require much more construction powers, and will be used more (ex vec2, vec3, etc.)
Re: static arrays becoming value types
language_fan wrote: Wed, 21 Oct 2009 10:48:34 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? Using tuples in D is a major pain in the ass. In fact it has been made so hard that people start avoiding the feature like plague. How do you know what people do? I wrote some test code to reveal how inconsistent their semantics are. Note that you need the built-in tuples for some stuff, like assigning and mixed value/ type tuples. Stuples can only be used as values and when the auto- flattening is not desired. STARTS HERE template Tuple(T...) { alias T Tuple; } Why do you define Tuple instead of using the standard std.typecons.tuple? struct STuple(T...) { T t; } Why do you insist on defining another tuple type instead of using the one provided by the standard library? void main() { Tuple!(int,int) a; // typeof(this) *is* the official tuple type STuple!(int,int) b; // this is actually a struct a = Tuple!(1,1); // ok That doesn't work for me at all (with std.typecons.Tuple). I think there is confusion about a couple of things. One is that Tuple!(int, int) is a type that contains two ints, whereas Tuple!(1, 1) is a type that contains two compile-time integral values. So if you write: a = Tuple!(1, 1); that is as good syntactically as: a = int; which I hope you agree shouldn't quite go through. Write this: Tuple!(int,int) a; a = tuple(1, 1); or this: auto a = tuple(1, 1); // Tuple!(int,int) a2 = Tuple!(1,1); // WTF? Error: cannot implicitly convert expression (tuple(1,1)) of type (int, int) to int Yeah, WTF that doesn't work either: int a2 = int; auto a3 = Tuple!(1,1); // ok Not ok on my machine, nor it should be ok as this is also not ok: auto a3 = int; b = STuple!(int,int)(1,1); // no easier way? make_tuple!(1,1) ? Yeah try tuple(1, 1) in conjunction with std.typecons.Tuple. STuple!(int,int) b2 = STuple!(int,int)(1,1); // ok, but very verbose Well write this: auto stuple(T...)(T args) { return STuple!(T)(args); } auto e1 = a[0]; // ok This doesn't work because of a bug in the compiler, but this does with std.typecons.Tuple: auto e1 = a.field[0]; etc. etc. etc. I'm sure you make a couple of good points, but they are difficult to find. I suggest you peruse std.typecons.Tuple and submit any bugs you find to bugzilla. Andrei
Re: static arrays becoming value types
Wed, 21 Oct 2009 16:54:22 +, language_fan thusly wrote: Wed, 21 Oct 2009 10:48:34 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? Using tuples in D is a major pain in the ass. In fact it has been made so hard that people start avoiding the feature like plague. I wrote some test code to reveal how inconsistent their semantics are. Note that you need the built-in tuples for some stuff, like assigning and mixed value/ type tuples. Stuples can only be used as values and when the auto- flattening is not desired. STARTS HERE Even though not being an expert in Python (have not really used it), as an experiment I managed to successfully port the examples in 2 minutes without any kind of problems. a = (1,1) e1 = a[0] print a def retTest(): return (1,1) (d,e) = (10,20) (d,_) = (10,20) (d,b) = (1, retTest()) a3b = [ (1,1), (2,2) ] a7 = { (1,1) : 5 } a8 = { 5 : (1,1)}
Re: this() not executing code on structs
== Quote from zoli (z...@freemail.hu)'s article Andrei Alexandrescu Wrote: Today, structs can't write their own this(). There aren't very solid reasons for that except that it makes language implementation more difficult. If the new operator for the class is redesigned to have multiply allocation types (allocate on heap, allocate on stack, etc.?), there is no main drawback of using classes instead of structs for small objects( like vec2, vec3) as well. Yes there is. How about the cost of storing vtbl and monitor? Actually, just last night I was in a corner case where this mattered (as well as needing fine control over allocation), so I ended up rolling my own polymorphism with structs. This is not a complaint about the design of D classes. They do exactly what they should do: Handle the first 99% of use cases well and make people in obscure corner cases roll their own from lower level primitives rather than succumbing to the inner platform effect. However, I think it would be ridiculous not to allow simple syntactic sugar like non-polymorphic member functions on structs. I don't think if there's any reason to use struct with member functions from that point, use class instead. And hence struct can be the good old plain data structures again, to give some semantics to a block of memory. Ok, simple example that's not a corner case: How about storing one inline in an array?
Re: static arrays becoming value types
Wed, 21 Oct 2009 12:35:35 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: void main() { Tuple!(int,int) a; // typeof(this) *is* the official tuple type STuple!(int,int) b; // this is actually a struct a = Tuple!(1,1); // ok That doesn't work for me at all (with std.typecons.Tuple). I think there is confusion about a couple of things. One is that Tuple!(int, int) is a type that contains two ints, whereas Tuple!(1, 1) is a type that contains two compile-time integral values. So if you write: a = Tuple!(1, 1); that is as good syntactically as: a = int; It might be if we use your definition of tuple. But the mighty compiler dmd 2.035 himself calls my types constructed with my template template Tuple(T...) { alias T Tuple; } a tuple. How do you explain that? If the resulting type is tuple according to dmd, why do you think it is actually not. If it works like you say, why does this work then? Tuple!(int,int) a; a = Tuple!(12,13); Here 'a' has a real runtime type (int,int) which is a runtime tuple according to dmd. And I assign a value to the tuple on runtime. I can even test it by printing the values a[0] and a[1] with writefln. So why didn't you just fix this particular tuple type and why did you come up with a library level hack? Show me a better way to achieve this with your tuple system. int d,e; Tuple!(d,e) = Tuple!(10,20); It's still not clear to me why you don't want to add full syntactic support for built-in tuples. Do you somehow find this kind of code difficult to read or maintain? (int,int) a = (1,1); int e1 = a[0]; writefln(a); (int,int) retTest() { return (1,1); } int d,e; (d,e) = (10,20); (d,_) = (10,20); (int,int) b; (d,b) = (1, retTest()); auto a3b = [ (1,1), (2,2) ]; auto a7 = [ (1,1) : 5 ]; auto a8 = [ 5 : (1,1)]; I want to know what is the rationale behind not accepting this semantics that is so widely used in other languages (and I very well mean the languages that *have* built-in tuple types).
Re: static arrays becoming value types
language_fan, el 21 de octubre a las 17:52 me escribiste: Wed, 21 Oct 2009 16:54:22 +, language_fan thusly wrote: Wed, 21 Oct 2009 10:48:34 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: Wed, 21 Oct 2009 11:07:29 -0400, Robert Jacques thusly wrote: My issue was that all your example _showed_ was nominal typing. Though I didn't mention it by name, I did mention that if SOL tuples had structural typing, it might would be a different story. (Well, until/if opImplicitCast was implemented, as it would allow for structural typing.) Why do you insist on using nominal typing for tuples and the library defined literal. If I want plain old tuples without any kind of type name, why should I care about extra hand waving needed to make it work. I'm late in this dialog, but I'm not seeing an impediment here. What does it matter to you that tuples actually have a name vs. not having a name at all? Using tuples in D is a major pain in the ass. In fact it has been made so hard that people start avoiding the feature like plague. I wrote some test code to reveal how inconsistent their semantics are. Note that you need the built-in tuples for some stuff, like assigning and mixed value/ type tuples. Stuples can only be used as values and when the auto- flattening is not desired. STARTS HERE Even though not being an expert in Python (have not really used it), as an experiment I managed to successfully port the examples in 2 minutes without any kind of problems. I think this is an important point too. Maybe tuples are not *that* broken as stated in this thread, but they are quite more complex to understand than tuples in other languages, and they feel somehow hackish. a = (1,1) e1 = a[0] print a def retTest(): return (1,1) (d,e) = (10,20) (d,_) = (10,20) (d,b) = (1, retTest()) a3b = [ (1,1), (2,2) ] a7 = { (1,1) : 5 } a8 = { 5 : (1,1)} In python you can even do: def f(a, b, c): print a, b, c x = (b, c) f(a, *x) # calls to f(a, b, c) I think this is only possible in D with type tuples, not with ... value tuples? That's part of the complexity, having 2 type of tuples is very confusing. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- You are the very reason why everything happens to you
Re: Condition Mutexes
dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up.
Re: static arrays becoming value types
language_fan wrote: Wed, 21 Oct 2009 12:35:35 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: void main() { Tuple!(int,int) a; // typeof(this) *is* the official tuple type STuple!(int,int) b; // this is actually a struct a = Tuple!(1,1); // ok That doesn't work for me at all (with std.typecons.Tuple). I think there is confusion about a couple of things. One is that Tuple!(int, int) is a type that contains two ints, whereas Tuple!(1, 1) is a type that contains two compile-time integral values. So if you write: a = Tuple!(1, 1); that is as good syntactically as: a = int; It might be if we use your definition of tuple. But the mighty compiler dmd 2.035 himself calls my types constructed with my template template Tuple(T...) { alias T Tuple; } a tuple. How do you explain that? If the resulting type is tuple according to dmd, why do you think it is actually not. If it works like you say, why does this work then? Tuple!(int,int) a; a = Tuple!(12,13); Here 'a' has a real runtime type (int,int) which is a runtime tuple according to dmd. And I assign a value to the tuple on runtime. I can even test it by printing the values a[0] and a[1] with writefln. So why didn't you just fix this particular tuple type and why did you come up with a library level hack? Show me a better way to achieve this with your tuple system. I don't understand what you are trying to accomplish. As far as I can tell you want to do this: Tuple!(int, int) a; a = tuple(12, 13); int x = a.field[0]; and similar things. I have no idea why you refuse to do it that way. int d,e; Tuple!(d,e) = Tuple!(10,20); It's still not clear to me why you don't want to add full syntactic support for built-in tuples. Do you somehow find this kind of code difficult to read or maintain? (int,int) a = (1,1); int e1 = a[0]; writefln(a); (int,int) retTest() { return (1,1); } int d,e; (d,e) = (10,20); (d,_) = (10,20); (int,int) b; (d,b) = (1, retTest()); auto a3b = [ (1,1), (2,2) ]; auto a7 = [ (1,1) : 5 ]; auto a8 = [ 5 : (1,1)]; I want to know what is the rationale behind not accepting this semantics that is so widely used in other languages (and I very well mean the languages that *have* built-in tuple types). To effect this, there'd first be a need to eliminate the current semantics of the comma operator. I probably find it as useless as the next guy, and don't take one second to buy into Walter's theory that it makes it easy to generate code (that may as well be his least convincing argument to date), but really there's two parts to your suggestion: (1) eliminate the comma operator, (2) make the comma operator work for tuples. I suspect there are some syntactical issues with (2). Andrei
Re: this() not executing code on structs
If the new operator for the class is redesigned to have multiply allocation types (allocate on heap, allocate on stack, etc.?), there is no main drawback of using classes instead of structs for small objects( like vec2, vec3) as well. Yes there is. How about the cost of storing vtbl and monitor? Actually, just I keep forgetting those (4-8) extra bytes per instance :) And what about the final classes (with no ancestors)? Is there a vtbl for them since they cannot be derived and they have no virtual parent to inherit members from ? Or the Object with opHash and the other operators are virtual by nature in all classes ? (sorry, I don't know D that much) Well, actually it seems as struct is a much better and clear solution. In that case I vote for this().
Re: Condition Mutexes
== Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up. Thanks. I've implemented this, along w/ one other suggestion from another poster. Here's the new program. It still doesn't work. Has anyone successfully used core.sync.condition from druntime *on D2, not the Tango version on D1*? If it works, then it should be better documented so people who aren't already threading gurus can figure out how to use it. If it doesn't work, then as soon as I can confirm that I'm not the problem, I'll go file a bug report. Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? import core.sync.mutex, core.sync.condition, core.thread, std.stdio; __gshared Condition condition; __gshared Mutex mutex; void waitThenPrint() { mutex.lock; condition.wait(); mutex.unlock; writeln(FOO); } void main() { mutex = new Mutex; condition = new Condition(mutex); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. T.join; }
Re: this() not executing code on structs
== Quote from zoli (ga...@freemail.hu)'s article If the new operator for the class is redesigned to have multiply allocation types (allocate on heap, allocate on stack, etc.?), there is no main drawback of using classes instead of structs for small objects( like vec2, vec3) as well. Yes there is. How about the cost of storing vtbl and monitor? Actually, just I keep forgetting those (4-8) extra bytes per instance :) And what about the final classes (with no ancestors)? Even final classes w/ no explicit ancestors are implicitly subclasses of Object, which defines virtual functions. Therefore, *all* class instances must have a vtbl pointer.
Re: d optimization: delegates vs. mixin
zoli: Can the compiler optimize the delegates (foo) to form an inline code, or the mixin version is prefered? Today D compilers are in general not smart enough yet (like the Scala compiler, for example) to inline delegates. But there's an alternative to string mixins, in D2 you can pass a templated function, even one where you omit the type of the arguments :-) There's no shortage of tricks in D2. Bye, bearophile
Re: static arrays becoming value types
Leandro Lucarella: In python you can even do: def f(a, b, c): print a, b, c x = (b, c) f(a, *x) # calls to f(a, b, c) In Python2.x you can also do: def foo(x, (y, (z1, z2))): print z2 print z1 print y print x Z = (1, 2) yz = [0, Z] foo(-1, yz) That outputs: 2 1 0 -1 Bye, bearophile
Re: static arrays becoming value types
Wed, 21 Oct 2009 13:41:50 -0500, Andrei Alexandrescu thusly wrote: I don't understand what you are trying to accomplish. As far as I can tell you want to do this: Tuple!(int, int) a; a = tuple(12, 13); int x = a.field[0]; Not only that, but also this: int d,e; Tuple!(d,e) = Tuple!(10,20); and similar things. I have no idea why you refuse to do it that way. You somehow refuse to see that D has a tuple type which the compiler calls a tuple. Run 'strings /path/to/dmd|wc -l' and you'll see 28 instances of the word 'tuple'. If there was no built-in support, why does the executable contain the word then? Here.. template Z(T...) { alias T Z; } Z!(int,int) a; pragma(msg,a.stringof); I did not mention the word tuple, but guess what dmd thinks. If it is not a tuple, why does dmd output 'tuple(_a_field_0,_a_field_1)'? Apparently this does not follow the math book definition of tuple nor is the traditional FPL tuple, but a special D flavor of tuple. Walter decided to build a tuple type, but something happened and he later started restricting its use (IIRC it *was* possible to create an array of these tuples, but now it is disallowed). What is left is a half-working mess mostly useful for compile time meta-programming. It works rather nicely there (except that the auto-flattening is sometimes rather annoying), but its operation is broken on runtime. You discarded this by stating that D does not have a tuple type, you just call it a 'type that contains two ints' in my example. DMD calls it a tuple (see .stringof, error messages etc.) I can see that you try to accomplish the same things with your library provided version of tuple. But if that is the recommended way of using tuples, why there is a bug riddled version in the compiler of the same type. It is extremely exhausting to implement a new compiler for D because the reference implementation is full of bugs I mentioned in previous posts and you cannot really tell how it should work. To effect this, there'd first be a need to eliminate the current semantics of the comma operator. I probably find it as useless as the next guy, and don't take one second to buy into Walter's theory that it makes it easy to generate code (that may as well be his least convincing argument to date), but really there's two parts to your suggestion: (1) eliminate the comma operator, (2) make the comma operator work for tuples. I suspect there are some syntactical issues with (2). I know that very well..
Re: Condition Mutexes
dsimcha Wrote: == Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up. Thanks. I've implemented this, along w/ one other suggestion from another poster. Here's the new program. It still doesn't work. Has anyone successfully used core.sync.condition from druntime *on D2, not the Tango version on D1*? If it works, then it should be better documented so people who aren't already threading gurus can figure out how to use it. If it doesn't work, then as soon as I can confirm that I'm not the problem, I'll go file a bug report. Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? import core.sync.mutex, core.sync.condition, core.thread, std.stdio; __gshared Condition condition; __gshared Mutex mutex; void waitThenPrint() { mutex.lock; condition.wait(); mutex.unlock; writeln(FOO); } void main() { mutex = new Mutex; condition = new Condition(mutex); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. T.join; } You should lock condition before calling notify. Even if you did that, you have a race for which thread gets the lock first. If the main thread gets it, the spawned thread will never receive the notify and hang forever.
Re: static arrays becoming value types
On Wed, 21 Oct 2009 22:41:50 +0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: language_fan wrote: Wed, 21 Oct 2009 12:35:35 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: void main() { Tuple!(int,int) a; // typeof(this) *is* the official tuple type STuple!(int,int) b; // this is actually a struct a = Tuple!(1,1); // ok That doesn't work for me at all (with std.typecons.Tuple). I think there is confusion about a couple of things. One is that Tuple!(int, int) is a type that contains two ints, whereas Tuple!(1, 1) is a type that contains two compile-time integral values. So if you write: a = Tuple!(1, 1); that is as good syntactically as: a = int; It might be if we use your definition of tuple. But the mighty compiler dmd 2.035 himself calls my types constructed with my template template Tuple(T...) { alias T Tuple; } a tuple. How do you explain that? If the resulting type is tuple according to dmd, why do you think it is actually not. If it works like you say, why does this work then? Tuple!(int,int) a; a = Tuple!(12,13); Here 'a' has a real runtime type (int,int) which is a runtime tuple according to dmd. And I assign a value to the tuple on runtime. I can even test it by printing the values a[0] and a[1] with writefln. So why didn't you just fix this particular tuple type and why did you come up with a library level hack? Show me a better way to achieve this with your tuple system. I don't understand what you are trying to accomplish. As far as I can tell you want to do this: Tuple!(int, int) a; a = tuple(12, 13); int x = a.field[0]; and similar things. I have no idea why you refuse to do it that way. int d,e; Tuple!(d,e) = Tuple!(10,20); It's still not clear to me why you don't want to add full syntactic support for built-in tuples. Do you somehow find this kind of code difficult to read or maintain? (int,int) a = (1,1); int e1 = a[0]; writefln(a); (int,int) retTest() { return (1,1); } int d,e; (d,e) = (10,20); (d,_) = (10,20); (int,int) b; (d,b) = (1, retTest()); auto a3b = [ (1,1), (2,2) ]; auto a7 = [ (1,1) : 5 ]; auto a8 = [ 5 : (1,1)]; I want to know what is the rationale behind not accepting this semantics that is so widely used in other languages (and I very well mean the languages that *have* built-in tuple types). To effect this, there'd first be a need to eliminate the current semantics of the comma operator. I probably find it as useless as the next guy, and don't take one second to buy into Walter's theory that it makes it easy to generate code (that may as well be his least convincing argument to date), but really there's two parts to your suggestion: (1) eliminate the comma operator, (2) make the comma operator work for tuples. I suspect there are some syntactical issues with (2). Andrei Well, he could just change the symbol used to denote comma operator to some other character (if he uses it so heavily internally), and don't expose it to a user. I don't use tuples a lot myself, but I would love to have multiple return types without some clumsy syntax. It's possible even now, but the syntax is a bit discouraging: Tuple!(int,float) foo() { return tuple(42, -1.0f); } make_tuple(a, b) = foo(); as opposed to: (int, float) foo() { return (42, -1.0f); } (a, b) = foo();
Re: d optimization: delegates vs. mixin
bearophile Wrote: zoli: Can the compiler optimize the delegates (foo) to form an inline code, or the mixin version is prefered? Today D compilers are in general not smart enough yet (like the Scala compiler, for example) to inline delegates. But there's an alternative to string mixins, in D2 you can pass a templated function, even one where you omit the type of the arguments :-) There's no shortage of tricks in D2. Thank you. Could you provide a sample or a link ? Sorry, i know it's a d.learn topic..., Offtopic: Is it possible to alter the web interface of the news to change newsgroups during composition ?
Re: Condition Mutexes
== Quote from Jason House (jason.james.ho...@gmail.com)'s article dsimcha Wrote: == Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up. Thanks. I've implemented this, along w/ one other suggestion from another poster. Here's the new program. It still doesn't work. Has anyone successfully used core.sync.condition from druntime *on D2, not the Tango version on D1*? If it works, then it should be better documented so people who aren't already threading gurus can figure out how to use it. If it doesn't work, then as soon as I can confirm that I'm not the problem, I'll go file a bug report. Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? import core.sync.mutex, core.sync.condition, core.thread, std.stdio; __gshared Condition condition; __gshared Mutex mutex; void waitThenPrint() { mutex.lock; condition.wait(); mutex.unlock; writeln(FOO); } void main() { mutex = new Mutex; condition = new Condition(mutex); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. T.join; } You should lock condition before calling notify. Even if you did that, you have a race for which thread gets the lock first. If the main thread gets it, the spawned thread will never receive the notify and hang forever. Thanks, but at a more general level, where can I find documentation on how to use conditions properly? I realize that I have absolutely no fundamental understanding of how they work or what assumptions they make, but it seems like there is very little written material on this, either for the general case or for the specific case of core.sync. For example, for some reason I assumed that a condition's methods would be already synchronized internally.
Re: this() not executing code on structs
On Wed, 21 Oct 2009 20:15:16 +0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Today, structs can't write their own this(). There aren't very solid reasons for that except that it makes language implementation more difficult. I wonder how much of a problem that could be in practice. I realized today that the Counted example - a classic C++ primer example featuring a struct that counts its own instances - cannot be implemented in D. In C++ the counted example looks like this: struct Counted { static unsigned count; unsigned myCount; Counted() { myCount = count++; } Counted(const Counted rhs) { myCount = count++; } Counted operator=(const Counted rhs) { // no writing to myCount return *this; } ~Counted() { --count; } } In D there's no chance to write Counted because you can always create Counted objects without executing any code. struct Counted { static uint count; uint myCount; this() { myCount = count++; } // ERROR this(this) { myCount = count++; } ref Counted opAssign(Counted rhs) { // no writing to myCount return this; } ~this() { --count; } } This being a toy example, I wonder whether there are much more serious examples that would be impossible to implement within D. Andrei I agree it's a very annoying limitation, but I believe there is a rationale behind it. Imagine a class that aggregates a struct: struct Foo { ... } class Bar { Foo foo; this() {} // ... } The class object construction is now consists of two steps: 1) memcpy the Bar.classinfo.init 2) call __ctor() Unlike C++, there is no stage at which class members are being initialized, and it simplifies things quite a lot. Think about the following: what happens if structs will be allowed default ctors? How to avoid double initialization? You may end up with design very similar to C++ in this case (including an initialization list). Some problems could be solved with an enforced explicit initialization of each member. That's the only way I see now that would avoid double initialization of a struct in presence of default and non-default ctors: struct Scoped(T) // I like this name a lot more than InPlace, and especially InSitu { this(Args...)(Args args) { T obj = cast(T)data.ptr; obj.__ctor(args); } ubyte[T.classinfo.init.length] data = T.classinfo.init; // I believe this should work at compile-time, since classinfo is immutable } class Foo { this() {} this(int i) {} } class Bar { Scoped!(Foo) foo; this() { // foo is already constructed by now (default ctor is called) which is cool // but what if I need to initialize it with some other ctor? foo = Scoped!(Foo)(42); // double initialization } int doesntNeedToBeInitializedExplicitlyInACtor = 17; } Enforcing explicit initialization of each member (unless its value is set at the declaration, as in the example above) is gracefully solving this issue. Also think about exception safety: what if an exception is thrown in a class ctor - should the dtors be invoked on initialized members or not? If yes, in what order? D doesn't enforce initialization order, so it's a bit tricky to determine what members are already initialized and need to be destroyed (with a dtor call) efficiently. C++ handles issues like this very well IMO. I believe D should also have a sound solution to this problem.
Re: Condition Mutexes
dsimcha wrote: == Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up. Thanks. I've implemented this, along w/ one other suggestion from another poster. Here's the new program. It still doesn't work. Has anyone successfully used core.sync.condition from druntime *on D2, not the Tango version on D1*? If it works, then it should be better documented so people who aren't already threading gurus can figure out how to use it. If it doesn't work, then as soon as I can confirm that I'm not the problem, I'll go file a bug report. Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? import core.sync.mutex, core.sync.condition, core.thread, std.stdio; __gshared Condition condition; __gshared Mutex mutex; void waitThenPrint() { mutex.lock; condition.wait(); mutex.unlock; writeln(FOO); } void main() { mutex = new Mutex; condition = new Condition(mutex); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. T.join; } Well, you should lock the mutex before calling condition.notify and release it afterwards. Note that there is always a chance that notify will be called before the thread starts waiting. In that case your program will deadlock (randomly). Jerome -- mailto:jeber...@free.fr http://jeberger.free.fr Jabber: jeber...@jabber.fr signature.asc Description: OpenPGP digital signature
Re: Revamping associative arrays
Bill Baxter pisze: So C# avoids the ambiguity. Unless there's some other AA type in C#. --bb True. Java does it too. My fault. Cheers Piotrek
Re: Revamping associative arrays
Pelle Månsson pisze: Piotrek wrote: Bill Baxter pisze: On Sun, Oct 18, 2009 at 1:12 PM, Piotrek star...@tlen.pl wrote: Bill Baxter pisze: I think the default should be to iterate over whatever 'in' looks at. I was almost convinced, because that rule has a sense. But treating normal arrays and associative array has more sense to me. fun (SomeObject object) { foreach (element;object.arr1){ //normal, but how do I know at first look //just do something with element } foreach (element;object.arr2){ // assoc, but how do I know at first look //just do something with element hopefully not index } That sounds like an argument that there should be no default, because either way it's not clear whether you're iterating over keys or values. Really?! That wasn't my intention :) In both cases I wish it were values ;) Just get rid of the the one-argument foreach over AAs altogether and force the user to be explicit about it. I wouldn't do so. Would anybody do an error by thinking that foreach (elem,table) should iterate over keys? Maybe I'm not thinking correctly but for me an assoc array is just an array with additional key (index) features thanks to which I save space and/or have more indexing method than only integers. e.g. Normal array No. Item 0George 1Fred 2Dany 3Lil Index/key is infered from position (offset) Now Assoc array: No.Item 10Lindsey 21Romeo 1001C-Jay Or No.Item firstEurope secondSouth America thirdAustralia Or Names occurrence frequency: No. Item Andy21 John23 Kate12 And the only difference is the need for using a hash function for value lookup (calculate position) which should not bother a user when he doesn't care. Then when you ask somebody to iterate over the tables, what he will do almost for certain? If it would be me, you know... values all the time. Even for last example most important values are those numbers (despite in this case they're meaningless without keys). Cheers Piotrek Put it this way: Is there any time you are interested in the values without the keys? Yes! Is there any time you are interested in the keys without the values? Yes! If you're not interested in the keys, the real question would be why you are using an associative array instead of just an array. The answer is simple. I can reuse AA in many different functions. Sometimes I need keys other time values and even... both :) That isn't the issue. The problem was about what should return short version of foreach over AA. I can think of at least one example of when you want key iteration, which would be when using a bool[T] as a set. See above. Cheers Piotrek
Re: static arrays becoming value types
Denis Koroskin wrote: On Wed, 21 Oct 2009 22:41:50 +0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: language_fan wrote: Wed, 21 Oct 2009 12:35:35 -0500, Andrei Alexandrescu thusly wrote: language_fan wrote: void main() { Tuple!(int,int) a; // typeof(this) *is* the official tuple type STuple!(int,int) b; // this is actually a struct a = Tuple!(1,1); // ok That doesn't work for me at all (with std.typecons.Tuple). I think there is confusion about a couple of things. One is that Tuple!(int, int) is a type that contains two ints, whereas Tuple!(1, 1) is a type that contains two compile-time integral values. So if you write: a = Tuple!(1, 1); that is as good syntactically as: a = int; It might be if we use your definition of tuple. But the mighty compiler dmd 2.035 himself calls my types constructed with my template template Tuple(T...) { alias T Tuple; } a tuple. How do you explain that? If the resulting type is tuple according to dmd, why do you think it is actually not. If it works like you say, why does this work then? Tuple!(int,int) a; a = Tuple!(12,13); Here 'a' has a real runtime type (int,int) which is a runtime tuple according to dmd. And I assign a value to the tuple on runtime. I can even test it by printing the values a[0] and a[1] with writefln. So why didn't you just fix this particular tuple type and why did you come up with a library level hack? Show me a better way to achieve this with your tuple system. I don't understand what you are trying to accomplish. As far as I can tell you want to do this: Tuple!(int, int) a; a = tuple(12, 13); int x = a.field[0]; and similar things. I have no idea why you refuse to do it that way. int d,e; Tuple!(d,e) = Tuple!(10,20); It's still not clear to me why you don't want to add full syntactic support for built-in tuples. Do you somehow find this kind of code difficult to read or maintain? (int,int) a = (1,1); int e1 = a[0]; writefln(a); (int,int) retTest() { return (1,1); } int d,e; (d,e) = (10,20); (d,_) = (10,20); (int,int) b; (d,b) = (1, retTest()); auto a3b = [ (1,1), (2,2) ]; auto a7 = [ (1,1) : 5 ]; auto a8 = [ 5 : (1,1)]; I want to know what is the rationale behind not accepting this semantics that is so widely used in other languages (and I very well mean the languages that *have* built-in tuple types). To effect this, there'd first be a need to eliminate the current semantics of the comma operator. I probably find it as useless as the next guy, and don't take one second to buy into Walter's theory that it makes it easy to generate code (that may as well be his least convincing argument to date), but really there's two parts to your suggestion: (1) eliminate the comma operator, (2) make the comma operator work for tuples. I suspect there are some syntactical issues with (2). Andrei Well, he could just change the symbol used to denote comma operator to some other character (if he uses it so heavily internally), and don't expose it to a user. I don't use tuples a lot myself, but I would love to have multiple return types without some clumsy syntax. It's possible even now, but the syntax is a bit discouraging: Tuple!(int,float) foo() { return tuple(42, -1.0f); } make_tuple(a, b) = foo(); as opposed to: (int, float) foo() { return (42, -1.0f); } (a, b) = foo(); Or even: a, b = foo(); or a, _ = foo(); Works in Python (tm)
Re: d optimization: delegates vs. mixin
zoli: Thank you. Could you provide a sample or a link ? Silly D2 code: import std.stdio: writeln; void table(alias Mapper, T)(T[] arr) { foreach (el; arr) writeln(Mapper(el)); } void main() { table!((x){ return x * x;})([2, 3, 4]); } I don't like that code a lot, I'd like the D compiler to be smarter, so the programmer can avoid such silly tricks, and the programmer can program in a more functional style (where you use *functions*). Sorry, i know it's a d.learn topic..., Yep. Better to ask such things there. Offtopic: Is it possible to alter the web interface of the news to change newsgroups during composition ? I don't know. Probably not. Bye, bearophile
Re: this() not executing code on structs
Andrei Alexandrescu Wrote: this() { myCount = count++; } // ERROR It's worse than that. Try this: struct foo { this(int dummy = 0) { writeln(Default constructor);} } foo x = foo(); Nothing gets printed. If default constructors are disallowed, so should constructors with all parameters defaulted.
Re: this() not executing code on structs
This means that no non-trivial invariant may be defined for a struct. In most cases it doesn't matter, but it might be a problem with the smart pointer family. For instance, refcounted may not assume that the shared refcount pointer has been allocated. Without this invariant all refcounted operations must have additional code that tests for null and does the right thing (which is not always obvious).
Re: static arrays becoming value types
grauzone, el 21 de octubre a las 22:12 me escribiste: Or even: a, b = foo(); or a, _ = foo(); Works in Python (tm) _ is a regular symbol (variable name in this case), there is nothing special about the second form, which is exactly the same as the first. And BTW, the trailing ; is not needed ;) -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Hey you, standing in the aisles With itchy feet and fading smiles Can you feel me?
Re: this() not executing code on structs
Bartosz Milewski, el 21 de octubre a las 16:33 me escribiste: Andrei Alexandrescu Wrote: this() { myCount = count++; } // ERROR It's worse than that. Try this: struct foo { this(int dummy = 0) { writeln(Default constructor);} } foo x = foo(); Nothing gets printed. If default constructors are disallowed, so should constructors with all parameters defaulted. Fill bug reports in bugzilla, please! -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Los jóvenes no son solo brazos que nos cargan... También se los puede mandar a la guerra, que es su obligación. -- Ricardo Vaporeso
Re: static arrays becoming value types
language_fan wrote: You somehow refuse to see that D has a tuple type which the compiler calls a tuple. D has tuples, it doesn't have tuple literals. Tuple attempts to supplant that. Andrei
Re: Condition Mutexes
On Wed, 21 Oct 2009 14:50:32 -0400, dsimcha dsim...@yahoo.com wrote: == Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up. Thanks. I've implemented this, along w/ one other suggestion from another poster. Here's the new program. It still doesn't work. Here is a major flaw in your logic: A condition is a *signal* not a *flag*. In order to catch the signal you have to be listening for it. It's not like a semaphore. What you need in order to use a condition is a flag that is protected by the lock. Generally, the model is: thread1() { lock(mutex) { set(flag); condition.notify(); } } thread2() { lock(mutex) { while(!flag) condition.wait(); unset(flag); // we received the signal, clear it. } } The condition is basically a way to give control of waking up a thread to another thread. But the condition is not the, um... condition you are waiting for :) You still need a state variable to say hey, you should continue now, the state is correctly set. Think of the flag like a mailbox flag. You only put it up *after* you put mail in the mailbox, and the mailman lowers the flag when he gets the mail out. There are lots of threading tutorials you can probably read to get it. But basically, I can break down what exactly happens, I'll do 2 scenarios: Scenario 1: 1. thread2 locks the mutex, which protects the flag. It sees that the flag is unset, so it waits on the condition. This *atomically* unlocks the mutex and enters the thread into the list of threads to wake up when the condition is signaled. 2. thread1 now can lock the mutex, and sets the flag. It notifies the condition, which wakes up thread2. 3. thread2 *remains asleep* until it can reacquire the lock. thread1 unlocks the mutex after leaving the scope. 4. thread2 wakes up after reacquiring the mutex, and repeats the while-loop, seeing that the flag is now set. 5. thread2 unsets the flag and unlocks the mutex, continuing. Scenario 2: 1. thread1 locks the mutex. 2. thread2 sleeps because it cannot lock the mutex. 3. thread1 sets the flag, then signals the condition. Since nobody is listening *this doesn't affect anything*. 4. thread1 exits the scope, releasing the mutex. 5. thread2 now acquires the lock, sees the flag is set, and doesn't even wait on the condition, unsets the flag, exits the scope, and unlocks the mutex. You can see how the locking is important to protect the atomicity of setting the flag, and it is *really* important that the condition wait atomically unlocks the mutex and enters the thread into the condition's wakeup queue. So generally speaking: rule 1, don't do anything with a condition unless the mutex it uses is locked. rule 2, always have a state that is protected by the same lock that the condition is waiting with. You also may wonder why there is even a while loop, I mean, why recheck the flag after the condition is signalled? Well, in this case, it's not required, but it's very good practice. When you have a case where the flag is not a flag, but a multi-state variable, and you are waiting for a specific state, one thread might signal every time the state changes. Well, you don't want to continue until you get the state that you want, so you need to re-check the state. Another case is if you have several instances of thread2, and you only want to release one of them with the signal. Hope this helps. -Steve
Re: Condition Mutexes
== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article On Wed, 21 Oct 2009 14:50:32 -0400, dsimcha dsim...@yahoo.com wrote: == Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: void main() { condition = new Condition( new Mutex() ); auto T = new Thread(waitThenPrint); T.start(); condition.notify(); // Never wakes up and prints FOO. } Your program terminates immediately after sending the notification. You need to stall the exit until the other thread has a chance to wake up. Thanks. I've implemented this, along w/ one other suggestion from another poster. Here's the new program. It still doesn't work. Here is a major flaw in your logic: A condition is a *signal* not a *flag*. In order to catch the signal you have to be listening for it. It's not like a semaphore. What you need in order to use a condition is a flag that is protected by the lock. Generally, the model is: thread1() { lock(mutex) { set(flag); condition.notify(); } } thread2() { lock(mutex) { while(!flag) condition.wait(); unset(flag); // we received the signal, clear it. } } The condition is basically a way to give control of waking up a thread to another thread. But the condition is not the, um... condition you are waiting for :) You still need a state variable to say hey, you should continue now, the state is correctly set. Think of the flag like a mailbox flag. You only put it up *after* you put mail in the mailbox, and the mailman lowers the flag when he gets the mail out. There are lots of threading tutorials you can probably read to get it. But basically, I can break down what exactly happens, I'll do 2 scenarios: Scenario 1: 1. thread2 locks the mutex, which protects the flag. It sees that the flag is unset, so it waits on the condition. This *atomically* unlocks the mutex and enters the thread into the list of threads to wake up when the condition is signaled. 2. thread1 now can lock the mutex, and sets the flag. It notifies the condition, which wakes up thread2. 3. thread2 *remains asleep* until it can reacquire the lock. thread1 unlocks the mutex after leaving the scope. 4. thread2 wakes up after reacquiring the mutex, and repeats the while-loop, seeing that the flag is now set. 5. thread2 unsets the flag and unlocks the mutex, continuing. Scenario 2: 1. thread1 locks the mutex. 2. thread2 sleeps because it cannot lock the mutex. 3. thread1 sets the flag, then signals the condition. Since nobody is listening *this doesn't affect anything*. 4. thread1 exits the scope, releasing the mutex. 5. thread2 now acquires the lock, sees the flag is set, and doesn't even wait on the condition, unsets the flag, exits the scope, and unlocks the mutex. You can see how the locking is important to protect the atomicity of setting the flag, and it is *really* important that the condition wait atomically unlocks the mutex and enters the thread into the condition's wakeup queue. So generally speaking: rule 1, don't do anything with a condition unless the mutex it uses is locked. rule 2, always have a state that is protected by the same lock that the condition is waiting with. You also may wonder why there is even a while loop, I mean, why recheck the flag after the condition is signalled? Well, in this case, it's not required, but it's very good practice. When you have a case where the flag is not a flag, but a multi-state variable, and you are waiting for a specific state, one thread might signal every time the state changes. Well, you don't want to continue until you get the state that you want, so you need to re-check the state. Another case is if you have several instances of thread2, and you only want to release one of them with the signal. Hope this helps. -Steve Thank you. This was *extremely* helpful. I'll read over it in more detail when I get back to hacking my futures/parallel foreach lib.
Re: this() not executing code on structs
Andrei Alexandrescu wrote: Today, structs can't write their own this(). There aren't very solid reasons for that except that it makes language implementation more difficult. I wonder how much of a problem that could be in practice. I realized today that the Counted example - a classic C++ primer example featuring a struct that counts its own instances - cannot be implemented in D. In C++ the counted example looks like this: struct Counted { static unsigned count; unsigned myCount; Counted() { myCount = count++; } Counted(const Counted rhs) { myCount = count++; } Counted operator=(const Counted rhs) { // no writing to myCount return *this; } ~Counted() { --count; } } In D there's no chance to write Counted because you can always create Counted objects without executing any code. struct Counted { static uint count; uint myCount; this() { myCount = count++; } // ERROR this(this) { myCount = count++; } ref Counted opAssign(Counted rhs) { // no writing to myCount return this; } ~this() { --count; } } This being a toy example, I wonder whether there are much more serious examples that would be impossible to implement within D. Any struct that uses dynamic memory allocation internally. Any struct that registers its instances in some dort of global registry. 'ValueType!T', which turns reference type 'T' into a value type. A 'ScopedLock' variant that uses a single global mutex. RAII wrappers over global initialization/deinitialization functions. A 'UniqueId' struct that initializes to a value that is guaranteed to be distinct from the vale of any other 'UniqueId' used by the program. -- Rainer Deyke - rain...@eldwood.com
Re: Condition Mutexes
dsimcha Wrote: Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? Conditions were implemented by Sean Kelly, so he's the guru. The file condition.d in core.sync has unit tests, which presumably still run (although I don't know if anybody still runs unit tests in druntime). If using conditions in D is harder than in Java, than we should rethink their implementation. Every D object has a built-in mutex. Conditon variables should be able to work with this mutex and with synchronized sections out of the box. The most common case should be the easiest. The fact that you are having all those technical problems proves my point. As for non-technical problems, rewrite your test so that you wait on a condition in main and let the new thread do the signalling. That way they won't be able to miss each other, as they currently do.
Re: Condition Mutexes
== Quote from Bartosz Milewski (bartosz-nos...@relisoft.com)'s article dsimcha Wrote: Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? Conditions were implemented by Sean Kelly, so he's the guru. The file condition.d in core.sync has unit tests, which presumably still run (although I don't know if anybody still runs unit tests in druntime). If using conditions in D is harder than in Java, than we should rethink their implementation. Every D object has a built-in mutex. Conditon variables should be able to work with this mutex and with synchronized sections out of the box. The most common case should be the easiest. The fact that you are having all those technical problems proves my point. As for non-technical problems, rewrite your test so that you wait on a condition in main and let the new thread do the signalling. That way they won't be able to miss each other, as they currently do. I got my test program to work and understand what I did wrong. I think the real problem is that: 1. core.sync isn't even in the Phobos/druntime docs yet, and is still kind of here be dragons, so I originally thought it might legitimately just be broken. 2. The docs for core.sync.condition assume you already know what a condition variable is and how to use one and just provide a terse description of the interface to the druntime implementation with zero examples. On the other hand, the details of this primitive are somewhat arcane and hard to find. I'd vote for improving these and will do it myself if noone else does it by the time I get some higher priority hacking done.
Re: Condition Mutexes
On Wed, 21 Oct 2009 17:13:48 -0400, Bartosz Milewski bartosz-nos...@relisoft.com wrote: dsimcha Wrote: Bartosz, since you're a threading guru, could you please write a simple test program using core.sync.condition and see if it works, and if not either file a bug report or let me know? Conditions were implemented by Sean Kelly, so he's the guru. The file condition.d in core.sync has unit tests, which presumably still run (although I don't know if anybody still runs unit tests in druntime). If using conditions in D is harder than in Java, than we should rethink their implementation. Every D object has a built-in mutex. Conditon variables should be able to work with this mutex and with synchronized sections out of the box. The most common case should be the easiest. The fact that you are having all those technical problems proves my point. IIRC, Conditions should be able to use the in-object mutex. However, I think you still need a core.sync.Mutex object. I think the way it works is you initialize the Mutex with an object, and it inserts itself as the in-object mutex (hopefully before the on-demand mutex is created). So indirectly, you can do: new Condition(new Mutex(this)); Kinda odd, I agree... This should probably be shortcutted. Sean? -Steve
Re: static arrays becoming value types
Leandro Lucarella wrote: grauzone, el 21 de octubre a las 22:12 me escribiste: Or even: a, b = foo(); or a, _ = foo(); Works in Python (tm) _ is a regular symbol (variable name in this case), there is nothing special about the second form, which is exactly the same as the first. And I didn't even know this. In Python, it doesn't matter anyway, because it is dynamically typed, and you can assign arbitrary values to the same variable. Apparently, writing foreach (index,_;something) in D isn't a special case either; it just declares a variable named _. Several nested loops using _ are not possible. PS: let's hope Walter recognizes the need of *good* syntax for a simple, basic language construct like tuples. Just look at language_fan's D code and compare it with the corresponding Python code posted afterward. The D code looks so ridiculous. BTW, the trailing ; is not needed ;)
Re: Array, AA Implementations
On 19/10/2009 23:42, Andrei Alexandrescu wrote: Yigal Chripun wrote: here's an example of a well designed, consistent API: http://www.gobosoft.com/eiffel/gobo/structure/index.html This is a solid framework, unlike Java's containers which are a joke. I disagree with some of Gobo's abstractions (e.g. I believe all containers must be traversable and that primitives such as count() have no place in a general container) but generally the framework seems to be very well put together. It's a great source of inspiration for Phobos. Thanks very much for the link. Andrei My understanding of this design is that they identified all the orthogonal properties relevant to containers and that specific containers are a composition of a specific set of such properties. Eiffel has MI (different from the c++ implementation) which is helpful if you already have suitable default implementations for these properties. regarding traversable property: what if I want a container for a non-ordered type? an example would be a container of complex numbers, how would you traverse it? what about hash tables?
Re: Array, AA Implementations
On Thu, 22 Oct 2009 01:35:49 +0400, Yigal Chripun yigal...@gmail.com wrote: On 19/10/2009 23:42, Andrei Alexandrescu wrote: Yigal Chripun wrote: here's an example of a well designed, consistent API: http://www.gobosoft.com/eiffel/gobo/structure/index.html This is a solid framework, unlike Java's containers which are a joke. I disagree with some of Gobo's abstractions (e.g. I believe all containers must be traversable and that primitives such as count() have no place in a general container) but generally the framework seems to be very well put together. It's a great source of inspiration for Phobos. Thanks very much for the link. Andrei My understanding of this design is that they identified all the orthogonal properties relevant to containers and that specific containers are a composition of a specific set of such properties. Eiffel has MI (different from the c++ implementation) which is helpful if you already have suitable default implementations for these properties. regarding traversable property: what if I want a container for a non-ordered type? an example would be a container of complex numbers, how would you traverse it? what about hash tables? What's wrong with iterating over a hash table? An order is just unreliable (but still deterministic).
int always 32 bits on all platforms?
How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? Why is integer width so ambiguous in C/C++? (I am using platform as equivalent to CPU+OS+compiler).
Re: this() not executing code on structs
Andrei Alexandrescu wrote: Today, structs can't write their own this(). There aren't very solid reasons for that except that it makes language implementation more difficult. I wonder how much of a problem that could be in practice. I realized today that the Counted example - a classic C++ primer example featuring a struct that counts its own instances - cannot be implemented in D. In C++ the counted example looks like this: struct Counted { static unsigned count; unsigned myCount; Counted() { myCount = count++; } Counted(const Counted rhs) { myCount = count++; } Counted operator=(const Counted rhs) { // no writing to myCount return *this; } ~Counted() { --count; } } In D there's no chance to write Counted because you can always create Counted objects without executing any code. struct Counted { static uint count; uint myCount; this() { myCount = count++; } // ERROR this(this) { myCount = count++; } ref Counted opAssign(Counted rhs) { // no writing to myCount return this; } ~this() { --count; } } This being a toy example, I wonder whether there are much more serious examples that would be impossible to implement within D. I'd really like to know why scope x = new X(); is unsafe, while encouraging doing exactly the same with structs seems to be a perfectly fine idea. Allocating structs on the stack is obviously not any safer than with classes. I don't remember the exact reasons why you wanted to turn scope into a library feature, but I think I remember something about discouraging it for safety reasons; please forgive me is this is wrong. Why do you want to add class functionality to structs to enable RAII like features, when you could just use scope classes? To refresh everyone's memory: a scope class is declared like scope class Foo { ... }, and references to it can only appear as a function local variable. I for one don't really like the idea of having to distinguish between PODs and other stuff (like you had in C++) just again. At the very least, the default constructor should always be available for structs. (If not, have fun figuring out what S[10] should do.) Andrei
No header files?
Since D has no header files, how does one create a library that another developer can use without exposing the implementation?
Re: this() not executing code on structs
On Wed, 21 Oct 2009 17:54:08 -0400, grauzone n...@example.net wrote: I'd really like to know why scope x = new X(); is unsafe, while encouraging doing exactly the same with structs seems to be a perfectly fine idea. Allocating structs on the stack is obviously not any safer than with classes. I don't remember the exact reasons why you wanted to turn scope into a library feature, but I think I remember something about discouraging it for safety reasons; please forgive me is this is wrong. A class is a reference type. If you pass the reference to the stack to a function that then stores it for later use, it is unsafe. If you return it from the function, it's unsafe. If you do the same with a struct (not a struct pointer), this is not the case. Note that you *could* have the same problem with struct pointers or references, but typically, you expect to treat struct references like they are referencing stack data, it's not typical for classes. -Steve
Re: No header files?
On Wed, 21 Oct 2009 17:59:52 -0400, AJ a...@nospam.net wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? try dmd -H. .di files are D header files, basically used for the reason you specify. -Steve
Semicolons: mostly unnecessary?
Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Less typing is more!
Re: No header files?
On 21/10/2009 23:59, AJ wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? D does have header files with the extension .di which can be either auto generated and/or manually edited. IMO this is a design mistake carried over from c/c++.
Re: int always 32 bits on all platforms?
Hello aJ, How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? D is not built for 8 or 16 bit systems. However 32 bit math can be done on a 16 bit CPU, it's just slow. In the other direction, 32 bit math (and 16 and 8 bit) can be done on a 64 bit CPU so that's not a problem. If you really want the machine word size (and expecting code that does that to port is foolish) use size_t. Why is integer width so ambiguous in C/C++? (I am using platform as equivalent to CPU+OS+compiler). In C IIRC the rule is: native text item == char = short = int = long. This is a result of legacy issues from WAY back when (I think).
Re: Semicolons: mostly unnecessary?
On Wed, Oct 21, 2009 at 05:05:04PM -0500, AJ wrote: Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Less typing is more! It looks wrong, breaks habit, opens up bizarre parsing corner cases, and makes error messages uglier. Next thing you know someone will propose eliminating braces and just using whitespace to denote blocks. It's utter madness. -- Adam D. Ruppe http://arsdnet.net
Re: Semicolons: mostly unnecessary?
Hello aJ, Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Less typing is more! For the same reason error correction bits are not removed from transmission lines; that is because the redundancy has some very nice effects when it comes to detecting and dealing with errors. Also, having a language that is whitespace aware has issues and in this cases the upside is to small.
Re: No header files?
Steven Schveighoffer schvei...@yahoo.com wrote in message news:op.u157hfkveav...@localhost.localdomain... On Wed, 21 Oct 2009 17:59:52 -0400, AJ a...@nospam.net wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? try dmd -H. .di files are D header files, basically used for the reason you specify. OK, so header files can be generated. The thing is though, when I am designing at the code level, I start with the declarations (such as class data members and methods) and do the implementation (or one can hand it off to someone else) afterwards. That serves as the blue print for further development and remains as first level of documentation as well. Working with just implementation files seems to be putting the cart before the horse. While eliminating something unnecessary is something to strive for, I don't think header files are unnecessary in the development process (i.e., I don't think that relegating them to just the situation given with my OP is good, exactly for the reasons of usefullness I gave).
Re: No header files?
Hello Yigal, On 21/10/2009 23:59, AJ wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? D does have header files with the extension .di which can be either auto generated and/or manually edited. IMO this is a design mistake carried over from c/c++. What would you prefer? Aside from a better library format you need something to give DMD the information. Switching to a better library format has several issues including requiring more tools to make them and view them as well as it doesn't solve the problem of linking with C libs that don't and never will use this new format. Not fatal issues I'll grant, but what we have works NOW.
Re: No header files?
AJ Wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? If you need interfaces, just do them. your_interfaces.d: interface WhatYouWantToShow {} your_code.d: class WhatYouDontWantToShow : somePublicInterface {}
Re: No header files?
Hello aJ, Steven Schveighoffer schvei...@yahoo.com wrote in message news:op.u157hfkveav...@localhost.localdomain... On Wed, 21 Oct 2009 17:59:52 -0400, AJ a...@nospam.net wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? try dmd -H. .di files are D header files, basically used for the reason you specify. OK, so header files can be generated. The thing is though, when I am designing at the code level, I start with the declarations (such as class data members and methods) and do the implementation (or one can hand it off to someone else) afterwards. As it happens, .di files are just .d files that by convention only contain the interface. You can declare a class in a .d file and not give bodies for its methods and you won't get errors till link time, just like in C. That serves as the blue print for further development and remains as first level of documentation as well. Working with just implementation files seems to be putting the cart before the horse. While eliminating something unnecessary is something to strive for, I don't think header files are unnecessary in the development process (i.e., I don't think that relegating them to just the situation given with my OP is good, exactly for the reasons of usefullness I gave). I'm not sure what use you are seeing for them. As far as documentation goes, In the cases where I don't care about the implementation, I'd rather see some kind of extracted, generated documentation rather than a header file. The only argument I see for a header/implementation split is if you need to put part of a class in one file and part in another and I think that is a very weak case.
Re: Semicolons: mostly unnecessary?
Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Probably mostly because both some part of D language, some part of the mind of D developers, and some of the D programmers are old school and like to do things as they were in the past. I can list you twenty examples of this. Breaking old habits is not easy. - Adam D. Ruppe: It looks wrong, To me semicolons everywhere look wrong, even if I've programmed enough with languages that require a semicolon at the ends. breaks habit, It breaks a negative habit. opens up bizarre parsing corner cases, and makes error messages uglier. I have yet to see a proof of this. Next thing you know someone will propose eliminating braces and just using whitespace to denote blocks. It's utter madness. Even worse, someone may even implement such alternative D syntax, and the sky will fall on your head: http://delight.sourceforge.net/ Bye, bearophile
Re: int always 32 bits on all platforms?
BCS n...@anon.com wrote in message news:a6268ffbadb8cc20772570e...@news.digitalmars.com... Hello aJ, How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? D is not built for 8 or 16 bit systems. However 32 bit math can be done on a 16 bit CPU, it's just slow. In the other direction, 32 bit math (and 16 and 8 bit) can be done on a 64 bit CPU so that's not a problem. I wasn't thinking about math issues, but rather struct field alignment/portability, and platform alignment requirements for basic types, issues. I'm guessing that it is all worked out by the compiler, so that makes the development of a compiler more difficult, if so, but how much more difficult? A simple example or description of how this is done would really be great. (BTW, this is definitely an area where I would approve of more language implementation complexity for the great strides in programming efficiency (and fun!) it gives).
Re: No header files?
AJ Wrote: Steven Schveighoffer schvei...@yahoo.com wrote in message news:op.u157hfkveav...@localhost.localdomain... On Wed, 21 Oct 2009 17:59:52 -0400, AJ a...@nospam.net wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? try dmd -H. .di files are D header files, basically used for the reason you specify. OK, so header files can be generated. The thing is though, when I am designing at the code level, I start with the declarations (such as class data members and methods) and do the implementation (or one can hand it off to someone else) afterwards. That serves as the blue print for further development and remains as first level of documentation as well. Working with just implementation files seems to be putting the cart before the horse. While eliminating something unnecessary is something to strive for, I don't think header files are unnecessary in the development process (i.e., I don't think that relegating them to just the situation given with my OP is good, exactly for the reasons of usefullness I gave). I think you keep a very structured development style that few share. Nothing stops you from writing a header-file-like .d file and then hand it off for someone to fill in the methods, etc... A good IDE can also make a .d file look like a header file. Personally, I like colocating documentation with implementation and using tools (such as dmd) to extract higher level documentation.
Re: Semicolons: mostly unnecessary?
Hello bearophile, opens up bizarre parsing corner cases, and makes error messages uglier. I have yet to see a proof of this. Just off hand for parsing issues: - it allows long code lines to be folded - it acts as a bug check on reformat: origonal code MyType t; // result of -t and opSub_r(int) are lvalues auto a = 5 -t = 3 MyType t; auto a = 5 -t = 3 //reformat and forgot to add ';' Oops
Re: int always 32 bits on all platforms?
AJ Wrote: BCS n...@anon.com wrote in message news:a6268ffbadb8cc20772570e...@news.digitalmars.com... Hello aJ, How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? D is not built for 8 or 16 bit systems. However 32 bit math can be done on a 16 bit CPU, it's just slow. In the other direction, 32 bit math (and 16 and 8 bit) can be done on a 64 bit CPU so that's not a problem. I wasn't thinking about math issues, but rather struct field alignment/portability, and platform alignment requirements for basic types, issues. I'm guessing that it is all worked out by the compiler, so that makes the development of a compiler more difficult, if so, but how much more difficult? A simple example or description of how this is done would really be great. (BTW, this is definitely an area where I would approve of more language implementation complexity for the great strides in programming efficiency (and fun!) it gives). In D, both type size and alignment have the same defaults on all platforms. If desired, alignment can be explicitly controlled with the align attribute. Similarly, use of specific types control sizes.
Re: No header files?
On 22/10/2009 00:14, BCS wrote: Hello Yigal, On 21/10/2009 23:59, AJ wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? D does have header files with the extension .di which can be either auto generated and/or manually edited. IMO this is a design mistake carried over from c/c++. What would you prefer? Aside from a better library format you need something to give DMD the information. Switching to a better library format has several issues including requiring more tools to make them and view them as well as it doesn't solve the problem of linking with C libs that don't and never will use this new format. Not fatal issues I'll grant, but what we have works NOW. As you said, what is needed is a better lib format. we already have DDL NOW which already has most of what you described above. D can also take advantage of the LLVM framework. why do you need to choose between the two options anyway? dmd can support c header files combined with c libs and use a better D lib format for D code. Another option would be to have a simple tool to convert a bunch of c header files and a C lib to a D lib. The C/C++ way of headers + lib has problems which D inherited as part of the same (broken) design.
Re: int always 32 bits on all platforms?
Hello aJ, BCS n...@anon.com wrote in message news:a6268ffbadb8cc20772570e...@news.digitalmars.com... Hello aJ, How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? D is not built for 8 or 16 bit systems. However 32 bit math can be done on a 16 bit CPU, it's just slow. In the other direction, 32 bit math (and 16 and 8 bit) can be done on a 64 bit CPU so that's not a problem. I wasn't thinking about math issues, OK but rather struct field alignment/portability, and platform alignment requirements for basic types, issues. Unless you say otherwise, the compiler is free to align struct however it wants (this is true in C but there are conventions) and in general you can't expect it to do the same for different system (again, ditto re C) OTOH I'm not sure how that links into int being the same size all over. If anything that should make these issue less of a problem. I'm guessing that it is all worked out by the compiler, so that makes the development of a compiler more difficult, if so, but how much more difficult? A simple example or description of how this is done would really be great. (BTW, this is definitely an area where I would approve of more language implementation complexity for the great strides in programming efficiency (and fun!) it gives).
Re: Semicolons: mostly unnecessary?
Adam D. Ruppe destructiona...@gmail.com wrote in message news:mailman.222.1256163114.20261.digitalmar...@puremagic.com... On Wed, Oct 21, 2009 at 05:05:04PM -0500, AJ wrote: Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Less typing is more! It looks wrong, breaks habit, opens up bizarre parsing corner cases, and makes error messages uglier. Next thing you know someone will propose eliminating braces and just using whitespace to denote blocks. It's utter madness. Not whitespace aware, but rather newline aware. Newlines are already at the end of a line, so a semicolon is redundant. IOW, the default statement terminator can be the newline. struct something { int x1 long x2 } vs. struct something { int x1; long x2; }; First one is definitely cleaner. The less the eye has to bring in to be deciphered by the brain, the better. void somefunc() Is the above a declaration or start of a definition? Still though, only 1 char of lookahead needed to determine. Maybe one can't fully appreciate semicolon terminators until one tries to implement a language without them. (Because apparently no one has written that article or paper (?)).
Re: Semicolons: mostly unnecessary?
Wed, 21 Oct 2009 18:29:37 -0400, bearophile thusly wrote: Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Probably mostly because both some part of D language, some part of the mind of D developers, and some of the D programmers are old school and like to do things as they were in the past. I can list you twenty examples of this. Breaking old habits is not easy. - Adam D. Ruppe: It looks wrong, To me semicolons everywhere look wrong, even if I've programmed enough with languages that require a semicolon at the ends. breaks habit, It breaks a negative habit. opens up bizarre parsing corner cases, and makes error messages uglier. I have yet to see a proof of this. Next thing you know someone will propose eliminating braces and just using whitespace to denote blocks. It's utter madness. Even worse, someone may even implement such alternative D syntax, and the sky will fall on your head: http://delight.sourceforge.net/ Relax, bearophile. It seems there are some things you cannot change in this world. It will not suffice that you prove them wrong. I think I'll just give up on D. The development model is too stagnant. The author refuses to learn from new languages like Python or C#, or old languages (SML) unless someone is kind enough to spend whole day explaining the features to him. That's a sick basis for developing new languages. Large part of the community shares this mindset. The more I think about it, the more I realize this language is not for me. I apologize my arrogance. Bye.
Re: Semicolons: mostly unnecessary?
On Wed, 21 Oct 2009 18:05:04 -0400, AJ a...@nospam.net wrote: Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Less typing is more! It has been said in the past that having semicolons makes parsing easier. I don't know how true this is, but Walter said it, so it probably is pretty important. You also forget about statements that span multiple lines, functions with 15 args are much easier to read when they are separated into multiple lines IMO. To all those guys who want no semicolons: get over it. Use another language if you don't want semicolons. There are some out there. D isn't going to to change one of it's most fundamental constructs because it's less typing. -Steve
Re: Semicolons: mostly unnecessary?
Adam D. Ruppe wrote: On Wed, Oct 21, 2009 at 05:05:04PM -0500, AJ wrote: Why not eliminate the requirement for semicolon statement terminators (unless there are multiple statements per line)? Less typing is more! It looks wrong, breaks habit, opens up bizarre parsing corner cases, and makes error messages uglier. Next thing you know someone will propose eliminating braces and just using whitespace to denote blocks. It's utter madness. Yay, Ruby! (almost) I started to use it some days ago and I feel in love with it.
Re: int always 32 bits on all platforms?
AJ Wrote: How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? Why is integer width so ambiguous in C/C++? (I am using platform as equivalent to CPU+OS+compiler). int can be any width D wants it to be and everything works great so long as you're only calling D functions. The conflict comes when calling C functions, and there's nothing in the language for addressing this. Instead, it's a library issue. For example, Druntime's core.stdc.config defines c_long and c_ulong types for interfacing with C, since these types change width across 32 and 64-bit platforms. There's been no attempt to deal with odd-sized int or other types though. That just isn't an issue on common platforms.
Re: No header files?
On Wed, 21 Oct 2009 18:16:48 -0400, AJ a...@nospam.net wrote: Steven Schveighoffer schvei...@yahoo.com wrote in message news:op.u157hfkveav...@localhost.localdomain... On Wed, 21 Oct 2009 17:59:52 -0400, AJ a...@nospam.net wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? try dmd -H. .di files are D header files, basically used for the reason you specify. OK, so header files can be generated. The thing is though, when I am designing at the code level, I start with the declarations (such as class data members and methods) and do the implementation (or one can hand it off to someone else) afterwards. That serves as the blue print for further development and remains as first level of documentation as well. Working with just implementation files seems to be putting the cart before the horse. While eliminating something unnecessary is something to strive for, I don't think header files are unnecessary in the development process (i.e., I don't think that relegating them to just the situation given with my OP is good, exactly for the reasons of usefullness I gave). Separating interface from implementation is good -- but not if you have to repeat the interface (as you do with C++ or C). What happens (and being a long-time C++ developer, I've had my fair share of experience with it) is that the interface gets out of sync with the implementation, so weird shit happens. I even think d's editable interface files are suspect. They can be out of sync with the object files, and then you have the same problem. The best model by far is Java and C# where the object files *are* the interface files. Then you only have to worry about documentation being out of sync. But at least your programs don't crash randomly for no reason because the docs are invalid. What I would suggest is creating stub functions via {} and then when you go back to fill in the interface, fill in the {} area. You get the same effect. -Steve
Re: Semicolons: mostly unnecessary?
BCS: - it allows long code lines to be folded This is not a problem, when you have optional semicolons, you add some syntax to fold long lines. Python uses \ Mathematica uses \\ and so on. Languages like Scala, Boo, Genie, etc seem able to survive. - it acts as a bug check on reformat: origonal code MyType t; // result of -t and opSub_r(int) are lvalues auto a = 5 -t = 3 MyType t; auto a = 5 -t = 3 //reformat and forgot to add ';' Oops I've written enough Python code to fill few books, and this doesn't happen often, something like few times in a year. I think this is one of those things that you have to try for real for few hours in a row to be able to judge them a little. Bye, bearophile
Re: No header files?
Hello Yigal, On 22/10/2009 00:14, BCS wrote: Hello Yigal, On 21/10/2009 23:59, AJ wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? D does have header files with the extension .di which can be either auto generated and/or manually edited. IMO this is a design mistake carried over from c/c++. What would you prefer? Aside from a better library format you need something to give DMD the information. Switching to a better library format has several issues including requiring more tools to make them and view them as well as it doesn't solve the problem of linking with C libs that don't and never will use this new format. Not fatal issues I'll grant, but what we have works NOW. As you said, what is needed is a better lib format. we already have DDL NOW which already has most of what you described above. D can also take advantage of the LLVM framework. Does DDL or LLVM work to generate monolithic executable that use all of D's features and do so for both Win32 and *nux? Also, can I use notepad to view either of those file types? why do you need to choose between the two options anyway? dmd can support c header files combined with c libs and use a better D lib format for D code. Another option would be to have a simple tool to convert a bunch of c header files and a C lib to a D lib. Option 1 is a no starter (Walter has said NO the that exact option based on it needing in effect a full C frontend to work) Option 2 in interesting but, it runs flat into to needs more tools issue. The C/C++ way of headers + lib has problems which D inherited as part of the same (broken) design.
Re: static arrays becoming value types
grauzone, el 21 de octubre a las 23:32 me escribiste: Leandro Lucarella wrote: grauzone, el 21 de octubre a las 22:12 me escribiste: Or even: a, b = foo(); or a, _ = foo(); Works in Python (tm) _ is a regular symbol (variable name in this case), there is nothing special about the second form, which is exactly the same as the first. And I didn't even know this. In Python, it doesn't matter anyway, because it is dynamically typed, and you can assign arbitrary values to the same variable. Apparently, writing foreach (index,_;something) in D isn't a special case either; it just declares a variable named _. Several nested loops using _ are not possible. Using _ is a bad idea if you use gettext though ;) -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- El techo de mi cuarto lleno de estrellas
Re: Semicolons: mostly unnecessary?
BCS wrote: Hello bearophile, opens up bizarre parsing corner cases, and makes error messages uglier. I have yet to see a proof of this. Just off hand for parsing issues: - it allows long code lines to be folded If you don't have semicolons this is also true, for example a = somefunc( first_param, second_param) b = something_else I can insert a line break there without confusing the parser because the parser is expecting the function call to end - it acts as a bug check on reformat: origonal code MyType t; // result of -t and opSub_r(int) are lvalues auto a = 5 -t = 3 MyType t; auto a = 5 -t = 3 //reformat and forgot to add ';' Oops Why would the formatter do that? The line break is acting as a semicolon, it won't remove it.
Re: int always 32 bits on all platforms?
Hello Jason, In D, both type size and alignment have the same defaults on all platforms. If desired, alignment can be explicitly controlled with the align attribute. Similarly, use of specific types control sizes. Ummm? IIRC, struct alignment follows the lead of the native compiler for the given system. That is, type size issues aside, structs without align directive can be passed from C to D by default.
Re: Semicolons: mostly unnecessary?
language_fan: It will not suffice that you prove them wrong. Usually I am not able to prove things, I mostly just give suggestions. The development model is too stagnant. D is now quite alive, Andrei seems interested in changing something basic of D every day :-) Bye, bearophile
Re: No header files?
BCS n...@anon.com wrote in message news:a6268ffbae78cc207990f9b...@news.digitalmars.com... Hello aJ, Steven Schveighoffer schvei...@yahoo.com wrote in message news:op.u157hfkveav...@localhost.localdomain... On Wed, 21 Oct 2009 17:59:52 -0400, AJ a...@nospam.net wrote: Since D has no header files, how does one create a library that another developer can use without exposing the implementation? try dmd -H. .di files are D header files, basically used for the reason you specify. OK, so header files can be generated. The thing is though, when I am designing at the code level, I start with the declarations (such as class data members and methods) and do the implementation (or one can hand it off to someone else) afterwards. As it happens, .di files are just .d files that by convention only contain the interface. You can declare a class in a .d file and not give bodies for its methods and you won't get errors till link time, just like in C. That serves as the blue print for further development and remains as first level of documentation as well. Working with just implementation files seems to be putting the cart before the horse. While eliminating something unnecessary is something to strive for, I don't think header files are unnecessary in the development process (i.e., I don't think that relegating them to just the situation given with my OP is good, exactly for the reasons of usefullness I gave). I'm not sure what use you are seeing for them. The 2 that I gave were: 1. Serves as a blueprint (or skeleton) for further development. 2. Serves as documentation for usage or for evaluation-for-purpose (suitability). (1) is working at a higher level (designing vs. implenting) and perhaps even separating much of the design work from the implementation work (i.e., separate individuals or teams working on one or the other). (2) eliminates the need for secondary documentation (for well-designed code). I think of secondary documentation as the detailed description of how something works. Prior to consulting such, I'd want to know what something is, and something like a class declaration gives me that information immediately, without reading paragraphs of text. For example, you can describe car to me, but it would be much easier to just show me one. As far as documentation goes, In the cases where I don't care about the implementation, I'd rather see some kind of extracted, generated documentation rather than a header file. Class Shape { void Draw(); } What more do you need to know usually? The only argument I see for a header/implementation split is if you need to put part of a class in one file and part in another and I think that is a very weak case.
Re: int always 32 bits on all platforms?
BCS n...@anon.com wrote in message news:a6268ffbaf38cc207c67388...@news.digitalmars.com... Hello aJ, BCS n...@anon.com wrote in message news:a6268ffbadb8cc20772570e...@news.digitalmars.com... Hello aJ, How can/does D guarantee that int will always be 32 bits on all platforms? Does this mean that D won't work on some platforms? D is not built for 8 or 16 bit systems. However 32 bit math can be done on a 16 bit CPU, it's just slow. In the other direction, 32 bit math (and 16 and 8 bit) can be done on a 64 bit CPU so that's not a problem. I wasn't thinking about math issues, OK but rather struct field alignment/portability, and platform alignment requirements for basic types, issues. Unless you say otherwise, the compiler is free to align struct however it wants (this is true in C but there are conventions) and in general you can't expect it to do the same for different system (again, ditto re C) OTOH I'm not sure how that links into int being the same size all over. If anything that should make these issue less of a problem. I would think so. Anyway, what I find compelling about guaranteed widths is the potential to eliminate alignment and padding issues (that is, be able to control it with confidence across platforms as one already can on a single platform via compiler pragmas or cmdline switches). I'm guessing that it is all worked out by the compiler, so that makes the development of a compiler more difficult, if so, but how much more difficult? A simple example or description of how this is done would really be great. (BTW, this is definitely an area where I would approve of more language implementation complexity for the great strides in programming efficiency (and fun!) it gives).
Re: Semicolons: mostly unnecessary?
Hello bearophile, BCS: - it allows long code lines to be folded This is not a problem, when you have optional semicolons, you add some syntax to fold long lines. Python uses \ Mathematica uses \\ and so on. Languages like Scala, Boo, Genie, etc seem able to survive. The only one of those in common use is Python and its not a good date point because of all the other whitespace stuff it does (it's in a category all its own). Also line continuation Is just ugly. (And before you ask, no, I don't think semicolons are ugly) - it acts as a bug check on reformat: origonal code MyType t; // result of -t and opSub_r(int) are lvalues auto a = 5 -t = 3 MyType t; auto a = 5 -t = 3 //reformat and forgot to add ';' Oops I've written enough Python code to fill few books, and this doesn't happen often, something like few times in a year. I think this is one of those things that you have to try for real for few hours in a row to be able to judge them a little. I'll grant the only white space aware languages I've used much are basic (a long time ago) and the C preprocessor. As for CPP the whitespace issues are the #1 thing I dislike about it (and there are a few other things I don't like one bit)