Well I guess I have been looking at mixin modules as a replacement for classes/objects (or just prototypes) and doing without classes/objects entirely. You probably can get a similar effect with classes/objects but I think that mixin modules might subsume classes but not vice versa since most OO systems dispatch only on the first argument making certain kinds of functions quite difficult to write- i.e. those that exhibit commutative properties.
I also feel that alot of languages out there are not very good for mud "scripting" and implementing core logic at the same time. One reservation I have in building another C variant is that it is that it's not particularly extensible and difficult to embed a scripting engine inside such a language and make it look like an extension. If it were for my personal use I would be more partial to using scheme as my language of choice since an s-expression based language are very extensible. Obviously it lacks type annotations/and compile time type checking but it seems you can write relatively large projects in Common Lisp or Scheme so perhaps this might not be such a shortcoming(though I am uncertain why this is the case).
In response to Quixadhal's points- as per David's comment I am talking about a form of structural pattern matching on the type structure of the variable. Most OOP languages use nominative equality- but FP languages sometimes use structural equality instead- so pattern matching per Haskell and ML become quite useful.
I think with languages which permit you to dynamically load code complete static type checking can be quite a challenge. The suggestion of using a module to do this is interesting though I think a good type checking pass should be able to statically check as much of the type annotations as possible and add appropriate runtime checks in cases where it cannot cope. The problem of course is you might need type annotations of some sort and certain languages might lack these or make them optional and type inference may not be able to completely determine the correct type for each variable in all cases.
Well, still, you could get around the dispatch method by using static methods: you could then decide which object (if any) will handle the message. To use Lua as an example again, since there is really no OO system imposed, you could do whatever you wanted from the getgo.
I agree about languages not being good for scripting and core logic. I would rephrase it as scripting versus system building. My feeling so far is that the more you tend toward dynamic typing etc., the more suited it is for agile, scripting based purposes, whereas the more you tend toward static typing, the more suited it is for large systems with complex interaction. Of course you "can", strictly speaking, write relatively large projects in more or less whatever language you want – that doesn't mean it's really a good idea. After having written or dealt with several relatively large projects in dynamic languages, I have come to the opinion that having some kind of static checking is extremely valuable as the project gets too big to fit in my head.
And yes, I agree that dynamically loading code in a static type checking system would be complicated. I think you'd have to define interfaces at which code could be loaded, and then it would only let you load code that communicates along a given interface. I suppose it'd be rather like how you do it in C/C++, except that the language wouldn't let you cast types.
This might be getting a bit offtopic since the original topic title was a c-variant. An alternative I had be considering was to implement a scheme on scheme system which though not statically type checkable might have a number of advantages. It would for example be easier to build almost metacircular evaluators which could be then used to construct domain specific languages which resemble the core logic language in fundamental structure which could be viewed as natural extensions to the core-logic language. thus making the core logic language in a certain sense the same language as the scripting language. Also it would make the parsing phase almost trivial and the semantic mapping implementationally quite trivial as well.
I guess static type checking is always a boon if possible to do however given that mud projects atm at least arent too large this might not be as problematic as it seems. Also once one has such a basic implementation it might not be too difficult to extend it to include static type checking as per soft scheme or typed scheme (which includes sum types- but I dont think explicit variant types).
I have been starting this project sort of in the middle because of the implementation language of choice. I.e. I have been working on semantic analysis of an s-expression version of the c-variant as opposed to doing the parsing first. Thus from my standpoint changing the frontend language is still something which can be done quite easily. The next thing I will likely move onto is working on the runtime system. This area unfortunately still requires a fair amount of work- i.e. I would like to make the server persistent and have it react in some ways similar to how a database does- i.e. include atomic nested transactions of some sort. As part of this I would like to include a query system so it's possible to probe this databank to find information about the overall usage patterns etc. These two features are sort of on my dream list the 3rd one which someone has been trying to encourage me to explore is STM.
I am guessing for a first prototype build however I might forgo some of these "features" since their presence should require a limited number or no extra annotations on the language side.
At this point, I can't help but think that you're designing a very advanced solution but without having a true problem in front of you. Do you have specific use cases for all of these high-level programming features? You obviously know a lot about all of this stuff, and so I wonder if you want to implement these features just because they're cool (which they are) and you want to play around with them (which is fun), or because you have specific examples where they would help a lot.
I guess static type checking is always a boon if possible to do however given that mud projects atm at least arent too large this might not be as problematic as it seems
Actually, and only FWIW of course, I've been finding that a MUD server is quite big enough that it's hard to remember every function's parameter list and exact types, and having the compiler to help speeds things up a lot.
Well that is precisely why I am willing to forgo the last 3 features. They = nice for me but arent really deal breakers- having a system which behaves rudimentarily for starters much like a traditional LPC server (like FluffOS or LDmud) rather than something more advanced like DGD which has both persistence and a limited form of nested atomic transactions.
The problem with making a system where the core-logic is done in an in game language is that you sort of cross a boundary between a solution for a specific mud and a general purpose solution where it's more difficult to assess which features on my wishlist should make the final cut. I can think of specific cases where certain things like persistence and atomics are useful based on what I know of DGD. Whether they are mandatory for a mud server is another question- alot of older servers seem to lack both these features and do fine.
STM I feel once you have to account for I/O might be too experimental still to stick into a server and the speedup might a bit limited. It is still on my list but I have reservations about it- some method for supporting concurrency might be a boon though (unfortunately the complexity is quite high as well). How well this interacts with exceptions in a persistent environment is of course an open question.
I also have a couple reservations about typed schemes in that they arent widely used atm and thus one runs into a steeper learning curve than for scheme in some sense since the documentation and available code is more limited. I would probably opt for typed scheme if I were to do this.