|
tef posted:welp a game designer writes terrible code I didn't know you were a game designer!
|
# ¿ Apr 5, 2012 01:39 |
|
|
# ¿ May 15, 2024 09:24 |
|
You know, I bet your code does increase in quality by a ton when you have that many people watching you code. You're both probably way more self-conscious and people will be catching your bugs all the time for you entirely for free as soon as you write them.
|
# ¿ Apr 8, 2012 01:28 |
|
Toady posted:I don't think it's accurate to pin negative opinions on nerd jealousy or increased scrutiny due to success. Minecraft's code is objectively bad. It doesn't even combine identical adjacent quads. So what, how often would that actually happen in a game like minecraft? Oh yeah. Edit: Although, to be honest, I highly doubt that would ever be a bottleneck anyway.
|
# ¿ Apr 8, 2012 01:52 |
|
Toady posted:Quite often since most buildings and other user creations, plains-like biomes, oceans/lava, etc. have flat surfaces. Yeah, that would be the joke.
|
# ¿ Apr 8, 2012 02:27 |
|
Factor Mystic posted:From reddit This post makes me so depressed.
|
# ¿ May 22, 2012 01:27 |
|
Suspicious Dish posted:My favorite is the guy who thinks that your memory has the capacity to repeat to infinity. Ummm, his name is base2op. I think he knows what he's talking about....
|
# ¿ May 22, 2012 02:35 |
|
Zombywuf posted:idgi Agreedo.
|
# ¿ May 25, 2012 01:10 |
|
SavageMessiah posted:How about coding standards horrors? I'm "improving" some code I wrote for our parent company by switching over to their "standards". ... this is it, folks, this is how we write good code!
|
# ¿ Jun 19, 2012 00:08 |
|
It's so hotta here.
|
# ¿ Jun 28, 2012 04:41 |
|
quote:PHP is a language with many high-level functions and while they're not always implemented as consistently as we'd like (mostly to blame on its underlying C parts) Err... what??? How can you possibly push the blame onto C.
|
# ¿ Jul 7, 2012 19:40 |
|
bobthecheese posted:The other day I wrote a post about possible changes to switch statement flow through. Maybe I'm missing something, but isn't your example just equivalent to a switch nested inside of a while loop: code:
|
# ¿ Jul 11, 2012 09:04 |
|
SupSuper posted:It might be horrible, but the readable comments and variable names put it way above a lot of code I've seen. I dunno, I think I'd rather have a nice, 5 line function that is very clear than have a 1000 line mess that does the same thing coupled with several paragraphs of comments. Edit: Even if they used 1-letter variable names I think it'd be better at 5 lines.
|
# ¿ Aug 13, 2012 03:06 |
|
At a place I worked they did something similar regarding linked lists. I can relate to a lot of that stuff. The game industry really needs some fixing.
|
# ¿ Sep 9, 2012 17:54 |
|
Some day, people will more widely embrace generic programming and we won't have to deal with retarded, inflexible hierarchies of poo poo.
|
# ¿ Sep 9, 2012 18:54 |
|
Pilsner posted:Just curious, if I ever were to code some C++ again, is Boost like a good wrapper for all the horrible tedious stuff in basic C++, like having to write 10 lines of code to read a file and such? What about networking, image handling, databases, etc? Reading files was already mentioned, but as for networking there's Boost.Asio, for image handling there's Boost.GIL. E: ToxicFrog posted:Don't forget to delete[] (not delete) buf when you're done with it! If you're manually using new and delete for dynamic memory allocation in modern C++, you're probably missing a better alternative in the standard library and/or boost. That Turkey Story fucked around with this message at 19:35 on Sep 10, 2012 |
# ¿ Sep 10, 2012 19:32 |
|
I'm only saying "probably" to be a pedant. unique_ptr is good for most cases where you'd use dynamic memory allocation, even when building higher-level data-structures, and shared_ptr and weak_ptr are good enough in those situations where one wants shared ownership. It's pretty difficult to come up with situations where you'd manually use new and delete for dynamic memory allocation in place of tools like these.
|
# ¿ Sep 10, 2012 19:48 |
|
shrughes posted:Boost is more like what happens when you take a bunch of sperglords who feel the need to make poo poo complicated in order to feel smart about themselves. This is what programming plebes actually believe.
|
# ¿ Sep 11, 2012 01:30 |
|
Boost isn't perfect, but it's generally as complicated as it needs to be and no more. Libraries go through peer review before being accepted. If you think something specific can be simplified without sacrificing functionality then post to the mailing list and someone will either listen to you and make changes or they will kindly explain existing rationale. If you have patches, you'll be all the more welcome.
|
# ¿ Sep 11, 2012 03:15 |
|
I realize you're likely trolling but I'm going to respond anyway because that's what I do.shrughes posted:No, this is what is actually true. Or rather, it is the theory that most accurately fits the facts. Pick any boost library. For example... *picks at random* the boost uuid library. It defines a struct that contains a 16-byte char array and has a few functions for creating UUIDs. It somehow uses or includes something that uses MPL. shrughes posted:Let's pick another ... *picks at random* the boost spirit library, probably the archetypal example. We implemented a bunch of spirit parsers and it's clearly overengineered garbage. Infinitely slow to compile, not fast or optimizable to run. It's always simpler, more debuggable, and more editable by coworkers, to pound out your own recursive descent parser, or to use some other method of building a parser. Boost.Spirit exists for people who want an EDSL for parsing and output generation without the tedium and chance to introduce bugs that comes about from hand-rolling parsers from scratch. You are obviously not one of those people, so don't use it. That's fine, but if you really don't see the advantages of it then you're just completely oblivious. shrughes posted:Let's pick another ... *picks something "safe"* scoped_ptr. It has an implicit conversion operator. The real point here is that probably 90% of programmers don't know this and don't have to know this. Thousands of people use the library without ever having to think about it or even look at the implementation because there is no reason for them to, as is the case with most well-designed, well-tested code. But of course, it's much easier to just criticize code you don't understand than actually ask someone about it or look into the rationale yourself. Certainly you can do it better, so just make your own -- oh wait, don't tell me, you've done so already. Have fun maintaining that while everyone else uses a more reliable library that the community in general is already familiar with. shrughes posted:Let's pick... shared_ptr: it is all mixed up with weak_ptr, to make it easier to make your code unnecessarily complicated. shrughes posted:Let's pick... boost serialization. "Oh, you want to serialize stuff? Sorry, you're using some slow library that wants to keep track of pointer graphs [and iirc, uses RTTI]." shrughes posted:The best example of making poo poo complicated for complete vanity is this binary conversion utility. It has a billion preprocessor expansions when you can just use a hexadecimal or octal constant, or convert at run time, or glue different field width sections together with a macro, or run an octal constant through some bitshifting... Anyway, if you really think it's for complete vanity, it's not. The reason that the macro exists is because other people wanted it -- I wasn't even the original one to propose it. In fact, I didn't even write it until a review for someone else's implementation was already underway (which first requires agreement that such a utility is useful to begin with). People show desire for a facility, there is a request for consideration of an implementation, it goes through peer review, and then it is accepted or denied (and a lot does get denied). It's not just a bunch of know-it-all programmers throwing in whatever they want. shrughes posted:It's very easy to create a "rationale" for any feature: you need it to do X. The argument against making things complicated is less tangible -- it is a sense learned by experience and not derivable through software philosophy.
|
# ¿ Sep 11, 2012 07:35 |
|
Shinku ABOOKEN posted:Inexperienced opinion here:
|
# ¿ Sep 11, 2012 07:37 |
|
shrughes posted:- No, it's not reasonable for UUID to use MPL. shrughes posted:The fact that you think it's reasonable is an example of why Boost is such a horrible set of libraries: you don't care about quality, and you don't understand the benefits of keeping code simple with a constrained set of dependencies. shrughes posted:- You think I don't understand how Spirit works. I have used Spirit for parsing and used other people's uses of Spirit for parsing big and little things. We're no longer using it. shrughes posted:Y'know, when somebody says that they used to think X but then experience made them change their mind to Y, while you still hold the opinion X, it means you should reconsider X. shrughes posted:- Saying that people "want" Spirit does not mean it's a good idea. I don't know why you'd think it means it's a good idea. It's a plausible implementation of a bad idea. Do you think that Spirit is useless for everyone or just you? If just you, then how does that imply overall poor design? If everyone, you'd better make a pretty strong case and an alternative approach that doesn't involve writing everything from scratch all of the time, which you haven't. shrughes posted:- I know about the convertible-to-bool idiom, I've written it myself, and then removed it, and I just included reliable evidence that I looked at the code in my previous post, so why are you acting like I don't know how it works? A lot of smart pointers do this and people don't whine about it because there's nothing there to whine about. Like I said, in the real world nobody cares what's going on when they do if( my_pointer ), nor should they have to. It works, it's correct, it's efficient, and perhaps best, they didn't have to write it. What's more is they're probably not ever going to look at the source, just like they'll rarely look at their standard library's source. If I took two smart pointer types, showed their usage to a programmer, pointing out that one allows you to do if( my_pointer ) and the other makes you do something along the lines of if( my_pointer.is_valid() ) or if( my_pointer.get() ) do you honestly think that they give a poo poo that one uses an idiom that they may or may not be aware of underneath the hood and that it will somehow negatively impact their ability to write code or use the library? Further the interface difference is unbelievably superficial. Would I really care if I had to do if( my_pointer.is_valid() ) all of the time? No, but if there's a more concise way of writing it, I might as well take advantage of it. shrughes posted:Here's a conclusive example where even you should recognize that you were wrong about something. Given this new self-knowledge, you should probably trust your opinion about other matters less than you do. The convertable-to-bool idiom is another example of the X -> Y movement where you're still at X and I've moved on to Y. shrughes posted:- Writing OCTAL_BINARY(01101011100) (or heh, just using hex) does indeed show your intent. Also, just using hex generally does not directly show your intent when working with bitmasks. First off, when writing a bitmask you have a bit pattern in mind -- that's why it's a bitmask. If you have to write the value in hex or octal, you're going to have to appropriately, and manually, convert it. Similarly, for a reader, the first thing you're going to do to figure out what the bitmask corresponds to is convert the hex or octal digits to binary in your head. Writing the value, you know, actually in binary directly, removes both of these unnecessary steps, and in doing so removes some of the chance for human error. I understand that you have the correspondence between every nibble and every hex digit memorized, but plenty of people don't, nor should they have to to quickly and easily write out something as trivial as a bitmask. shrughes posted:- Yes, I have written smart pointer classes that did use the convertable-to-bool idiom and now don't. And guess what: they're reliable and don't require "maintenance." (Why the hell would you expect a smart pointer type to be hard to maintain? I know, maybe it's because you like to introduce unneeded dependencies to other libraries.) Go ahead, write all your trivial bits of code from scratch because you have some arbitrary philosophical gripe with already written, heavily-tested code that does exactly the same thing and that thousands of other programmers are already familiar with. I personally love working on projects where some supposedly hot-poo poo programmer likes to write everything on his own, including trivial smart pointers, rather than use existing solutions to problems solved a decade ago. I know, it must be fun to write or learn yet another smart pointer for a given project that has no actual benefit over something in the C++ standard or in Boost. That's really a great approach to programming. There is no possible way that that time would have been better spent writing code specific to whatever domain you are actually dealing with. Plorkyeran posted:A dependency the size of MPL is not something to throw in to simply some already simple code unless your primary goal is to ensure that the only way to use boost is to depend on all of it, rather than to create a useful library. Plorkyeran posted:I think I would be less annoyed by boost if it admitted it was a monolithic blob with some optional components rather than pretending that it's actually modular. I don't really get why bcp even exists, as I've never seen it output something reasonable to distribute along with the application source.
|
# ¿ Sep 11, 2012 19:40 |
|
Vanadium posted:Also D lets you assign non-static member functions to function pointers without a cast or anything, and the function pointers will segfault when called while this doesn't happen to have the right type in the lexical context of the call. Wait, what? What was even the rationale for this?
|
# ¿ Sep 11, 2012 21:26 |
|
Senso posted:Same guy trashed linked lists in his next post. I'm a newbie regarding that but what's the general opinion of this thread, is he right? Linking directly in the object (intrusive lists) is preferred to using linked lists? Like anything else, you weigh your options. Lots of types (containers, smart pointers, etc.) may be implemented intrusively, with varying benefits. If you are dealing with value types, a std::list is often a better choice and is easier to reason about. Throwing down your fist and saying that users should always prefer intrusive over non-intrusive containers is ridiculous and at the very least forces people to intrusively alter their types simply because of the containers they may be stored in when it may not even be worthwhile, and it forces you to change your types if you simply change where/how they are stored. Also, a fair amount of what he says is not entirely true: Patrick Wyatt posted:Here is code that safely removes a person record from the linked list: Second, his comment that it forces people to write "list-removal" functions such as the one he wrote out above are completely not true. Despite deciding that std::list is universally bad, he apparently doesn't even know the STL well enough to realize that std::list has a function for removal (imagine that) and it's called, unsurprisingly, "remove." You just have to write your_list.remove( your_person ); You don't have to manually write a search as he explicitly claims and cites as a reason why his intrusive list is "better" than std::list. Third, but admittedly on somewhat of a tangent, in cases like these, very often people mistakenly choose a std::list over something like a std::vector simply because they want constant time removal from the container. There are a couple issues here. First, you can remove items from a vector in constant time, it just alters the stored order and potentially invalidates an iterator -- you do so by swapping the element you want to remove with the one in the back and then pop_back. Second, if you are dealing with something like a container of pointers (or really anything that is trivially movable), as is in the example, erasing something from the middle can generally just be a memmove on the chunk of data that appears after the removed element anyway, and will even preserve storage order. It's also important to note that neither of these operations will require a call to your allocator's deallocation function, unlike when using a std::list, since in the list case, a node has to be deleted. For small lists, it's unlikely the difference between the constant-time erasure and the erasure from the middle of a vector of trivially-movable types, such as pointers, is significant at all, and depending on a number of variables including the size of the container, how allocation/deallocation is performed, and where your list nodes happen to be in memory in relation to one another, the vector erase may end up being faster, even if you don't use the swap trick. Finally, linked lists provide constant removal, but iteration over them is potentially much slower and not cache-friendly. If you are iterating over the list frequently (I.E. every frame, or almost every frame), but are removing things from the list only on occasion (I.E. when an object moves from one sector to another, or when an item is removed from inventory or a selection list, etc.), you should probably be valuing fast iteration a lot more than fast removal (though in those cases, neither would likely be a bottleneck anyway). Anyway, the point is, you always need to weigh your options. The differences between std::list, intrusive lists (whatever implementation you choose), std::vectors, and any container are trade-offs. One is not universally better than another. Senso posted:EDIT: Eh, he's also trashing Boost, since we're talking about it. Edit: shrughes posted:Actually it runs around more like 80 lines. It could potentially balloon to 90 if I ever need to iterate the thing without consuming it. Or, you could just use a peer-reviewed, efficient, tested, open source solution that people already know instead of making your own intrusive container, apparently for at least the second time, programming messiah. *cough* That Turkey Story fucked around with this message at 22:58 on Sep 12, 2012 |
# ¿ Sep 12, 2012 18:15 |
|
Vanadium posted:I'd like to suggest that the D motto is "Those who cannot learn from history are doomed to repeat it" but I can't really argue against the combined Walter Bright and Andrei Alexandrescu C++ learnin'.
|
# ¿ Sep 12, 2012 23:06 |
|
HORATIO HORNBLOWER posted:What a nonsense post. Part one was intriguing, but this is just a mess. My three favorite things about it: a) purports to explain how to avoid game crashes while concerning itself exclusively with performance; b) goes out of its way to point out that the author did not invent the concept of a linked list without seperate container objects, like, no poo poo, sherlock; and c) advocates hand-rolled code as less susceptible to bugs than standard libraries. C) is what really gets me more than anything else and it happens with tons of programmers. How big of an ego do you have to have to think that something you write ad-hoc for a project is going to have fewer bugs, be better designed, and be less buggy than a standard or open-source solution put together by one or more people who have devoted their time explicitly to it, usually with plenty of tests and other people using it, improving it, and potentially finding bugs. This is true even, if not especially, for something trivial -- I say especially for something trivial only because there are probably fewer potential trade-offs that could actually make a difference for a project. Anyway, if the code really is so trivial that you could write it in an hour or two and be relatively convinced of its correctness, why would you spend any time making it at all, particularly with even the slightest chance that you may mess something subtle up. For something so trivial, there are probably plenty of already-written, known alternatives, that other people are aware of. What are you gaining by reinventing the wheel? Even if it just takes an hour, devote that hour to whatever specific task you are trying to accomplish, not some mundane little algorithm or datastructure.
|
# ¿ Sep 13, 2012 05:16 |
|
Ithaqua posted:Some individuals / organizations have an insane sense of pride that all of their software uses no third-party code. I interviewed at a place like that; they weren't amused when I suggested that they implement their own operating systems, web servers, and database servers to be truly 100% in-house.
|
# ¿ Sep 13, 2012 05:39 |
|
Contero posted:I'm curious what your list of retained features would be to make a successful successor to C++. Contero posted:My biggest issue is that the first thought when replacing C++ always seems to be "So this language is going to be like C++, except with garbage collection! Then we can get rid of those nasty, confusing destructors." GrumpyDoctor posted:Garbage collection isn't nice because destructors are hard, garbage collection is nice because keeping track of object lifetimes is cognitive overhead and if you can get rid of it then why the hell not? Realistically, garbage collection is fine in cases where 1) non-deterministic memory management is acceptable, 2) you actually want shared ownership of a given object (garbage collection is pointless for clearly scoped objects), and 3) where disposal of the type is trivial and predictably will be trivial in the future (i.e. in C++ terms, any C++ type with a trivial destructor or that only directly or indirectly dynamically allocates types that have trivial destructors). In terms of #1, most people are okay with it, and that's fine. I'm including this for completeness and because it isn't always acceptable. If you really are trying to make a general-purpose language, this is definitely important to understand. Optional garbage collection is one thing, but if you force it for all dynamically allocated objects then you're ruling out a whole class of users for no reason. In terms of #2, you should already be striving for minimizing or eliminating shared ownership to begin with -- you use value semantics in C++. Take a look at all of the C++ standard libraries and all of the boost libraries, for example. Specifically, which of their components would be significantly, if at all, impacted by the presence of garbage collection and how would it make their implementation better, easier to understand, or even easier to write for that matter? Since they use value semantics, pretty much none of them (you could probably stretch and say something like shared_ptr could be metaprogrammed to have a different implementation in cases where types have trivial destructors). Further, as for #3, even if you're not dealing with value semantics, if your types are nontrivially dispoable or if your code (especially generic code) is to contain anything that is potentially not trivially disposable, then you want or need deterministic disposal anyway, which garbage collection itself cannot provide. Because of this, you need some other way to keep track of when disposal can take place that is actually deterministic and timely -- if you have to keep track of when to dispose anyway, then the benefits of garbage collection in that scenario go out the window (if you know when to dispose of the object, you know when its memory is ready to be reclaimed). Garbage collection is fine for dynamic memory allocation of trivial types, but it falls flat on its face with respect to deterministic resource management. In something like C++ with garbage collection, there's nothing detrimental about the facility being there and it's very welcome, but good practice will still always be to use value semantics unless you have a solid reason not to, use unique_ptr in places where you have simple lifetimes of dynamic objects, and use shared_ptr in places where you have dynamic objects with shared lifetimes (though again, that's something you should strive to avoid if possible anyway). That Turkey Story fucked around with this message at 21:28 on Sep 13, 2012 |
# ¿ Sep 13, 2012 21:15 |
|
Zombywuf posted:Have you seen Clay. It's in early stages but it seems to be going in a nice direction. No, but from the listed features and design philosophy I'm already interested. Edit: Skimming the language reference, I like how they handle a lot of things, often better than C++: overloading, discriminated unions (though I'm not entirely sure they should be a language feature as opposed to a library feature), and function return type deduction. Edit2: In IRC someone is claiming that development on the language isn't really active anymore, even though it looks like it was updated relatively recently. :/ Edit3: I really like this language a lot. That Turkey Story fucked around with this message at 01:55 on Sep 14, 2012 |
# ¿ Sep 13, 2012 23:35 |
|
shrughes posted:4) You want memory safety and don't want every piece of broken code to be a security flaw. If by that you mean you don't want somebody to be able to accidentally write to something that's been deleted and/or destroyed, I agree, but unless you're disallowing holding references to non-dynamically-allocated objects, or you are always implicitly dynamically allocating and garbage collecting all objects, you're still going to have that potential problem anyway. That's a gigantic trade-off. You could sort of have it both ways, though -- keep track of traceable memory references ala GC, and if other pieces of code are still holding onto them at the time delete is called or the object is destroyed, produce some kind of error (probably something like terminate without stack unwinding, allowing some kind of hook). The thing is, even if you avoid trampling over memory, your program is still in some erroneous, unaccounted for state by the programmer. Something still should be done other than silently continuing.
|
# ¿ Sep 14, 2012 01:03 |
|
GrumpyDoctor posted:It looks like it's how they do their OO: A lot of the ideas look like they're directly influenced by Stepanov's Elements of Programming. The only thing is, it doesn't look as though it's yet at the stage where it has full concept and concept map support, or if they're necessarily planned in the sense that they are for C++. That Turkey Story fucked around with this message at 02:44 on Sep 14, 2012 |
# ¿ Sep 14, 2012 02:17 |
|
Vanadium posted:Clay looks like it shares some DNA with Haskell, so I'm all for it Yeah, it really got a ton of poo poo right already, and a lot of the important stuff is the basis for language and not an after-thought. It's like the designer actually understood what makes a good language before he went out and designed a language, and knows C++ well enough to actually understand what is required to make a "better C++." Usually I have some nasty criticism about a language, but I don't really with Clay yet. I don't think I really like the fact that overload selection is partially based on ordering, though. IMO, if something is ambiguous, it probably should be a compile error and shouldn't just pick the last one. If anything, if you want the unambiguous behavior and you want your newly-written implementation to be used, I think you should have to be explicit about it (I.E. somehow reference the previous overload that would be a worse match in the declaration of the new overload to notate that this one takes precedence). Anyway I do a lot of generic programming and I just don't see the rationale for this feature at all, but perhaps I'm missing something? Edit: errrr actually, I guess I misunderstood and it's worse than that? It uses the first match it finds in reverse order, so something that'd be a worse pick in C++ would be picked over a better one if it were written later. I don't see why anyone would want this behavior. That Turkey Story fucked around with this message at 17:44 on Sep 14, 2012 |
# ¿ Sep 14, 2012 17:26 |
|
McGlockenshire posted:This is the straight-jacket of inheritance. If you want behavior shared between classes, it's going to be beneficial to share the code as well instead of doing c&p. Nothing in C++ required this approach. You don't need a scripting language to avoid misusing inheritance.
|
# ¿ Sep 14, 2012 21:29 |
|
Otto Skorzeny posted:One of the reasons it bogs down so much late in long running games Civ V isn't much better in that respect -- they ditched python for lua. Maybe I'm crazy, but I really don't see what the big advantage is with using either of them over something that's statically typed for this. I know the games pretty well and while there's a lot of stuff going on it's pretty straightforward. There has to be some simple, statically-typed language that works with LLVM that you could use as a scripting language instead.
|
# ¿ Sep 15, 2012 00:31 |
|
ToxicFrog posted:In the case of Lua, the advantage is that it's a very small, simple language designed from the start for being compact, fast, and easy to embed - it's a configuration and scripting language first and foremost. I don't know if it was around when CiV was written, but it also has two JIT interpreters - luaJIT and llvm-lua - which are API compatible with the reference implementation and pretty fast. Speaking as someone who has worked on multiple professional games that have used lua for gameplay scripting, performance problems do get traced back to lua, through profiling, and it's really not specific to lua either. The problem for us was mainly due to creating lots of objects in lua, which all end up being dynamically allocated and garbage collected. If for every bullet or projectile you're spawning an object in lua, and all of your objects are dynamically typed and all of your function calls are on types in a dynamic language, it does cripple performance, and the worst part is, there's no simple way to parallelize the logic code that is typically implemented in a scripting language, so you end up really hurting without many options. What's dumb is that most of these things don't need to be dynamically allocated nor does the language need to be dynamically typed.
|
# ¿ Sep 15, 2012 06:41 |
|
ToxicFrog posted:My point is that these issues can be - and are in many games - solved by "not allocating shitloads of lua objects every frame" and "running independent scripts in separate threads" (which is actually quite easy to do) respectively. Also, you usually cannot simply "run independent scripts in separate threads" nor would that necessarily be a good idea or even fix anything to begin with. First, we're talking about general gameplay code that cannot easily be run concurrently with other scripts (and other code does run at the same time: C++ code runs in parallel occupying the cores that it can, but the lua is actually the bottleneck). Simply running certain scripts concurrently does not scale well, either, even if it were an actual option in our case, which it is not. ToxicFrog posted:Yes, it will never be as fast as writing equivalent code in a language that compiles ahead of time to optimized machine code, but it can be "fast enough", and evidently a lot of development teams consider that a worthwhile tradeoff in exchange for faster development and increased moddability. ToxicFrog posted:That said, I'm certainly interested in suggestions for languages that have better performance characteristics than Lua/LuaJIT while still being threadsafe, suitable for embedding, and capable of on-the-fly script editing and loading.
|
# ¿ Sep 15, 2012 17:47 |
|
Plorkyeran posted:WoW UI modders came up with a library that made this fairly easy -- by switching to manual memory management and clearing and reusing tables rather than allocating new ones. The whole thing was hilariously slow compared to the amortized cost of lua's garbage collector, but triggering the GC during combat could lock up the UI for multiple seconds. Yeah, when you have to manually manage memory in a dynamically typed language with GC, I really start to question the benefits of using that language as a scripting language.
|
# ¿ Sep 16, 2012 02:29 |
|
hobbesmaster posted:What would you expect it to do? Yeah, I'm confused as to what the problem is here. If it didn't do this, how would you define non-function-style macros that start with parentheses? Would you make a new syntax? I think this is the most concise way to do it.
|
# ¿ Sep 18, 2012 17:47 |
|
Suspicious Dish posted:The preprocessor really should always insert parens for you automatically. I can't think of a single reason for it not to. You mean have macros always expand to something parenthesized? That wouldn't work -- the are lots of times where you don't want the expansion to result in something that's parenthesized I.E. almost anything that doesn't result in an expression.
|
# ¿ Sep 18, 2012 23:01 |
|
Suspicious Dish posted:I don't think so. It already takes comments and strings into account, and certainly parses a lot of C's existing structure. Determining whether the macro expansion will result in an expression isn't that hard, I don't think. Those are all very trivial. The preprocessor basically has no knowledge of C++ or C for that matter. It doesn't even know what an expression is let alone how to differentiate one from other code. This is actually very complicated in C++. For a simple example: int( foo ) What is that? Is that an expression or is it a type? It depends on what foo is. If foo is a type, then int( foo ) is also a type. If foo is not a type, then that's an expression constructing an int from foo. Also, what about macros that are partial or potentially partial: #define foo -a What is that? Is that -a or is that the second part of a subtraction? There's a ton more stuff to consider other than what I've shown that make it impossible to determine whether or not the user actually wants parentheses, even in the case of expressions. Suspicious Dish posted:I do think that C needs something that enables metaprogramming a bit more than its current processor, but I'm not sure what that should entail. I'm with you there. Right now the C preprocessor is technically Turing complete, but it's still a bitch to do complicated stuff with.
|
# ¿ Sep 19, 2012 06:03 |
|
|
# ¿ May 15, 2024 09:24 |
|
Suspicious Dish posted:But you can't keep state when looping, which I thought was necessary. Hmm? You pass along the state as macro arguments. You can emulate fold with the C preprocessor -- Boost.Preprocessor has an implementation. In fact, you can emulate all sorts of constructs up to a given limit. For instance, you can implement recursion in the more general sense than just fold, you can do while, for each, you can even emulate mutability, and more (Chaos even has lambda functions)!. Of course, most of these library-emulated constructs have limits and you "recurse" up to a given depth. You could probably argue that because of this it is not really Turing complete, but that ends up being somewhat unimportant especially since all compilers effectively have internal limits anyway. The only difference is that the limits with the C preprocessor for recursion are library-dependent as opposed to compiler dependent. In practice, that difference doesn't actually matter. That Turkey Story fucked around with this message at 07:15 on Sep 19, 2012 |
# ¿ Sep 19, 2012 07:12 |