Re: Proposal: user defined attributes
On 21 March 2012 20:32, Andrei Alexandrescu wrote: > Well if the argument boils down to nice vs. ugly, as opposed to possible > vs. impossible - it's quite a bit less compelling. > By this logic, I might as well stick with C++. It's 'possible' to do everything I need, but it makes my cry myself to sleep at night, and wastes insane amounts of time. Code simplicity and cleanliess on the front end IS important, it makes code reasable, maintainable. In a large code team, if someone has to go out of their way to understand some code, chances are, they won't understand it, and make improper or damaging changes to it. Or make improper implementations based on it. This will destroy your code across 5 years or so. In gamedev, the average engine codebase lasts 10+ years.
Re: Proposal for a MessageQueue (was Re: public MessageBox)
Making such interface public would even allow to integrate D communication mechanisms between processes/machines, similar to what Akka allows. "Nathan M. Swan" wrote in message news:ladihiaieksszjodf...@forum.dlang.org... On Wednesday, 21 March 2012 at 03:37:35 UTC, Nathan M. Swan wrote: After playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other. So this is my proposal: that std.concurrency is modified so that class MessageBox is public and MessageBoxs be passed around through other MessageBoxs, or perhaps another class is devised for this. I'm not sure of the implications of this, though I know I would find it very useful by allowing me to write code without ("import core."~someLowLevelModule) After thinking about this more, this is my proposal for the API. Backward compatibility is more important here than in other places because it is documented in TDPL. Each Tid contains a default MessageQueue accessible by property messageQueue. The send/receive functions and their variants operate on the tid's default messageQueue. The interface for class MessageQueue: void send(T...)(T vals); void prioritySend(T...)(T vals); void receive(T...)(T ops); receiveOnlyRet!(T) receiveOnly(T...)(T ops); bool receiveTimeout(T...)(Duration duration, T ops); @property void maxSize(size_t size); @property void onCrowding(OnCrowding oc); @property void onCrowding(bool function(MessageQueue) doThis); Hopefully, this won't break any current code, and it will be easy to implement.
Re: Wrong lowering for a[b][c]++
On 3/21/12, H. S. Teoh wrote: > Sorry, I was thinking in terms of my AA implementation which is done > using a struct with operator overloading. I should've checked what the > behaviour of the current built-in AAs are before posting. :-P Well in that case isn't it a necessity to keep compatibility with the old implementation? Do we really have to break user-code again?
Re: opEquals/opCmp returning other types
On 21/03/12 21:53, Jacob Carlborg wrote: On 2012-03-21 17:44, H. S. Teoh wrote: The "D way" is to use strings for DSELs which get evaluated at compile-time, or a custom set of methods that you can build expressions out of. Operator overloading really should be limited to arithmetic types (for numerical classes) and built-in operations like array lookups and stuff. Trying to shoehorn language-level operators to do something they weren't intended to do only leads to problems. (C++'s overloading of<< and>> for I/O is a very bad design decision IMO.) "find", "map" and similar functions can be used on arrays. What's wrong in being able to use the same syntax for accessing a database. I think the following would be a great syntax: Person.where(x => x.name == "John"); Where "Person" is a class connected to a database table. Indeed, it may be possible to use a new-style delegate literal instead of a string, for defining your DSL. My point was that we don't need to be able to return arbitrary types from operators. Instead, we might need some syntax sugar or library support for getting syntax trees from expressions.
Re: Proposal: user defined attributes
On 3/21/12, Andrei Alexandrescu wrote: > I think the liability here is that b needs to appear in two places. Andrei, how about this: import std.stdio; import std.conv; struct NonSerialized(T) { enum isNonSerialized = true; T payload; alias payload this; } struct Foo { this(int x, string name, string lastName, string extra) { this.x = x; this.name = name; this.lastName = lastName; this.extra = extra; } int x; NonSerialized!string name; NonSerialized!string lastName; string extra; } string serialize(T)(T input) { string result; foreach (i, field; input.tupleof) { static if (skipSerialize!(typeof(field))) result ~= to!string(typeof(field).init) ~ "\n"; else result ~= to!string(field) ~ "\n"; } return result; } template skipSerialize(T) { enum bool skipSerialize = hasValidMember!(T, "isNonSerialized"); } template hasValidMember(T, string member) { static if (__traits(hasMember, T, member)) { enum bool hasValidMember = mixin("T." ~ member); } else enum bool hasValidMember = false; } void main() { Foo foo = Foo(10, "Foo", "Bar", "Doo"); string bin = serialize(foo); writeln(bin); } Note that I've had to make a constructor because I can't implicitly assign a string to a NonSerialized!string inside of a struct literal (but I think this is just a DMD frontend bug).
Re: Proposal: user defined attributes
On Thursday, 22 March 2012 at 10:18:24 UTC, Andrej Mitrovic wrote: On 3/21/12, Andrei Alexandrescu wrote: I think the liability here is that b needs to appear in two places. Andrei, how about this: Note that I've had to make a constructor because I can't implicitly assign a string to a NonSerialized!string inside of a struct literal (but I think this is just a DMD frontend bug). Now, this is pure beauty. :)
Re: Proposal: user defined attributes
On Thursday, 22 March 2012 at 10:18:24 UTC, Andrej Mitrovic wrote: On 3/21/12, Andrei Alexandrescu wrote: I think the liability here is that b needs to appear in two places. Andrei, how about this: Note that I've had to make a constructor because I can't implicitly assign a string to a NonSerialized!string inside of a struct literal (but I think this is just a DMD frontend bug). Altering the type is not a reasonable approach for a generic annotation system. 1) It wrecks things that use template arguments, possibly special casing for certain types. 2) It makes it difficult to combine attributes. 3) It forces altering actual code to indicate an annotation, as opposed to just annotating it. Honestly, C# already handles annotations perfectly (with the exception of too little compile-time power to specify the arguments), I see no reason to attempt to reinvent it. I've never had a problem where I thought that C#'s attributes were not sufficient.
Re: Wrong lowering for a[b][c]++
On 21/03/12 21:41, Alvaro wrote: El 21/03/2012 19:39, Jonathan M Davis escribió: On Wednesday, March 21, 2012 11:29:14 H. S. Teoh wrote: A question was asked on the d-learn forum about why this throws a RangeError: int[string][int] map; map["abc"][20]++; This is understandable, since the compiler translates the second line to: map.opIndex("abc").opIndexUnary!"++"(20); Since map["abc"] doesn't exist yet, opIndex throws RangeError before we ever get to the ++. I'd like to propose the following fix: if a given chained indexing expression has any operator applied to its final result (either a unary operator like ++ or --, or an assignment operator like +=), then instead of translating previous indexes into opIndex, the compiler should map it to a new operator overload, say opIndexCreate, which creates the relevant entry with default value if it doesn't exist yet. That is to say: map["abc"][20]++; should be translated to: map.opIndexCreate("abc").opIndexUnary!"++"(20); where opIndexCreate looks something like: Slot opIndexCreate(Key k) { Slot *s = findSlot(k); if (s is null) { s = createNewSlot(k); } return s; } Similar changes should be made for expressions like a[b][c][d]=100, or a[b][c][d]+=100. In other words, if the tail of a chain of indexing operations maps to opIndexAssign, opIndexUnary, or opIndexOpAssign, then all preceding opIndex calls should be converted to opIndexCreate instead. Comments? IMHO, it's _horrible_ that C++ creates entries in a std::map when you ask for values that aren't there. A RangeError is _exactly_ what should be happening here. There's no element to increment, because it hasn't been added yet. I think that the current behavior is very much what the behavior _should_ be. - Jonathan M Davis I partially disagree. I think items should be added if we try to *write* to them, but not when we *read* them (lvalue vs rvalue). The problem is that it's hard to distinguish those cases in C++ without an intermediate class that makes its use uglier. So: int[int] a; a[3] = 1; // OK, add key 3 b = a[5]; // error, add nothing And, compound assignment and increment/decrement are forms of *writing*. Yes, but they read before they write. So, they should trigger an element creation with the .init value. a[5]++; // create a[5] = int.init; and then increment
Re: What about putting array.empty in object.d?
On Wed, 21 Mar 2012 20:53:42 -0400, Jonathan M Davis wrote: On Wednesday, March 21, 2012 20:46:05 Jonathan M Davis wrote: On Wednesday, March 21, 2012 20:17:06 Steven Schveighoffer wrote: > On Wed, 21 Mar 2012 19:56:41 -0400, Jonathan M Davis > > wrote: > > Except that containers shouldn't provide indexing if it's not efficient. > > And > > from what I've seen, it's far too common for programmers to check length > > == 0, > > and they end up doing it on stuff like linked lists where it _is_ > > inefficient. > > Wait, if someone provides inefficient length, what makes you think they > won't provide inefficient indexing? Both C++'s STL and D's std.container put requirements on the algorithmic complexity of various operations. O(n) indexing would violate them, whereas they allow O(n) length/size. Actually, it looks like std.container _does_ guarantee that length is O(1), unlike C++'s STL, in which case it's not the same issue that it is in C++. I'd still tend to argue that checking for empty is better, but I guess that it's not as big a deal. In C++, it's a definite problem when programmers keep checking that size() == 0, since inevitably, it ends up happening with linked lists and the like, making for inefficient code, and simply being in the habit of using empty() rather than size() == 0 avoids such problems. Yes, that was my point. Note that the default std::list has O(1) length (as does dcollections' LinkedList). It's not as inevitable as you think. -Steve
Re: Proposal: user defined attributes
On 20/03/12 22:29, Jacob Carlborg wrote: On 2012-03-20 17:13, Andrei Alexandrescu wrote: On 3/20/12 10:52 AM, Jacob Carlborg wrote: On 2012-03-20 16:17, Andrei Alexandrescu wrote: On 3/20/12 12:50 AM, Kapps wrote: Perhaps we should add a field of type Variant[string]. No, not Variant[string] again. Why? I thought it was agreed that that's a good idea for exceptions. Maybe you agreed on that. I still don't like it. I'm not sure who agreed, but I don't even think it would work. What happens if the AA or Variant throws an exception? Especially if AAs become a library type, they've got no business being in something as fundamental as an exception base class. It leads to a big ball of mud design.
Re: Proposal: user defined attributes
On 3/22/12, Kapps wrote: > 1) It wrecks things that use template arguments, possibly special > casing for certain types. Yeah I've noticed things tend to break with alias this. Anyway if templates could be improved for these edge-cases then it's a benefit for everyone, regardless of annotations. :) > 2) It makes it difficult to combine attributes. Difficult.. well maybe. You could use something like: Attribute!(int, NonSerialized, Encrypted) ID1, ID2; Or override opAssign and use bit masks: Attribute!int ID1 = NonSerialized | Encrypted; Attribute!int ID2 = NonSerialized | Encrypted; With attributes this would maybe be: @NonSerialized @Encrypted int ID1, ID2; I do like the attribute syntax more. > 3) It forces altering actual code to indicate an annotation, as > opposed to just annotating it. Yup.
Re: Proposal: user defined attributes
On 3/22/12 2:32 AM, Andrei Alexandrescu wrote: On 3/21/12 12:06 PM, Jacob Carlborg wrote: On 2012-03-21 16:11, Andrei Alexandrescu wrote: I think the liability here is that b needs to appear in two places, once in the declaration proper and then in the NonSerialized part. (A possible advantage is that sometimes it may be advantageous to keep all symbols with a specific attribute in one place.) A possibility would be to make the mixin expand to the field and the metadata at once. Yes, but that just looks ugly: class Foo { int a; mixin NonSerialized!(int, "b"); } That's why it's so nice with attributes. Well if the argument boils down to nice vs. ugly, as opposed to possible vs. impossible - it's quite a bit less compelling. Andrei Why don't you program everything with gotos instead of for, foreach and while? If it boils down to nice vs. ugly, as opposed to possible vs. impossible... Hmm...
Re: Wrong lowering for a[b][c]++
On Wednesday, 21 March 2012 at 20:41:17 UTC, Alvaro wrote: I partially disagree. I think items should be added if we try to *write* to them, but not when we *read* them (lvalue vs rvalue). The problem is that it's hard to distinguish those cases in C++ without an intermediate class that makes its use uglier. So: int[int] a; a[3] = 1; // OK, add key 3 b = a[5]; // error, add nothing And, compound assignment and increment/decrement are forms of *writing*. So, they should trigger an element creation with the .init value. a[5]++; // create a[5] = int.init; and then increment I have used similar before, it is nicer than if(5 !in a) a[5] = 1; else a[5]++; but after taking a look at reduce. double[int] a; What is the result of your code on 'a' now? double.init is NAN.
Re: Wrong lowering for a[b][c]++
On 3/22/12, Jesse Phillips wrote: > double[int] a; > What is the result of your code on 'a' now? double.init is NAN. Hmm this is interesting. With 2.058: double[int] a; a[0]++; writeln(a[0]); // prints 1 double b; b++; writeln(b); // prints nan
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 11:01:35AM +0100, Andrej Mitrovic wrote: > On 3/21/12, H. S. Teoh wrote: > > Sorry, I was thinking in terms of my AA implementation which is done > > using a struct with operator overloading. I should've checked what the > > behaviour of the current built-in AAs are before posting. :-P > > Well in that case isn't it a necessity to keep compatibility with the > old implementation? Do we really have to break user-code again? Yes we have to keep compatibility. But as some have pointed out, this works: int[string][int] map; map[20]["abc"]++; // sets map[20]["abc"] to 1 Looking at druntime code, I see that in aaA.d there's _aaGetX (which creates a new entry if it doesn't already exist) and _aaGetRvalueX (doesn't create new entry). Which look like the equivalents of opIndexCreate and opIndex. The problem is that the language doesn't currently support the former in user-defined structs; so this *will* break compatibility. T -- Real Programmers use "cat > a.out".
Re: Proposal: user defined attributes
On 03/21/12 14:36, Adam D. Ruppe wrote: > On Wednesday, 21 March 2012 at 08:29:23 UTC, Tove wrote: >> With the mixin improvement proposal any arbitrarily complex feature can be >> implemented in the library, appearing to enjoy first class syntax with just >> 1 extra character penalty vs the compiler. > > My main concern with the library implementation isn't > syntax. > > The big question is still: where will you put the > annotation data? A (new) compile-time only (mutable) storage class. It's probably needed for other things too, to avoid compiler-specific pragmas+section-attributes+linker-magic to achieve the same effect. For run-time accessible custom attributes (if those are even necessary), the lib solution wouldn't be much different than a built-in one anyway. artur
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 03:26:00PM +0100, Andrej Mitrovic wrote: > On 3/22/12, Jesse Phillips wrote: > > double[int] a; > > What is the result of your code on 'a' now? double.init is NAN. > > Hmm this is interesting. With 2.058: > > double[int] a; > a[0]++; > writeln(a[0]); // prints 1 > > double b; > b++; > writeln(b); // prints nan This is because in aaA.d _aaGetX creates a new entry if one isn't found, but because it has no direct access to value types (only has typeinfo), it doesn't know what value .init has. It sets the value to binary zero by default. (This is one of the places where you *really* want the AA implementation to be in object_.d, where it can actually say Value.init instead of hacking it with binary zero, which is wrong in this case but pretty much impossible to fix.) T -- If it tastes good, it's probably bad for you.
Re: Three Unlikely Successful Features of D
On Thursday, 22 March 2012 at 04:49:24 UTC, Nick Sabalausky wrote: And then later on someone made sort of a mini file-system where you could add data to a ROM image and then query/access it from your code Now, this reminds me, what if you want to access the compile time files from runtime? For instance, one of my projects lets you include other files in the html. (Something I actually don't like, but it is an easy crutch.) You can also replace these at runtime, so the other team members can change stuff without access to the compiler. Here's what I ended up writing: // filesystem alternatives... string getFile(string name)() { if(std.file.exists(dir ~ name)) return std.file.readText(dir ~ name); else return import(name); } // runtime fetching string getIncludeFile(string name) { enum manifest = ["file1.html", "file2.html", ..]; string manifests() { string cases; foreach(f; manifest) cases ~= "case \""~f~"\": return getFile!(\""~f~"\");"; return cases; } switch(name) { default: assert(0, name); mixin(manifests()); } } I'm a bit disappointed that I needed a list of files duplicated there. With import(), if it is in the import directory, it just works, but then the name must be known at compile time. This is the best I have so far... and i like it, but it isn't quite ideal yet.
Re: Wrong lowering for a[b][c]++
On 3/22/12, H. S. Teoh wrote: > This is because in aaA.d _aaGetX creates a new entry if one isn't found, > but because it has no direct access to value types (only has typeinfo), > it doesn't know what value .init has. It sets the value to binary zero > by default. Damn, hashes really are a terrible hack. I'm really looking forward to your new implementation.
Re: public MessageBox
Le 21/03/2012 04:37, Nathan M. Swan a écrit : After playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other. They will, even with different boxes.
Re: Wrong lowering for a[b][c]++
On 3/22/12 9:32 AM, H. S. Teoh wrote: On Thu, Mar 22, 2012 at 11:01:35AM +0100, Andrej Mitrovic wrote: On 3/21/12, H. S. Teoh wrote: Sorry, I was thinking in terms of my AA implementation which is done using a struct with operator overloading. I should've checked what the behaviour of the current built-in AAs are before posting. :-P Well in that case isn't it a necessity to keep compatibility with the old implementation? Do we really have to break user-code again? Yes we have to keep compatibility. But as some have pointed out, this works: int[string][int] map; map[20]["abc"]++; // sets map[20]["abc"] to 1 Looking at druntime code, I see that in aaA.d there's _aaGetX (which creates a new entry if it doesn't already exist) and _aaGetRvalueX (doesn't create new entry). Which look like the equivalents of opIndexCreate and opIndex. The problem is that the language doesn't currently support the former in user-defined structs; so this *will* break compatibility. This is a bug in the language that requires fixing. Andrei
Re: Wrong lowering for a[b][c]++
Andrei Alexandrescu: This is a bug in the language that requires fixing. I agree. Is someone willing to write a good enhancement request about it? Bye, bearophile
Re: public MessageBox
On Thursday, 22 March 2012 at 00:30:51 UTC, Nathan M. Swan wrote: As I posted a while back, the concept of a variant message queue is wonderful and powerful, and the implementation is great. But the fact that you can't declare "auto mq = new MessageQueue()" is a gaping whole in an otherwise A+ API. Nice to hear that I'm not alone with that opinion – I hit the same problem when implementing a request log file writer for Thrift, which runs in a separate thread and communicates with the main thread via a message queue. It works great and performed even better than a similar C++ version due to lower lock contention, but the user'd better not try to call receiveOnly!() from »his« thread… David
Re: Proposal for a MessageQueue (was Re: public MessageBox)
On Mar 21, 2012, at 9:12 PM, "Nathan M. Swan" wrote: > On Wednesday, 21 March 2012 at 03:37:35 UTC, Nathan M. Swan wrote: >> After playing around with making a library with uses threads, I realized it >> would be nice if there could be multiple inter-thread mailboxes than just >> one per thread. That way, client code and third-party library code don't >> interfere with each other. >> >> So this is my proposal: that std.concurrency is modified so that class >> MessageBox is public and MessageBoxs be passed around through other >> MessageBoxs, or perhaps another class is devised for this. >> >> I'm not sure of the implications of this, though I know I would find it very >> useful by allowing me to write code without ("import >> core."~someLowLevelModule) > > After thinking about this more, this is my proposal for the API. Backward > compatibility is more important here than in other places because it is > documented in TDPL. > > Each Tid contains a default MessageQueue accessible by property messageQueue. > > The send/receive functions and their variants operate on the tid's default > messageQueue. > > The interface for class MessageQueue: > > void send(T...)(T vals); > void prioritySend(T...)(T vals); > void receive(T...)(T ops); > receiveOnlyRet!(T) receiveOnly(T...)(T ops); > bool receiveTimeout(T...)(Duration duration, T ops); > @property void maxSize(size_t size); > @property void onCrowding(OnCrowding oc); > @property void onCrowding(bool function(MessageQueue) doThis); > > Hopefully, this won't break any current code, and it will be easy to > implement. I can see adapting the API so that each thread has a default message queue (keep in mind that we'll be adding interprocess messaging at some point via the same routines). I'm not yet clear how the existence of alternate message queues could be communicated to other portions of the code though. register() is one way I suppose. Really what's happening here is that Tid is being replaced by a queue ID, not extended with a mutable variable. I guess Tid would become an alias for the Qid created when a thread is spawned. What I really don't want though, is for receive() to operate on a message queue created in a different thread. Messaging would become substantially slower if receive() had to be synchronized.
Re: public MessageBox
On Thursday, 22 March 2012 at 15:14:31 UTC, deadalnix wrote: They will, even with different boxes. Similarly succinct: How so?
Re: public MessageBox
Le 22/03/2012 16:50, David Nadlinger a écrit : On Thursday, 22 March 2012 at 15:14:31 UTC, deadalnix wrote: They will, even with different boxes. Similarly succinct: How so? They will because of synchronization. This cost will not be transparent. Not that it is a bad idea, but it depends what it meant by no interference.
Proposal: __traits(code, ...) and/or .codeof
So the discussions about Attributes and Aspect Oriented Programming (AOP) got me thinking... Basically AOP requires injecting code fragments together in a comprehensible way. Similarly, Attributes that go beyond @note (such as @GC.NoScan) need similar ability. D already has the ability to mixin arbitrary code fragments at compile time, and to process those in useful ways through CTFE. Which rocks. What it lacks is the ability to reflect upon the actual source code due to IO limitations of CTFE. So creating a mixin templates which pieces together a unique object is, to my knowledge, currently next to impossible (and slow since you'd have to parse and isolate code in .d file multiple times in a separate process, then compile again to put it all together). So, to quote Walter, what compelling features would it bring? Here's an example of a simple AOP program from the AOP wiki page (probably not the best implementation, but the concept is there): struct BankType { void transfer() { ... } void getMoneyBack() { ... } } struct Logger { void transfer() { log("transferring money..."); } void getMoneyBack() { log("User requested money back"); } } and now some magic... string bankCode(T...)(T aspects) { auto code = "struct Bank {"; auto members = [__traits(allMembers, Bank)]; foreach (m; members) { code ~= "void "~m~"() {"; code ~= __traits(getMember, Bank, m).codeof; foreach (a; aspects) { if (__traits(hasMember, a, m) { code ~= __traits(getMember, a, m).codeof; } } code ~= "}" } return code ~ "}"; } mixin template Bank(T...) { mixin(bankCode(T)); } mixin Bank!Logger; void main() { auto b = Bank(); b.transfer(); // logs b.getMoneyBack(); // ditto } So this would allow us to make "Compilers" within the Compiler (Codeception), since we could parse/strip/append any existing code fragments together in endless combination. Generic "Builders" could probably be built and put into a std.builder lib for general use. One particular use I have in mind is for Behavior Objects (Game Scripts). Each behavior would hold Property(T) objects which define per-property, per-state "binding" dependencies (eg. position.x.bind(other.x, State.Idle)) and execution code. On release, the Property(T) object would be stripped away (leaving just T) and it's behavior code "compressed" with others into optimized functions. I don't know much about the internals of DMD, so I'm not sure this is a realistic request, but I think the idea is compelling. Also, for Attributes I'm not sure this technique is really applicable. But it's possible that the compiler could exploit this internally for certain Attributes like @GC.whatever
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 03:48:24PM +0100, Andrej Mitrovic wrote: > On 3/22/12, H. S. Teoh wrote: > > This is because in aaA.d _aaGetX creates a new entry if one isn't found, > > but because it has no direct access to value types (only has typeinfo), > > it doesn't know what value .init has. It sets the value to binary zero > > by default. > > Damn, hashes really are a terrible hack. I'm really looking forward to > your new implementation. You can check out the current code here: https://github.com/quickfur/New-AA-implementation You can just import newAA. Obviously it's not integrated with druntime/dmd yet, so it doesn't have the nice V[K] or literal syntax. But you can use it as AssociativeArray!(K,V). There's also a fromLiteral static method that you can use to simulate literals (I'm considering making it a module function instead of a static method, though). It should work like the current implementation, for the most part, except for some outstanding issues I'm working on. Actually, it would be nice if people gave me some feedback on how well the current implementation works. :-) I may not be aware of all the issues that need fixing. T -- Life is complex. It consists of real and imaginary parts. -- YHL
Re: Wrong lowering for a[b][c]++
On 3/22/12, H. S. Teoh wrote: > You can check out the current code here: > > https://github.com/quickfur/New-AA-implementation I need Git Head (2.059) for this, right? Otherwise I get: newAA.d(426): Error: inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')
Re: Proposal: __traits(code, ...) and/or .codeof
ps. Mono-C#'s NRefactory, and Microsoft .Net's forthcoming Roslyn Project are the only comparable infrastructures I can think of with this level of reflection, and they're the foundation to some pretty innovative new development tools. NRefactory: http://wiki.sharpdevelop.net/NRefactory.ashx Roslyn: http://msdn.microsoft.com/en-us/vstudio/hh500769
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 05:52:54PM +0100, Andrej Mitrovic wrote: > On 3/22/12, H. S. Teoh wrote: > > You can check out the current code here: > > > > https://github.com/quickfur/New-AA-implementation > > I need Git Head (2.059) for this, right? Otherwise I get: > newAA.d(426): Error: inout on parameter means inout must be on return > type as well (if from D1 code, replace with 'ref') Probably. I've been developing on 2.059 so I didn't realize there are incompatibilities with earlier versions. T -- People tell me that I'm paranoid, but they're just out to get me.
Re: Wrong lowering for a[b][c]++
On Thu, 22 Mar 2012 15:35:06 +0100, H. S. Teoh wrote: On Thu, Mar 22, 2012 at 03:26:00PM +0100, Andrej Mitrovic wrote: On 3/22/12, Jesse Phillips wrote: > double[int] a; > What is the result of your code on 'a' now? double.init is NAN. Hmm this is interesting. With 2.058: double[int] a; a[0]++; writeln(a[0]); // prints 1 double b; b++; writeln(b); // prints nan This is because in aaA.d _aaGetX creates a new entry if one isn't found, but because it has no direct access to value types (only has typeinfo), it doesn't know what value .init has. It sets the value to binary zero by default. TypeInfos have a ubyte[] array with the needed data. It's badly named though. rdmd --eval="writeln(typeid(double).init)" But the AA doesn't have access to the typeinfo of the value anyhow.
Re: Proposal: __traits(code, ...) and/or .codeof
On Thursday, 22 March 2012 at 16:55:34 UTC, F i L wrote: ps. Mono-C#'s NRefactory, and Microsoft .Net's forthcoming Roslyn Project are the only comparable infrastructures I can think of with this level of reflection, and they're the foundation to some pretty innovative new development tools. NRefactory: http://wiki.sharpdevelop.net/NRefactory.ashx Roslyn: http://msdn.microsoft.com/en-us/vstudio/hh500769 Even if I'm closer to the opposite of a MS-evangelist... color me impressed, I like your idea. +1.
Re: Wrong lowering for a[b][c]++
On 3/22/12, H. S. Teoh wrote: > Probably. I've been developing on 2.059 so I didn't realize there are > incompatibilities with earlier versions. Your test files work ok. I'll test it on my own projects as soon as I get rid of a few compilation errors (all of a sudden I get 900 error lines for failed template instantiations, LOL).
Re: opEquals/opCmp returning other types
On Thursday, 22 March 2012 at 10:06:46 UTC, Don Clugston wrote: Indeed, it may be possible to use a new-style delegate literal instead of a string, for defining your DSL. My point was that we don't need to be able to return arbitrary types from operators. Instead, we might need some syntax sugar or library support for getting syntax trees from expressions. And how exactly do you plan to implement _library_ support for that in the case of expressions containing comparison or equality operators? David
Re: public MessageBox
On Mar 22, 2012, at 8:49 AM, David Nadlinger wrote: > On Thursday, 22 March 2012 at 00:30:51 UTC, Nathan M. Swan wrote: >> As I posted a while back, the concept of a variant message queue is >> wonderful and powerful, and the implementation is great. But the fact that >> you can't declare "auto mq = new MessageQueue()" is a gaping whole in an >> otherwise A+ API. > > Nice to hear that I'm not alone with that opinion – I hit the same problem > when implementing a request log file writer for Thrift, which runs in a > separate thread and communicates with the main thread via a message queue. > > It works great and performed even better than a similar C++ version due to > lower lock contention, but the user'd better not try to call receiveOnly!() > from »his« thread… And this is why I've never used receiveOnly. A simple way to receive a specific message type is great, but throwing if there's anything else in the queue isn't generally what you want, as it assumes complete knowledge of all messages received by the application. Perhaps what's needed here is something semantically like receiveOnly that doesn't throw?
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 06:43:29PM +0100, Andrej Mitrovic wrote: > On 3/22/12, H. S. Teoh wrote: > > Probably. I've been developing on 2.059 so I didn't realize there > > are incompatibilities with earlier versions. > > Your test files work ok. I'll test it on my own projects as soon as I > get rid of a few compilation errors (all of a sudden I get 900 error > lines for failed template instantiations, LOL). Yeah that's probably caused by a recent dmd change to soldier on after a template instantiation error. :-) Some template instantiation problems are my fault, though. There are still some AA's that don't instantiate correctly. Please let me know any that you find, 'cos they need to be fixed. T -- The peace of mind---from knowing that viruses which exploit Microsoft system vulnerabilities cannot touch Linux---is priceless. -- Frustrated system administrator.
Re: Wrong lowering for a[b][c]++
On 3/22/12, Andrej Mitrovic wrote: > Your test files work ok. Well unfortunately isAssociativeArray from std.traits fails on your hashes (reasonable, since it calls __traits internally and has no way of knowing about external hashes). I also can't use your hashes with some helper functions that I use: template ValueType(V : V[K], K) { alias V ValueType; } The function that needs the above is: void addKey(AA, Key)(ref AA hash, Key key) if (isAssociativeArray!AA && is(KeyType!AA == Key)) { hash[key] = (ValueType!AA).init; } I can temporarily remove those constraints, but how do I extract the value type of your hash?
Re: Wrong lowering for a[b][c]++
On 3/22/12, H. S. Teoh wrote: > Yeah that's probably caused by a recent dmd change to soldier on after a > template instantiation error. :-) Hopefully that gets fixed by the next release. Otherwise we can expect an angry dev creating a D FQA site, heheh. :P
Re: Proposal: __traits(code, ...) and/or .codeof
in addition to .codeof, let's think about .astof returning an abstract syntax tree.
Re: Proposal: __traits(code, ...) and/or .codeof
On Thursday, 22 March 2012 at 18:06:24 UTC, Felix Hufnagel wrote: in addition to .codeof, let's think about .astof returning an abstract syntax tree. I agree, as stated on the IRC, .astof (and therefor .astof.toString()) is a much better concept.
Re: Proposal: __traits(code, ...) and/or .codeof
On Thursday, 22 March 2012 at 18:06:24 UTC, Felix Hufnagel wrote: in addition to .codeof, let's think about .astof returning an abstract syntax tree. I haven't really looked at DMD's AST structure, but I assume we could just duplicate that minus any CTFE stuff or codegen stuff.
Re: getHash inconsistency
On Wed, Mar 21, 2012 at 04:35:11PM +1100, Daniel Murphy wrote: > "H. S. Teoh" wrote in message > news:mailman.951.1332306541.4860.digitalmar...@puremagic.com... > > > > Here's the current hashing code for char[] and string: > > > >foreach (char c; s) > >hash = hash * 11 + c; > > > > For const(char)[], it's rt.util.hash.hashOf, which is Paul Hsieh's > > SuperFastHash algorithm with very good hash distribution properties. > > It does seem to involve a lot more operations that the simple loop > > above, though; so I assume the above simple loop was chosen because > > hashing strings are a very common operation and, for the most part, > > only need a simple hash function. > > > > So I'm kinda leaning towards SuperFastHash, but worried about > > whether it will cause performance degradation, in which case we > > should stick with the simple loop. [...] > Benchmark time! Alright, so after some benchmarking, I found that the above custom hash function works best for *short* (3 to 10 character) randomized alphabetic strings (I assumed alphabetic to be the typical use case of strings). It's faster than SuperFastHash, and even has better distribution properties, probably because SuperFastHash is tuned for arbitrary binary data of arbitrary length, whereas the custom function is tuned for short string-like data. With longer strings, SuperFastHash beats the custom algorithm, and distribution properties are approximately the same. So I'm still on the fence about which algorithm is better. I can see why the custom hash was adopted for strings, since your typical AA tends to have short alphabetic keys, and something like SuperFastHash is probably overkill. But for longer keys, SuperFastHash is better. T -- Curiosity kills the cat. Moral: don't be the cat.
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 07:04:09PM +0100, Andrej Mitrovic wrote: > On 3/22/12, Andrej Mitrovic wrote: > > Your test files work ok. > > Well unfortunately isAssociativeArray from std.traits fails on your > hashes (reasonable, since it calls __traits internally and has no way > of knowing about external hashes). > > I also can't use your hashes with some helper functions that I use: > > template ValueType(V : V[K], K) { > alias V ValueType; > } > > The function that needs the above is: > > void addKey(AA, Key)(ref AA hash, Key key) > if (isAssociativeArray!AA && is(KeyType!AA == Key)) > { > hash[key] = (ValueType!AA).init; > } > > I can temporarily remove those constraints, but how do I extract the > value type of your hash? Hmm. Perhaps some aliases are in order? struct AssociativeArray(K,V) { ... alias Key keytype; alias Value valuetype; ... } Presumably this won't be an issue once it's integrated with dmd. But these aliases might be useful for other things, too. T -- "You know, maybe we don't *need* enemies." "Yeah, best friends are about all I can take." -- Calvin & Hobbes
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 11:21:43AM -0700, H. S. Teoh wrote: [...] > Hmm. Perhaps some aliases are in order? > > struct AssociativeArray(K,V) { > ... > alias Key keytype; > alias Value valuetype; > ... > } [...] OK, I've added these aliases and pushed to github. I think they're a useful thing to have. If not, it's easy to remove before we integrate with druntime. But at least in the meantime it will make these AA's easier to work with. T -- Bomb technician: If I'm running, try to keep up.
Re: Wrong lowering for a[b][c]++
On 3/22/12, H. S. Teoh wrote: > OK, I've added these aliases and pushed to github. I think they're a > useful thing to have. If not, it's easy to remove before we integrate > with druntime. But at least in the meantime it will make these AA's > easier to work with. Could you also add an enum to the template like so:? struct AssociativeArray(Key,Value) { enum isAssociativeArray = true; ... } I've realized that by just removing constraints I'm ending up with a lot of conflicts (doh!), but I can implement a custom template that checks for this enum field instead.
Re: What about putting array.empty in object.d?
On Thursday, March 22, 2012 07:12:22 Steven Schveighoffer wrote: > Note that the default std::list has O(1) length (as does dcollections' > LinkedList). It's not as inevitable as you think. It depends on bothe container its implementation as to how efficient length/size is (and in the case of linked lists, it's generally a question of whether you want splicing to be efficient or size/length to be efficient). But you don't have to worry about how efficient length/size's implementation is when checking whether a container is empty if you just always use empty rather than length == 0, so it's a good habit to get into. There's generally no advantage to using length == 0 over empty. There's a slight advantage with D and arrays only in that empty isn't built into arrays, so you have to import std.array to use empty, and empty is just a wrapper around length == 0, which will then be _slightly_ less efficient without -inline, but I'd still argue for using empty, because it avoids the whole issue of length/size's efficiency. Regardless, fortunately, it's not as big an issue in D as in C++ thanks to the fact that Phobos defines length to be O(1) - and it's good that dcollections does the same. - Jonathan M Davis
Re: Proposal: __traits(code, ...) and/or .codeof
Am 22.03.2012 19:06, schrieb Felix Hufnagel: in addition to .codeof, let's think about .astof returning an abstract syntax tree. Would this not require something similar to the expression trees in .NET? http://msdn.microsoft.com/en-us/library/bb397951.aspx -- Paulo
Re: getHash inconsistency
On Mar 20, 2012, at 10:10 PM, H. S. Teoh wrote: > On Wed, Mar 21, 2012 at 03:55:49PM +1100, Daniel Murphy wrote: >> "H. S. Teoh" wrote in message >> news:mailman.917.1332250604.4860.digitalmar...@puremagic.com... > [...] >>> Then the question is, what should be the fix? >>> >>> Currently, char[] and string have getHash defined in >>> rt.typeinfo.ti_Ad.TypeInfo_Aa, which appears to be a custom hashing >>> algorithm, whereas const(char)[] uses TypeInfo_Array.getHash, which >>> uses rt.util.hash.hashOf. Which one should be used? > [...] >> >> I assume the custom hashing routine is better/faster? If so, that >> one. I'd assume that getHash not working the same for const strings >> is an oversight. > [...] > > Here's the current hashing code for char[] and string: > >foreach (char c; s) >hash = hash * 11 + c; > > For const(char)[], it's rt.util.hash.hashOf, which is Paul Hsieh's > SuperFastHash algorithm with very good hash distribution properties. It > does seem to involve a lot more operations that the simple loop above, > though; so I assume the above simple loop was chosen because hashing > strings are a very common operation and, for the most part, only need a > simple hash function. > > So I'm kinda leaning towards SuperFastHash, but worried about whether it > will cause performance degradation, in which case we should stick with > the simple loop. The thing with hashes is that you usually gain more by getting a good distribution than you lose by computing the hash. Our AA implementation should probably store the computed hash value per node if it isn't already though, so we can compare against that before doing opEquals when looking up a node, and so it's available when rehashing.
Re: Proposal: __traits(code, ...) and/or .codeof
Am 22.03.2012 18:34, schrieb CTFE-4-the-win: On Thursday, 22 March 2012 at 16:55:34 UTC, F i L wrote: ps. Mono-C#'s NRefactory, and Microsoft .Net's forthcoming Roslyn Project are the only comparable infrastructures I can think of with this level of reflection, and they're the foundation to some pretty innovative new development tools. NRefactory: http://wiki.sharpdevelop.net/NRefactory.ashx Roslyn: http://msdn.microsoft.com/en-us/vstudio/hh500769 Even if I'm closer to the opposite of a MS-evangelist... color me impressed, I like your idea. +1. Same here. Microsoft R&D does lots of cool stuff actually, pity that sometimes they get it so wrong, due to the way the management/marketing works. -- Paulo
Re: getHash inconsistency
On 3/22/12 1:18 PM, H. S. Teoh wrote: Alright, so after some benchmarking, I found that the above custom hash function works best for *short* (3 to 10 character) randomized alphabetic strings (I assumed alphabetic to be the typical use case of strings). It's faster than SuperFastHash, and even has better distribution properties, probably because SuperFastHash is tuned for arbitrary binary data of arbitrary length, whereas the custom function is tuned for short string-like data. With longer strings, SuperFastHash beats the custom algorithm, and distribution properties are approximately the same. So I'm still on the fence about which algorithm is better. I can see why the custom hash was adopted for strings, since your typical AA tends to have short alphabetic keys, and something like SuperFastHash is probably overkill. But for longer keys, SuperFastHash is better. Note that you can switch the actual algorithm depending on string length. Andrei
Re: Wrong lowering for a[b][c]++
> On 3/22/12, H. S. Teoh wrote: > snip Hmm, what about (temporary) compatibility with hash literals? You could add the following to the newAA module: static import std.traits; template KeyType(V : V[K], K) { alias K KeyType; } template ValueType(V : V[K], K) { alias V ValueType; } and in the AssociativeArray struct: void opAssign(AA)(AA aa) if (std.traits.isAssociativeArray!AA && is(KeyType!AA == keytype) && is(ValueType!AA == valuetype)) { foreach (key, val; aa) this[key] = val; } Then this will work: AA!(int, string) intToStr; intToStr = [1:"foo"]; assert(intToStr[1] == "foo"); Otherwise it will be pretty hard to test the new hashes without changing a significant amount of code.
Re: getHash inconsistency
On Mar 22, 2012, at 11:18 AM, H. S. Teoh wrote: > On Wed, Mar 21, 2012 at 04:35:11PM +1100, Daniel Murphy wrote: >> "H. S. Teoh" wrote in message >> news:mailman.951.1332306541.4860.digitalmar...@puremagic.com... >>> >>> Here's the current hashing code for char[] and string: >>> >>> foreach (char c; s) >>> hash = hash * 11 + c; >>> >>> For const(char)[], it's rt.util.hash.hashOf, which is Paul Hsieh's >>> SuperFastHash algorithm with very good hash distribution properties. >>> It does seem to involve a lot more operations that the simple loop >>> above, though; so I assume the above simple loop was chosen because >>> hashing strings are a very common operation and, for the most part, >>> only need a simple hash function. >>> >>> So I'm kinda leaning towards SuperFastHash, but worried about >>> whether it will cause performance degradation, in which case we >>> should stick with the simple loop. > [...] >> Benchmark time! > > Alright, so after some benchmarking, I found that the above custom hash > function works best for *short* (3 to 10 character) randomized > alphabetic strings (I assumed alphabetic to be the typical use case of > strings). It's faster than SuperFastHash, and even has better > distribution properties, probably because SuperFastHash is tuned for > arbitrary binary data of arbitrary length, whereas the custom function > is tuned for short string-like data. > > With longer strings, SuperFastHash beats the custom algorithm, and > distribution properties are approximately the same. > > So I'm still on the fence about which algorithm is better. I can see why > the custom hash was adopted for strings, since your typical AA tends to > have short alphabetic keys, and something like SuperFastHash is probably > overkill. But for longer keys, SuperFastHash is better. Might be worth plugging in MurmurHash for comparison.
Re: Proposal for a MessageQueue (was Re: public MessageBox)
On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote: I can see adapting the API so that each thread has a default message queue (keep in mind that we'll be adding interprocess messaging at some point via the same routines). I'm not yet clear how the existence of alternate message queues could be communicated to other portions of the code though. register() is one way I suppose. Really what's happening here is that Tid is being replaced by a queue ID, not extended with a mutable variable. I think they would be passed as parameters to spawn or received from the default message queue. I guess Tid would become an alias for the Qid created when a thread is spawned. What I really don't want though, is for receive() to operate on a message queue created in a different thread. Messaging would become substantially slower if receive() had to be synchronized. That's a drawback I haven't considered. To solve this, it would be made part of the contract that receiving must all be done in one thread. I can't think of a use where receiving in multiple threads would apply, but if it would, a SynchronizedMessageQueue subclass could easily be drawn up that broadens the contract and synchronizes for receive(). BTW, how do you unittest just the std.concurrency module?
Re: Proposal: __traits(code, ...) and/or .codeof
On 03/22/2012 07:08 PM, F i L wrote: On Thursday, 22 March 2012 at 18:06:24 UTC, Felix Hufnagel wrote: in addition to .codeof, let's think about .astof returning an abstract syntax tree. I agree, as stated on the IRC, .astof (and therefor .astof.toString()) is a much better concept. I think that would necessitate the addition of AST macros.
Re: Proposal: __traits(code, ...) and/or .codeof
Timon Gehr wrote: I think that would necessitate the addition of AST macros. You mean passing DMD's actual AST tree object? Only a stripped down version?
Re: Wrong lowering for a[b][c]++
On 22/03/12 18:43, Andrej Mitrovic wrote: On 3/22/12, H. S. Teoh wrote: Probably. I've been developing on 2.059 so I didn't realize there are incompatibilities with earlier versions. Your test files work ok. I'll test it on my own projects as soon as I get rid of a few compilation errors (all of a sudden I get 900 error lines for failed template instantiations, LOL). Please report them as bugs. I know of one situation where that happens, but I'm sure there are more. I want to get to the point where there is exactly one error message for each bug in your code. Previously the compiler was cheating by calling exit() as soon as it got ANY template error, but the cheating also caused subtle bugs, because it can't abort if errors are gagged.
Re: Three Unlikely Successful Features of D
"Adam D. Ruppe" wrote in message news:oyqxvngsgjfmrlrwh...@forum.dlang.org... > On Thursday, 22 March 2012 at 04:49:24 UTC, Nick Sabalausky wrote: >> And then later on someone made sort of a mini file-system where you could >> add data to a ROM >> image and then query/access it from your code > > Now, this reminds me, what if you want to access the > compile time files from runtime? > > For instance, one of my projects lets you include other > files in the html. (Something I actually don't like, but > it is an easy crutch.) > > You can also replace these at runtime, so the other team > members can change stuff without access to the compiler. > > Here's what I ended up writing: > > > // filesystem alternatives... > string getFile(string name)() { > if(std.file.exists(dir ~ name)) > return std.file.readText(dir ~ name); > else > return import(name); > } > > // runtime fetching > string getIncludeFile(string name) { > enum manifest = ["file1.html", "file2.html", ..]; > string manifests() { > string cases; > foreach(f; manifest) > cases ~= "case \""~f~"\": return getFile!(\""~f~"\");"; > return cases; > } > switch(name) { > default: assert(0, name); > mixin(manifests()); > } > } > > > > I'm a bit disappointed that I needed a list of files duplicated > there. With import(), if it is in the import directory, it just > works, but then the name must be known at compile time. > > > This is the best I have so far... and i like it, > but it isn't quite ideal yet. Clever idea, I like it.
D + Arduino
Hey all, i'm not sure who would be the right person on this, but a good Google Summer of Code project would be to get D programs running on Arduino. There's already been work done with MonoDevelop to get .NET MF code to deploy via MonoDevelop on Netduino. And there's a D Language plugin for MonoDevelop, so maybe they could leverage both those things, put them together and get a pipeline for creating D stuff in MonoDevelop, then deploying to Arduino. would be awesome. Does the D community participate in Google Summer of Code? The Mono team does, and we've had some awesome contributions to Mono from summer of code kids.
Workaround for Issue 6906
It appears I'm running into issue 6906, meaning it's impossible to store structs in an AA if they have opAssign defined. For example: struct S { }
Re: D + Arduino
i found the GSOC page for D and added it as a possible project.
Re: Workaround for Issue 6906
On Thursday, 22 March 2012 at 20:08:02 UTC, Rene Zwanenburg wrote: It appears I'm running into issue 6906, meaning it's impossible to store structs in an AA if they have opAssign defined. For example: struct S { } Apologies, sent before I finished. Tab + enter in the web interface. struct S { void opAssign(S s) { // for the AA assign, 'this' is invalid here } } S[int] sAA; sAA[1] = S(); Is there a workaround? I'm storing smart pointers in an AA, the combination incorrect this + reference counting destructor is fatal.
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 07:55:09PM +0100, Andrej Mitrovic wrote: [...] > Hmm, what about (temporary) compatibility with hash literals? You > could add the following to the newAA module: > > static import std.traits; > template KeyType(V : V[K], K) > { > alias K KeyType; > } > > template ValueType(V : V[K], K) > { > alias V ValueType; > } Done, pushed to github. > and in the AssociativeArray struct: > void opAssign(AA)(AA aa) > if (std.traits.isAssociativeArray!AA > && is(KeyType!AA == keytype) > && is(ValueType!AA == valuetype)) > { > foreach (key, val; aa) > this[key] = val; > } Done, though this required another opAssign() to replace the default one that got suppressed by this template. Which required some nasty const casts to work properly, but at least D lets you do that when you need to. :-) > Then this will work: > > AA!(int, string) intToStr; > intToStr = [1:"foo"]; > assert(intToStr[1] == "foo"); > > Otherwise it will be pretty hard to test the new hashes without > changing a significant amount of code. True. I still can't get this to work though: AA!(string,int) aa = ["abc":123]; Maybe this needs a ctor? T -- Almost all proofs have bugs, but almost all theorems are true. -- Paul Pedersen
Windows Socket Timeout
Hi, I'm trying to write a game sever/client architecture in D, but I keep running into problems with the timeouts for windows sockets. On the std.socket documentation page it states that you can't set a timeout smaller than 500ms, and I've been experiencing this problem first hand. The problem is that I am trying to interlace sending packets with receiving packets, and I can't do that at 60 FPS without having a low timeout. Two questions: First, can you use select() on UDP sockets? Second, would it be feasible to have two different sockets instead, and use the REUSEADDR option? I'm somewhat worried about client-side cheating. Thanks for any thoughts, Evan Davis
Re: Three Unlikely Successful Features of D
On Wednesday, 21 March 2012 at 19:11:08 UTC, Nick Sabalausky wrote: Although, while it wasn't a major selling point in and of itself, the ability to put underscores in numeric literals *really* helped tell me, "Now *this* is a language that's very well thought out and values pragmatism." And *that* was the other main thing about D that grabbed me. I take that feature for granted! Try using it in other languages and am always taken back on what it is complaining about, its just a stupid integer literal... oh.
Re: Wrong lowering for a[b][c]++
On 3/22/12, H. S. Teoh wrote: > Maybe this needs a ctor? Yeah probably. I really don't know when opAssign or the ctor are called (especially with more complex types with alias this). Maybe someone knows this or it's in the spec but I haven't read about it.
Re: Proposal for a MessageQueue (was Re: public MessageBox)
On Mar 22, 2012, at 12:06 PM, "Nathan M. Swan" wrote: > On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote: >> I can see adapting the API so that each thread has a default message queue >> (keep in mind that we'll be adding interprocess messaging at some point via >> the same routines). I'm not yet clear how the existence of alternate message >> queues could be communicated to other portions of the code though. >> register() is one way I suppose. Really what's happening here is that Tid is >> being replaced by a queue ID, not extended with a mutable variable. > > I think they would be passed as parameters to spawn or received from the > default message queue. But will either of those solve the problem you outlined where user code is calling receiveOnly and bumping into a message meant for a third-party API? If the API is spawning threads they typically won't be running user code, or at least would certainly impose restrictions on message queue use by called user code. And in the case of sending the Qid to the default queue, you end up with a race condition where user code might call receiveOnly. >> I guess Tid would become an alias for the Qid created when a thread is >> spawned. What I really don't want though, is for receive() to operate on a >> message queue created in a different thread. Messaging would become >> substantially slower if receive() had to be synchronized. > > That's a drawback I haven't considered. To solve this, it would be made part > of the contract that receiving must all be done in one thread. > > I can't think of a use where receiving in multiple threads would apply, but > if it would, a SynchronizedMessageQueue subclass could easily be drawn up > that broadens the contract and synchronizes for receive(). > > BTW, how do you unittest just the std.concurrency module? Not easily, since a failure often means that a thread hangs.
Re: Proposal: __traits(code, ...) and/or .codeof
On 03/22/2012 08:12 PM, F i L wrote: Timon Gehr wrote: I think that would necessitate the addition of AST macros. You mean passing DMD's actual AST tree object? Only a stripped down version? We have the macro keyword. I envision something like: macro replaceAggregate(macro newAggregate, macro loop : foreach(x; aggr){statements}, macro x, macro aggr, macro statements) { foreach(x; newAggregate){statements} } void main(){ int[] a = [1,2,3]; int[] b = [2,3,4]; replaceAggregate(b, foreach(x;a){writeln(x);}); } (The syntax looks horrible, but you get the idea: AST walking by pattern matching) Ideally, such macros would allow introducing local helper variables inside the macro that are not accessible from outside and introducing variables/enums in the context the macro is used. (prefixing identifiers that should interfere with the enclosing context with $ would be an option). Another idea: macro someFancyDSL(string dsl){ mixin(someFancyDSLtoD(dsl); } void main(){ int n = 5; someFancyDSL { import n; let x = 1 : x let y = product (take n) x export y; } writeln(y); } // this would also enable less fancy but useful stuff: macro until(macro condition, string str){ while(!condition){ mixin(str); // string and mixin not strictly necessary, // maybe enable the feature on macro params too } } void main(){ bool done = false; int x; until(done){ done = foo(x++); } } This is just a very rough sketch though, we would need a much more refined design. I think getting the symbol scoping right is most important.
Re: Proposal for a MessageQueue (was Re: public MessageBox)
On Thursday, 22 March 2012 at 21:27:40 UTC, Sean Kelly wrote: On Mar 22, 2012, at 12:06 PM, "Nathan M. Swan" wrote: On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote: I can see adapting the API so that each thread has a default message queue (keep in mind that we'll be adding interprocess messaging at some point via the same routines). I'm not yet clear how the existence of alternate message queues could be communicated to other portions of the code though. register() is one way I suppose. Really what's happening here is that Tid is being replaced by a queue ID, not extended with a mutable variable. I think they would be passed as parameters to spawn or received from the default message queue. But will either of those solve the problem you outlined where user code is calling receiveOnly and bumping into a message meant for a third-party API? If the API is spawning threads they typically won't be running user code, or at least would certainly impose restrictions on message queue use by called user code. And in the case of sending the Qid to the default queue, you end up with a race condition where user code might call receiveOnly. But what if the client spawns threads? An example would be with a desktop GUI. In a background thread meant for a CPU-intensive task, they want to update a progress indicator and send partially-calculated data to a main-thread. void mainThread() { string data; auto mq = new MessageQueue(); spawn(&backgroundThread, mq, pi); pi.onChange = (double val) { if (val == 0.5) { data = me.receiveOnly!string(); } else { data ~= me.receiveOnly!string(); } }; } void backgroundThread(MessageQueue me, ProgressIndicator pi) { // part 1 of calculations... me.send(partiallyCalculatedData); pi.value = 0.5; // implementation: this._queue.send(UpdateValue(value)) // part 2... me.send(theRestOfTheData); pi.value = 1.0; } With one MessageQueue per thread, the mailbox would contain a (string, UpdateValue, string, UpdateValue). The mainThread would expect a (UpdateValue, string, UpdateValue, string). This way, the client code is separated from the library. The default queue is an idea suggested for backward compatibility, and new programmers wouldn't be encouraged to use it. I guess Tid would become an alias for the Qid created when a thread is spawned. What I really don't want though, is for receive() to operate on a message queue created in a different thread. Messaging would become substantially slower if receive() had to be synchronized. That's a drawback I haven't considered. To solve this, it would be made part of the contract that receiving must all be done in one thread. I can't think of a use where receiving in multiple threads would apply, but if it would, a SynchronizedMessageQueue subclass could easily be drawn up that broadens the contract and synchronizes for receive(). BTW, how do you unittest just the std.concurrency module? Not easily, since a failure often means that a thread hangs. Linking fails (I'm on OSX): $ rdmd --main -unittest std/concurrency.d Undefined symbols for architecture x86_64: "_D3std3utf10strideImplFNaNeamZk", referenced from: _D3std3utf15__T6strideTAxaZ6strideFNaNfxAamZk in concurrency.d.o _D3std3utf14__T6strideTAaZ6strideFNaNfxAamZk in concurrency.d.o _D3std3utf15__T6strideTAyaZ6strideFNaNfxAyamZk in concurrency.d.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status --- errorlevel 1 Thanks, NMS
Re: Proposal: __traits(code, ...) and/or .codeof
Timon Gehr wrote: We have the macro keyword. I envision something like: macro replaceAggregate(macro newAggregate, macro loop : foreach(x; aggr){statements}, macro x, macro aggr, macro statements) { foreach(x; newAggregate){statements} } void main(){ int[] a = [1,2,3]; int[] b = [2,3,4]; replaceAggregate(b, foreach(x;a){writeln(x);}); } (The syntax looks horrible, but you get the idea: AST walking by pattern matching) This looks substantially more complicated than what I had in mind. I think it's a great idea, but something that could be added after the initial functionality was there. macro until(macro condition, string str){ while(!condition){ mixin(str); // string and mixin not strictly necessary, // maybe enable the feature on macro params too } } void main(){ bool done = false; int x; until(done){ done = foo(x++); } } This is just a very rough sketch though, we would need a much more refined design. I think getting the symbol scoping right is most important. I'm a bit confused about what's actually going on here, but it certainly looks interesting. What exactly is being passed to "string str" in the macro?
Re: Windows Socket Timeout
Am 22.03.2012 22:09, schrieb Evan Davis: Hi, I'm trying to write a game sever/client architecture in D, but I keep running into problems with the timeouts for windows sockets. On the std.socket documentation page it states that you can't set a timeout smaller than 500ms, and I've been experiencing this problem first hand. The problem is that I am trying to interlace sending packets with receiving packets, and I can't do that at 60 FPS without having a low timeout. Two questions: First, can you use select() on UDP sockets? Second, would it be feasible to have two different sockets instead, and use the REUSEADDR option? I'm somewhat worried about client-side cheating. Thanks for any thoughts, Evan Davis If you really want performant sockets on Windows, you need to make use of the Windows specific APIs, and use IO completion ports not select. -- Paulo
Re: Proposal: user defined attributes
Le 22/03/2012 03:05, Andrei Alexandrescu a écrit : On 3/21/12 6:02 PM, deadalnix wrote: Le 21/03/2012 17:22, Andrei Alexandrescu a écrit : On 3/21/12 11:17 AM, Timon Gehr wrote: On 03/20/2012 10:36 PM, deadalnix wrote: Even the propagation of pure, @safe, nothrow and const that has been discussed recently can be done with that feature. I'm sceptical. How would that work exactly? I, too, am highly skeptical. For one thing these attributes must be made part of the type and have deep connections with code semantics. Andrei That is the point. The property must be able to manipulate what is qualified. This is the point of AOP. Problem is you'd need a ton of hooks to e.g. prevent mutation in const methods, or do attribute inference as the compiler does now. If you let me some time, I could write a proposal. BTW, this is probably something we don't want to rush in, but I'm sure it definitively worth it. Honest, I have zero enthusiasm for adding AOP to D right now. But I agree it would be an interesting project to see what it would take to implement something of the power of pure or const starting from zero knowledge. I think we have a misunderstanding here. I wasn't talking about reimplementing const or pure. I was talking about propagating them to overriden method (a way more easier task). I was talking about implementing the recently discussed behavior of override, not actually reimplementing const or pure. Not that that wouldn't be possible, but it would require a massive amount of work and a very cooperative compiler. Inference isn't possible with an attribute system. This is less impressive, but more realistic goal. And that is quite easy to achieve. Have you seen what a project like lombok can do ? This? http://projectlombok.org/ I'll take a look, thanks. Yes.
Re: Windows Socket Timeout
On Thursday, 22 March 2012 at 23:36:03 UTC, Paulo Pinto wrote: If you really want performant sockets on Windows, you need to make use of the Windows specific APIs, and use IO completion ports not select. Depending on what you are trying to achieve, you could always consider using enet or (parts of) RakNet. David
Re: Proposal for a MessageQueue (was Re: public MessageBox)
On Mar 22, 2012, at 4:01 PM, Nathan M. Swan wrote: > On Thursday, 22 March 2012 at 21:27:40 UTC, Sean Kelly wrote: >> On Mar 22, 2012, at 12:06 PM, "Nathan M. Swan" wrote: >> >>> On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote: I can see adapting the API so that each thread has a default message queue (keep in mind that we'll be adding interprocess messaging at some point via the same routines). I'm not yet clear how the existence of alternate message queues could be communicated to other portions of the code though. register() is one way I suppose. Really what's happening here is that Tid is being replaced by a queue ID, not extended with a mutable variable. >>> I think they would be passed as parameters to spawn or received from the >>> default message queue. >> >> But will either of those solve the problem you outlined where user code is >> calling receiveOnly and bumping into a message meant for a third-party API? >> If the API is spawning threads they typically won't be running user code, or >> at least would certainly impose restrictions on message queue use by called >> user code. And in the case of sending the Qid to the default queue, you end >> up with a race condition where user code might call receiveOnly. >> > > But what if the client spawns threads? > > An example would be with a desktop GUI. In a background thread meant for a > CPU-intensive task, they want to update a progress indicator and send > partially-calculated data to a main-thread. > > void mainThread() { >string data; >auto mq = new MessageQueue(); >spawn(&backgroundThread, mq, pi); >pi.onChange = (double val) { >if (val == 0.5) { >data = me.receiveOnly!string(); >} else { >data ~= me.receiveOnly!string(); >} >}; > } > > void backgroundThread(MessageQueue me, ProgressIndicator pi) { >// part 1 of calculations... >me.send(partiallyCalculatedData); >pi.value = 0.5; // implementation: this._queue.send(UpdateValue(value)) >// part 2... >me.send(theRestOfTheData); >pi.value = 1.0; > } > > With one MessageQueue per thread, the mailbox would contain a (string, > UpdateValue, string, UpdateValue). The mainThread would expect a > (UpdateValue, string, UpdateValue, string). While sending messages like a bare string might be good for example code, any real application is going to use structured messages whose type is specific to what the message is for, contains fields like sender Tid, etc. It seems like you're aiming more for CSP where you'd create a separate communication channel per use. You could even fake it by wrapping send/receive with your own CSP-like API, though it's quite likely that a from-scratch CSP style implementation would be faster because there'd be no need to package messages. I guess Tid would become an alias for the Qid created when a thread is spawned. What I really don't want though, is for receive() to operate on a message queue created in a different thread. Messaging would become substantially slower if receive() had to be synchronized. >>> That's a drawback I haven't considered. To solve this, it would be made >>> part of the contract that receiving must all be done in one thread. >>> I can't think of a use where receiving in multiple threads would apply, but >>> if it would, a SynchronizedMessageQueue subclass could easily be drawn up >>> that broadens the contract and synchronizes for receive(). >>> BTW, how do you unittest just the std.concurrency module? >> >> Not easily, since a failure often means that a thread hangs. > > Linking fails (I'm on OSX): > > $ rdmd --main -unittest std/concurrency.d > Undefined symbols for architecture x86_64: > "_D3std3utf10strideImplFNaNeamZk", referenced from: > _D3std3utf15__T6strideTAxaZ6strideFNaNfxAamZk in concurrency.d.o > _D3std3utf14__T6strideTAaZ6strideFNaNfxAamZk in concurrency.d.o > _D3std3utf15__T6strideTAyaZ6strideFNaNfxAyamZk in concurrency.d.o > ld: symbol(s) not found for architecture x86_64 > collect2: ld returned 1 exit status > --- errorlevel 1 Used to work, and std.concurrency doesn't even use std.utf. Not sure what's going on there.
Why CTFE I/O would be awesome: No-Build-Tool Custom Build Steps
"Nick Sabalausky" wrote in message news:jkdho8$1p3a$1...@digitalmars.com... > "F i L" wrote in message > news:sofbqiiyvragxjaxq...@forum.dlang.org... >> Kapps wrote: >>> or even automatically creating bindings for a C header file. >> >> I've thought about that before. It would be great to have fully automatic >> linking to C libs. You could even have a cache system that stores .di >> files and only regenerates them if the .h file was modified. >> > > That hits on the one irritating limitation of CTFE: No I/O. So that cache > system would be a no-go right now. > (I'm branching this off from "Three Unlikely Successful Features of D") At least one way I think CTFE I/O could be a really big thing: A library could include any custom build steps it needed (or at least pre-build steps) *in* the library itself without the library's user needing to deal with buildscripts/buildtools. You can *kinda* do it now, but it requires all the processing be done within the naturally-slow and memory-hungry CTFE interpreter (compared to just running already-compiled native code), and *everything* will be recomputed on every compile whether it needs to be or not. So it'd be more of a curiosity right now than a real professional approach. But with CTFE I/O, that can change, and I think that could be a very big thing: For example (and I apologize if this sounds like shameless promotion of my project - but it's a good example of the scenarios I have in mind), the typical expected workflow in most cases for Goldie Parsing System is like this: 1. Run 'goldie-grmc' to compile your grammar definition from the BNF-like GRM file to a CGT file ("compiled grammar tables" - ie, precomputed LALR and DFA tables). This can take some real non-trivial time for non-trivial grammars. 'Couse, I think I can still optimize it more, but the nature of LALR still prevents this step from scaling well even when natively compiled, let alone if it were to be run inside CTFE. 2. Run 'goldie-staticlang' on the CGT file to generate a D library custom-tailered for your grammar. 3. Compile your program (which imports the generated D files from 'goldie-static''). Obviously there's improvements I can still make, such allowing 'goldie-staticlang' to optionally do the job of 'goldie-grmc' (thus merging steps 1 and 2). Or, it should be possible to make 'goldie-staticlang' (minus any 'goldie-grmc' features) a CTFE-based library instead of an external tool, once some DMD bugs are fixed. But there's *still* a custom build step required, which you have to manually add into your buildscript, or even run manually. And while that build step could theoretically be made CTFE-able, it would be much less efficient, and would *considerably* slow down compile times for *every* compile. But: If CTFE had I/O, I'm pretty sure I could set things up so that *all* you'd need to do is step 3: import Goldie and compile your program. Then, inside Goldie, there would be some CTFE that checks if the CGT file is missing or out-of-date, and if so (and *only* if so), invokes 'goldie-grmc' on it automatically - which will run at *full* natively-compiled efficiency. Then it would do the same for 'goldie-staticlang' (although it should be reasonable to make 'goldie-staticlang' an CTFE-based library instead of an external tool, just with some existing DMD bugs fixed). And finally it would import your either-already-existing-or-freshly-rebuilt custom-tailered D library. Hell, it could even rebuild 'goldie-grmc' itself if it needed to! All CTFE needs is system(), file I/O, and date/time stuff, and then need for buildsystems could be heavily reduced and make external tools/libs easier to use. I can see that being a big selling point for D. That might even make it possible (though I haven't really thought it through) to implement the dependency-searching feature of RDMD as a library.
Re: Proposal for a MessageQueue (was Re: public MessageBox)
On Friday, 23 March 2012 at 00:14:00 UTC, Sean Kelly wrote: While sending messages like a bare string might be good for example code, any real application is going to use structured messages whose type is specific to what the message is for, contains fields like sender Tid, etc. It seems like you're aiming more for CSP where you'd create a separate communication channel per use. You could even fake it by wrapping send/receive with your own CSP-like API, though it's quite likely that a from-scratch CSP style implementation would be faster because there'd be no need to package messages. I see your point. To make this easier, may I suggest: T receiveNext(T)() { T r; receive((T t) {r = t;}); return r; } A big reason for the use of receiveOnly (in my code) is its convenience. receiveNext, and a discouragement of using receiveOnly, would be a simpler solution. Used to work, and std.concurrency doesn't even use std.utf. Not sure what's going on there. Weird :( NMS
Re: Why CTFE I/O would be awesome: No-Build-Tool Custom Build Steps
On 3/23/12, Nick Sabalausky wrote: > A library could include any custom build steps it needed (or at least > pre-build steps) *in* the library itself without the library's user needing > to deal with buildscripts/buildtools. Ahh, yes, I can already envision it. It's 2014, and a newbie just posted in D.learn: "Hey guys whats a great, flexible, and easy to use build tool??" And one of the oldtimers replies: "Why, just import std.build and write this: (inserts 2 lines of code)" :D
Re: Windows Socket Timeout
On 23 March 2012 12:52, David Nadlinger wrote: > On Thursday, 22 March 2012 at 23:36:03 UTC, Paulo Pinto wrote: >> >> If you really want performant sockets on Windows, you need to make use >> of the Windows specific APIs, and use IO completion ports not select. > > > Depending on what you are trying to achieve, you could always consider using > enet or (parts of) RakNet. > > David Ideally, no matter what platform you're on, you want some form of non-blocking or asynchronous networking. The easiest way would be a seperate thread for all networking logic. Especially since you should probably have a separate thread for your rendering code anyway. -- James Miller
Re: Three Unlikely Successful Features of D
On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu wrote: I plan to give a talk at Lang.NEXT (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with the subject above. There are a few features of D that turned out to be successful, in spite of them being seemingly unimportant or diverging from related consecrated approaches. What are your faves? I have a few in mind, but wouldn't want to influence answers. Thanks, Andrei It isn't mainline yet, but UFCS from git has made working with std.algorithm much nicer. Instead of something like array(filter!"a > 0"(map!((a){return somefunc(a);})(data))) where you can quickly drown in parenthesis and the order seems somewhat backwards, you can use data.map!((a){return somefunc(a);}).filter!"a > 0".array
Re: Three Unlikely Successful Features of D
Matt Peterson: It isn't mainline yet, but UFCS from git has made working with std.algorithm much nicer. Instead of something like array(filter!"a > 0"(map!((a){return somefunc(a);})(data))) where you can quickly drown in parenthesis and the order seems somewhat backwards, you can use data.map!((a){return somefunc(a);}).filter!"a > 0".array I suggest to compile all your D2 code with -wi (or -w) and -property. And one bug of UFCS will be probably fixed by Hara (http://d.puremagic.com/issues/show_bug.cgi?id=7722 ), so map and filter will require an ending () (I have closed my http://d.puremagic.com/issues/show_bug.cgi?id=7723 ). So your last line is better written like this: data.map!somefunc().filter!q{a > 0}().array() This is indeed a significant improvement in D syntax for functional-style code, because this reduced nesting a lot, making such code significantly more readable. Bye, bearophile
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 04:31:00PM +0100, bearophile wrote: > Andrei Alexandrescu: > > >This is a bug in the language that requires fixing. > > I agree. Is someone willing to write a good enhancement request > about it? [...] Done: http://d.puremagic.com/issues/show_bug.cgi?id=7753 Please comment/vote. ;-) Thanks! T -- Winners never quit, quitters never win. But those who never quit AND never win are idiots.
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 10:25:04PM +0100, Andrej Mitrovic wrote: > On 3/22/12, H. S. Teoh wrote: > > Maybe this needs a ctor? > > Yeah probably. I really don't know when opAssign or the ctor are > called (especially with more complex types with alias this). Maybe > someone knows this or it's in the spec but I haven't read about it. Gah. I tried adding a ctor but it still doesn't work. Compiler complains: Error: Integer constant expression expected instead of "abc" for AA!(string,int) bb = ["abc":123]; I'm guessing the compiler thinks the literal is an array literal, or maybe something went awry with the internal AA hacks that it currently has. So we can't have this nice syntax until druntime/dmd integration. :-( T -- Many open minds should be closed for repairs. -- K5 user
Re: Wrong lowering for a[b][c]++
On Thu, Mar 22, 2012 at 09:29:36PM -0700, H. S. Teoh wrote: > On Thu, Mar 22, 2012 at 10:25:04PM +0100, Andrej Mitrovic wrote: > > On 3/22/12, H. S. Teoh wrote: > > > Maybe this needs a ctor? > > > > Yeah probably. I really don't know when opAssign or the ctor are > > called (especially with more complex types with alias this). Maybe > > someone knows this or it's in the spec but I haven't read about it. > > Gah. I tried adding a ctor but it still doesn't work. Compiler > complains: > > Error: Integer constant expression expected instead of "abc" > > for AA!(string,int) bb = ["abc":123]; > > I'm guessing the compiler thinks the literal is an array literal, or > maybe something went awry with the internal AA hacks that it currently > has. So we can't have this nice syntax until druntime/dmd integration. [...] Seems to be related to this bug: http://d.puremagic.com/issues/show_bug.cgi?id=6469 T -- The right half of the brain controls the left half of the body. This means that only left-handed people are in their right mind. -- Manoj Srivastava
Re: opEquals/opCmp returning other types
"David Nadlinger" wrote in message news:ajuozpunkzfawcapc...@forum.dlang.org... > > And how exactly do you plan to implement _library_ support for that in the > case of expressions containing comparison or equality operators? > > David With a D parser in phobos.
Re: Wrong lowering for a[b][c]++
On 3/23/12, H. S. Teoh wrote: > I'm guessing the compiler thinks the literal is an array literal, or > maybe something went awry with the internal AA hacks that it currently > has. struct Foo { string[int] aa; alias aa this; } void main() { Foo x = [1 : "4"]; } test.d(22): Error: cannot use array to initialize Foo Borken to the bone. I don't know whether there's a bug report open on this. Btw, want to see a magic trick? Put this into your hash: this(AA)(AA aa) if (std.traits.isAssociativeArray!AA && is(KeyType!AA == keytype) && is(ValueType!AA == valuetype)) { foreach (key, val; aa) this[key] = val; } And thn. *drumroll*: AA!(string,int) bb = cast()["abc":123]; badoom-tshhh. LOL!
Re: Understanding Templates: why can't anybody do it?
"Nick Sabalausky" wrote in message news:jk2ro7$6dl$1...@digitalmars.com... > > Here's a little templates primer, I hope it helps: > > [...] I've cleaned this up, added an intro and outro, and posted it on my website here: https://www.semitwist.com/articles/article/view/template-primer-in-d
Re: Wrong lowering for a[b][c]++
On Fri, Mar 23, 2012 at 06:11:05AM +0100, Andrej Mitrovic wrote: [...] > Btw, want to see a magic trick? Put this into your hash: > > this(AA)(AA aa) > if (std.traits.isAssociativeArray!AA > && is(KeyType!AA == keytype) > && is(ValueType!AA == valuetype)) > { > foreach (key, val; aa) > this[key] = val; > } > > And thn. *drumroll*: > > AA!(string,int) bb = cast()["abc":123]; > > badoom-tshhh. LOL! WAT?! What on earth is "cast()" supposed to mean?? That's just screwed up. Well anyway, I pushed the change to github, since it at least makes literal sliiightly more usable. Have fun! :-) T -- What's a "hot crossed bun"? An angry rabbit.
Re: Understanding Templates: why can't anybody do it?
On Fri, Mar 23, 2012 at 01:16:13AM -0400, Nick Sabalausky wrote: > "Nick Sabalausky" wrote in message > news:jk2ro7$6dl$1...@digitalmars.com... > > > > Here's a little templates primer, I hope it helps: > > > > [...] > > I've cleaned this up, added an intro and outro, and posted it on my > website here: > > https://www.semitwist.com/articles/article/view/template-primer-in-d [...] +1. Good introduction to D templates. Pity you didn't get into fancy stuff like recursive templates, but I suppose that's out of the scope of an intro. :-) T -- Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
Re: Understanding Templates: why can't anybody do it?
"H. S. Teoh" wrote in message news:mailman.1037.1332480633.4860.digitalmar...@puremagic.com... > On Fri, Mar 23, 2012 at 01:16:13AM -0400, Nick Sabalausky wrote: >> "Nick Sabalausky" wrote in message >> news:jk2ro7$6dl$1...@digitalmars.com... >> > >> > Here's a little templates primer, I hope it helps: >> > >> > [...] >> >> I've cleaned this up, added an intro and outro, and posted it on my >> website here: >> >> https://www.semitwist.com/articles/article/view/template-primer-in-d > [...] > > +1. Good introduction to D templates. > Thanks :) > Pity you didn't get into fancy stuff like recursive templates, but I > suppose that's out of the scope of an intro. :-) > Yea. Just kind of a "So what are these 'template' things anyway?" And some of that fancier template stuff (like template fibonacci) is better done as CTFE anyway ;)
Re: Wrong lowering for a[b][c]++
On 3/23/12, H. S. Teoh wrote: > WAT?! What on earth is "cast()" supposed to mean?? I've no idea. It's probably a front-end bug and the cast forces the compiler to.. come to its senses?
Re: Wrong lowering for a[b][c]++
On 23 March 2012 19:15, Andrej Mitrovic wrote: > I've no idea. It's probably a front-end bug and the cast forces the > compiler to.. come to its senses? `cast()` is the compiler equivalent to a slap with a wet fish? -- James Miller
Re: Wrong lowering for a[b][c]++
On 03/23/2012 01:24 AM, H. S. Teoh wrote: WAT?! What on earth is "cast()" supposed to mean?? I think it removes one level of const or immutable from the type of its argument. Why that helps in this case, I don't know. --Ed