October 04, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright |
Walter Bright wrote:
> Bill Baxter wrote:
>>
>> But something more is needed for Dynamic Qt-like S&S. Some sort of compile-time introspection seems a minimal requirement. I think some way to tag particular method like Qt's "slot:" keyword will also be necessary to make it usable. Anyway you need some way to say "do something with this method" and do it at the point of declaration rather than in the constructor or elsewhere.
>
>
> I don't understand. Exactly what needs to be done at compile time that can't be done with the mixin method?
reflection data to allow dynamic method connection at runtime by identifier.....
|
October 04, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to J Duncan | J Duncan wrote:
>
>
> Walter Bright wrote:
>> Bill Baxter wrote:
>>>
>>> But something more is needed for Dynamic Qt-like S&S. Some sort of compile-time introspection seems a minimal requirement. I think some way to tag particular method like Qt's "slot:" keyword will also be necessary to make it usable. Anyway you need some way to say "do something with this method" and do it at the point of declaration rather than in the constructor or elsewhere.
>>
>>
>> I don't understand. Exactly what needs to be done at compile time that can't be done with the mixin method?
>
> reflection data to allow dynamic method connection at runtime by identifier.....
That's not compile time <g>. The only way I can see a need for this at runtime is if the classes are coming from a DLL that the compiler doesn't know about. The compiler does know about everything that is statically linked to it.
|
October 04, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tue, 03 Oct 2006 22:04:03 -0700, Walter Bright wrote: > Bill Baxter wrote: >> Yes. For statically checked S&S, templates & mixins seem like they provide basically all that is needed to implement a good solution, (maybe there's still some weak reference business that needs to be sorted out, but it looks like it's mostly there). The main wart is that you have to have a different template for each number of arguments, resulting in repetitive code. Some form of Variadic Templates would be very nice to have there. >> >> So instead of >> template Signal(T1) // for one argument ... >> template Signal(T1, T2) // for two arguments ... >> template Signal(T1, T2, T3) // for three arguments ... >> template Signal(T1, T2, T3, T4) // for four arguments ... >> template Signal(T1, T2, T3, T4, T5) // for five arguments ... >> template Signal(T1, T2, T3, T4, T5, T6) // for six arguments ... >> template Signal(etc... >> >> You can just have one template >> template Signal(...) // for any number of arguments ... > > That would be better, but the user doesn't see that code, just the library implementer. So it isn't so bad. Agreed, not a significant issue issue in this case, though the variadic feature might have saved the library writer (or future application authors) some time and cut down on some parsing overhead. >> But something more is needed for Dynamic Qt-like S&S. Some sort of compile-time introspection seems a minimal requirement. I think some way to tag particular method like Qt's "slot:" keyword will also be necessary to make it usable. Anyway you need some way to say "do something with this method" and do it at the point of declaration rather than in the constructor or elsewhere. > > I don't understand. Exactly what needs to be done at compile time that can't be done with the mixin method? It would be nicer to implement S&S without the need for modifying source code of existing classes or adding overhead to all uses of those classes. |
October 04, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > Bill Baxter wrote: >> So instead of >> template Signal(T1) // for one argument ... >> template Signal(T1, T2) // for two arguments ... >> template Signal(T1, T2, T3) // for three arguments ... >> template Signal(T1, T2, T3, T4) // for four arguments ... >> template Signal(T1, T2, T3, T4, T5) // for five arguments ... >> template Signal(T1, T2, T3, T4, T5, T6) // for six arguments ... >> template Signal(etc... >> >> You can just have one template >> template Signal(...) // for any number of arguments ... > > That would be better, but the user doesn't see that code, just the library implementer. So it isn't so bad. Well I may be crazy, but I tend to prefer using libraries with readable code. It makes things so much easier to debug when something goes wrong. I cringe every time I have some crash inside of STL or some Boost library in C++. The code is just terrible for readability. Yes, ideally I shouldn't have to care how it's implemented, but in practice every once in a while it is useful to be able to actually read the code. But you are right, it is not a show-stopper. Just makes it less convenient, and makes it look like it was implemented more "despite" the language than "thanks to" it. >> But something more is needed for Dynamic Qt-like S&S. Some sort of compile-time introspection seems a minimal requirement. I think some way to tag particular method like Qt's "slot:" keyword will also be necessary to make it usable. Anyway you need some way to say "do something with this method" and do it at the point of declaration rather than in the constructor or elsewhere. > > I don't understand. Exactly what needs to be done at compile time that can't be done with the mixin method? The mixins are fine for Signals, but I'm talking about a dynamically callable method, or Qt-like "slot". I was assuming a world in which methods are not dynamically callable by default, as is the case with current C++/Qt. In that case, the Qt way is for users to flag methods that should have extra runtime call-by-name code generated for them by putting the 'slots:' keyword before the method(s). Then the "moc" compiler generates this code. I believe it's already possible with templates to make a method callable by name if you provide a name to use, and call some sort of register!(method, "method") template. PyD does a related kind of thing, and I wrote my own dynamic sigslot implementation in C++ that does that (quite hacky, but it works), so it must be possible in D too. But having to call "register!(...)" somewhere is not as convenient (or as easy to maintain) as just being able to flag the method right at the place of declaration. Of course the outside-the-class "register!()" technique is useful too, for those cases where you can't modify the class's code for whatever reason. --bb For kicks, here's a snippet of my dynamic sigslot implementation in C++. I gave up after 4 arguments because it became too tedious and too much of an eyesore. I was originally planning to do 9. template <class ClassT> class _SlotCaller0 : public _SlotCaller<ClassT> { protected: typedef void (ClassT::*MethT)(); MethT mMeth; friend DynSigSlot; _SlotCaller0(ClassT* obj, MethT m) : _SlotCaller<ClassT>(obj), mMeth(m) {} virtual void call(va_list args) { (mObj->*mMeth)(); } }; template <class ClassT, class Arg1T> class _SlotCaller1 : public _SlotCaller<ClassT> { protected: typedef void (ClassT::*MethT)(Arg1T); MethT mMeth; friend DynSigSlot; _SlotCaller1(ClassT* obj, MethT m) : _SlotCaller<ClassT>(obj), mMeth(m) {} virtual void call(va_list args) { Arg1T a1 = DSS_VARG(args,Arg1T); (mObj->*mMeth)( a1 ); } }; template <class ClassT, class Arg1T, class Arg2T> class _SlotCaller2 : public _SlotCaller<ClassT> { protected: typedef void (ClassT::*MethT)(Arg1T,Arg2T); MethT mMeth; friend DynSigSlot; _SlotCaller2(ClassT* obj, MethT m) : _SlotCaller<ClassT>(obj), mMeth(m) {} virtual void call(va_list args) { Arg1T a1 = DSS_VARG(args, Arg1T); Arg2T a2 = DSS_VARG(args, Arg2T); (mObj->*mMeth)( a1, a2 ); } }; template <class ClassT, class Arg1T, class Arg2T, class Arg3T> class _SlotCaller3 : public _SlotCaller<ClassT> { protected: typedef void (ClassT::*MethT)(Arg1T,Arg2T,Arg3T); MethT mMeth; friend DynSigSlot; _SlotCaller3(ClassT* obj, MethT m) : _SlotCaller<ClassT>(obj), mMeth(m) {} virtual void call(va_list args) { Arg1T a1 = DSS_VARG(args, Arg1T); Arg2T a2 = DSS_VARG(args, Arg2T); Arg3T a3 = DSS_VARG(args, Arg3T); (mObj->*mMeth)( a1, a2, a3 ); } }; template <class ClassT, class Arg1T, class Arg2T, class Arg3T, class Arg4T> class _SlotCaller4 : public _SlotCaller<ClassT> { protected: typedef void (ClassT::*MethT)(Arg1T,Arg2T,Arg3T,Arg4T); MethT mMeth; friend DynSigSlot; _SlotCaller4(ClassT* obj, MethT m) : _SlotCaller<ClassT>(obj), mMeth(m) {} virtual void call(va_list args) { Arg1T a1 = DSS_VARG(args, Arg1T); Arg2T a2 = DSS_VARG(args, Arg2T); Arg3T a3 = DSS_VARG(args, Arg3T); Arg4T a4 = DSS_VARG(args, Arg4T); (mObj->*mMeth)( a1, a2, a3, a4 ); } }; |
October 04, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > Bill Baxter wrote: >> Yes. For statically checked S&S, templates & mixins seem like they provide basically all that is needed to implement a good solution, (maybe there's still some weak reference business that needs to be sorted out, but it looks like it's mostly there). The main wart is that you have to have a different template for each number of arguments, resulting in repetitive code. Some form of Variadic Templates would be very nice to have there. >> >> So instead of >> template Signal(T1) // for one argument ... >> template Signal(T1, T2) // for two arguments ... >> template Signal(T1, T2, T3) // for three arguments ... >> template Signal(T1, T2, T3, T4) // for four arguments ... >> template Signal(T1, T2, T3, T4, T5) // for five arguments ... >> template Signal(T1, T2, T3, T4, T5, T6) // for six arguments ... >> template Signal(etc... >> >> You can just have one template >> template Signal(...) // for any number of arguments ... > > That would be better, but the user doesn't see that code, just the library implementer. So it isn't so bad. Perhaps, but then what happens when I need to use more arguments than such a template library provides for? Suddenly, the problem is thrown in the library user's lap. -- - EricAnderton at yahoo |
October 04, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Wed, 04 Oct 2006 08:04:03 +0300, Walter Bright <newshound@digitalmars.com> wrote: > Bill Baxter wrote: [snip] >> arguments, resulting in repetitive code. Some form of Variadic Templates would be very nice to have there. >> So instead of >> template Signal(T1) // for one argument ... >> template Signal(T1, T2) // for two arguments ... >> template Signal(T1, T2, T3) // for three arguments ... >> template Signal(T1, T2, T3, T4) // for four arguments ... >> template Signal(T1, T2, T3, T4, T5) // for five arguments ... >> template Signal(T1, T2, T3, T4, T5, T6) // for six arguments ... >> template Signal(etc... >> You can just have one template >> template Signal(...) // for any number of arguments ... > > That would be better, but the user doesn't see that code, just the library implementer. So it isn't so bad. Hey, library writers are people too! ;) Actually I think it's absurd to divide people into two groups: ones writing libraries and ones using them. If you write something more complex than tiny programs, you're gonna need all the same features and tricks than library writers. Eventually. I think library writers and other heavy duty users would be good test subjects, wouldn't they? What they will need, the language should provide. ;) |
October 05, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kristian | Kristian wrote: > On Wed, 04 Oct 2006 08:04:03 +0300, Walter Bright <newshound@digitalmars.com> wrote: >> Bill Baxter wrote: > [snip] >>> arguments, resulting in repetitive code. Some form of Variadic Templates would be very nice to have there. >>> So instead of >>> template Signal(T1) // for one argument ... >>> template Signal(T1, T2) // for two arguments ... >>> template Signal(T1, T2, T3) // for three arguments ... >>> template Signal(T1, T2, T3, T4) // for four arguments ... >>> template Signal(T1, T2, T3, T4, T5) // for five arguments ... >>> template Signal(T1, T2, T3, T4, T5, T6) // for six arguments ... >>> template Signal(etc... >>> You can just have one template >>> template Signal(...) // for any number of arguments ... >> >> That would be better, but the user doesn't see that code, just the library implementer. So it isn't so bad. > > Hey, library writers are people too! ;) > > Actually I think it's absurd to divide people into two groups: ones writing libraries and ones using them. If you write something more complex than tiny programs, you're gonna need all the same features and tricks than library writers. Eventually. Amen to that! But I think Walter's point is more that it's encapsulated. After you write that gobbledygook once, it becomes an implementation detail you can forget about. At least for that one library. Contrast that with something like the hacks for adding OO support to C. Yes you can get inheritance and polymorphism, but you're still stuck with ugly syntax in your face every time you try to *use* it like: toolkitWidgetResize(widget, W,H); instead of widget->Resize(W,H); In the lack-of-variadic-template-args case Walter is arguing that you don't see it. But I take issue with that, because I will indeed see it the first time I pass it a bogus parameter and the compiler chokes on it. It's going to point me right at that file with the gobbledygook and tell me there's something wrong there. But here's what Walter's Signal class could look like with variadic template parameters. I've assumed the types of the variadic arguments can be accessed by some sort of static type array "_targuments": template Signal(...) // for any number of arguments { // _targuments.args can serve in place of a list of typed arguments // so this would expand to T1 a, T2 b for Signal(T1,T2) void emit( _targuments.args ) { foreach (dg; slots) // _targuments.args can be treated like varargs // they show up in the _arguments list dg(_arguments); //(can you forward arguments like this D?) } // _targuments.types expands to T1,T2 for Signal(T1,T2) void connect( void delegate(_targuments.types) dg) { slots ~= dg; } void disconnect( void delegate(_targuments.types) dg) { for (size_t i = 0; i < slots.length; i++) { if (slots[i] == dg) { if (i + 1 == slots.length) slots = slots[0 .. i]; else slots = slots[0 .. i] ~ slots[i + 1 .. length]; } } } private: void delegate(_targuments.types)[] slots; } I would prefer something user named like here: http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html rather than the "magic" variable, but that's a critique that applies to regular function varargs too. Might as well put that in a separate message. --bb |
October 07, 2006 Re: Games people play | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lutger | Lutger a écrit : > Georg Wrede wrote: >> Seems to me that while D is marketed as a Systems development language, it will be quite some time before anybody has developed a System with D. >> >> More plausible should be that one day games developers will find D /en masse/ because everything in D really is perfect for games development. > > <snip> > > I'm not a prof. game developer, but I sure agree that D is perfect for it. Just the other day I was looking into the C++ source of civilization 4 (they released a good bulk of it) and thinking how nice it must be for the developers to turn this 125.000 LoC monster that takes more than 15 minutes to build into D. And then that is even a small part of the total code. (and oh my god, how ugly it is) > > Just wondering whether it is a new language feature that game developers want. Tool, library and company support, general acceptance, marketing etc seems to be an important part of the equation. > From some developers at gamedev.net I understand that it is even the opposite: D is not a proven language and might have too much, not too few language features. Allow me to quote from a thread over there: > > "Compared to C, C++ is a really really big language. It has a lot of features. It is so complex, in fact, that its features begin to interact in unintended ways. A great example of this is the thread on default arguments and virtual function binding. Who knew that those two features--which theoretically are unrelated--would combine to form unexpected-looking behavior? Or that template arguments could break preprocessor macros? There's plenty of examples of this, many chronicled on GotW and many more still being discovered by hapless C++ students and intrepid Boost developers. > > And D goes so, so much further. The designers have a "why not" attitude towards adding useful-sounding features, with the result that D's feature list makes C++ look downright minimalist. Many of these features are new to the entire extended language family, or have been implemented in radically different ways than previously in the extended language family. Are mixins going to cause a problem with lambdas? Is liberal use of slices going to make DBC unmaintainable? Who knows! Who's going to find out? The early adopters. > > I hope that D gains traction among some large body of hypothetical developers who, despite not being rabid D fans, end up using it in large applications with a long lifecycle. I hope this happens, because this is the only way to vet a language. Maybe I'm wrong; maybe D will all hang together and the features will turn out to mesh perfectly and I'll come to terms with the syntactic features I dislike and everything will be great. I just don't think that it's likely." > > http://www.gamedev.net/community/forums/topic.asp?topic_id=409926&whichpage=2� > Hello, The risk of clash/inconsistencies between language features and the difficulties added in optimizing the compiler are two good reasons why the core language must stay as clean as possible. So features such as Signals & slots should IMHO be kept in libraries (maybe in Phobos) and not included in the language, simply because the language was not designed with this kind of feature in mind from the start. I'd say the same thing for the support of multi-processing. D can only offer very good multi-threading and message-passing capabilities via dedicated libraries. Just for the record, the best game examples written in D I know of are the shooter games by Kenta Cho: http://www.asahi-net.or.jp/~cs8k-cyu/index_e.html (source code included in the downloads). I think they demonstrate very well the gaming performances of D (it looks like they were written in C). |
Copyright © 1999-2021 by the D Language Foundation