JAI Primer: A Programming Language for Games
sites.google.com
sites.google.com
Until the language is actually released, at least in an alpha version, writing a tutorial is just speculation. Anything can change in the actual language implementation.
That being said, the author initiative is laudable if you don't want to watch a few hours of Youtube videos.
Watching Jon Blow's videos I could tell this was something my friend would be interested in, because the problem space is very similar: you need realtime performance, can't afford even the slightest garbage collection pause, etc. However, I could not tell my friend "go watch videos for six hours".
Thanks to Jorge Rodríguez, I can email my friend a document that will take him less than half an hour to read.
"If you want to never get any work done, use a programming language like this: https://isocpp.org/blog/2012/11/universal-references-in-c11-... "
I used to enjoy programming in C++, even though I always thought it was too complex. Too many things to learn and too many approaches. For example, I never could grasp template-meta-programming thing. May be I didn't dedicated enough time, but that's the point. If it takes so much time to learn the language and its complexities, you have much less time to program "things" with it.
At this point, he compiles Jai to C, and the compiler isn't too gigantic yet, so there's not a huge surface area to look for compiler bugs.
Well, for one, you can't just transpile to ANSI C, compile, and end up with sensible debug symbols in your binary. You'll end up with debug symbols for the C code, not the original language. So you end up writing in one language and debugging in another. This is one reason most new languages target LLVM.
Backtraces will sort of work (although the name mangling will leak through), but little else will. You really need to generate DWARF directly in your frontend in order to have an acceptable debugging experience.
Doesn't that depend entirely on how similar your language is to C? ;)
And also this particular feature is close to my heart, because what I would like to see as a feature(s) in programming languages that the programmer would only supply the data schema, and compiler selects the actual data structure based on run time performance characteristics of the program.
I don't know well enough how they compare to give any thorough analysis, though.
However, I just see C++ continuing to get better and better for games programming. The recent appearance of the Core Guidelines [1] (and the eventual codified form for compilers) will be a huge leap. I wish we had full #run-type control over the compile phase, but full constexpr support is a step of the way there.
1. https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC...
Nice to see #run similar to elixir macros.
Rust is a multi-purpose language, with an emphasis on clever type systems. That's not Blow's focus.
He wants there to be a clear path between simple code he's writing and the fast compiled code that results. He likes C, specifically this quality: you can reason about what the hardware is doing, and write C, and count on it doing exactly what you want. His emphasis in the work he's doing is to make a memory-foundry language that stresses this kind of power, with less of C's warts (and non of C++'s).
Mundane example: he has created a not-annoying function pointer syntax. Less obvious: he has created a high-level syntax that appears to be array-of-structs, but which you can /reason/ will be compiled to struct-of-arrays for caching purposes.
I've yet to see any deal breakers(custom allocators are coming) and I've not yet crashed once(!) in my entire time using it. Try that with C/C++/ObjC/etc. With functional approaches to polymorphism combined with an ownership model that I really like and I think we could see Rust make some serious in-roads in the next few years.
OK, but that's why glium is so popular (quite possibly the preferred OpenGL binding in the community nowadays?), which has very low overhead while maintaining OpenGL safety.
ioctls have similar wrappers for the important ones.
Anyway, the general principle I'm trying to get at here is that when you're in a field that requires specialized expertise beyond general-purpose programming, the domain problems tend to get much, much bigger than the problems posed by generic "unsafe" operations. It's sort of an Amdahl's Law thing. Even a language that gets (lack of) pointers and array bounds checking and the like 100% correct can only possibly save 5% of your hair from being pulled out.
That's not my experience, and I work in a very specialized domain (at the moment, OpenGL, in fact). It doesn't eliminate all the bugs, but memory safety saves me a lot of time.
He's not wrong. The rust community approaches everything from the standpoint that we should be forcing devs to code in a particular way because safety. What I like about Blow is that, so far, he's big into giving the dev options along with some (completely optional) syntactic sugar. The focus is on functionality, not ideology.
I understand that many people's ideology align better with Jai compared to Rust. On the other hand, many other people's ideology align better with Rust compared to Jai.
No, I'd actually be perfectly fine allowing the safety features to be turned off, and have suggested it several times. Nobody has seemed particularly interested, though, because what people tend to find is that safety ends up being good for productivity as well.
My favorite Hoare quote given at his ACM award speech in 1980, referring to his work in Algol during the late 60's:
"Many years later we asked our customers whether they wished us to provide an option to switch off these checks in the interests of efficiency on production runs. Unanimously, they urged us not to - they already knew how frequently subscript errors occur on production runs where failure to detect them could be disastrous. I note with fear and horror that even in 1980, language designers and users have not learned this lesson. In any respectable branch of engineering, failure to observe such elementary precautions would have long been against the law."
Blow has said many times: he doesn't think the language should be prevent you from shooting yourself in the foot, because sometimes that means preventing you from doing what you want to do.
He usually asks: what is something simple we can do that will give us 90% of the benefit, without adding a layer of overhead. Rather than Rust's "Safe All The Things!" approach, bounds checking is just another tool you can use or not use as is appropriate for the context.
That's pretty much exactly Rust's philosophy as well.
> Rather than Rust's "Safe All The Things!" approach, bounds checking is just another tool you can use or not use as is appropriate for the context.
Rust's philosophy is not "Safe All The Things". It has "unsafe" for a reason.
Anyway, I really dislike the overfocus on bounds checks, because they're pretty much zero overhead if properly implemented and optimized.
Can you cite where this happened? This sounds like it was an executive decision, but as I recall the community was opposed to a switch to turn off bounds checks. (Rightly so: the overhead of bounds checks is near zero.)
As I recall, there were some people asking for a bounds check switch, but they were mostly people coming from the D community and new to Rust who were asking for a copy of the -noboundscheck switch (without benchmarks to show that it would help). The more interesting option would be something to turn off the lifetime, borrow, and mutability checks. But when I suggested this, almost nobody seemed particularly interested.
As a matter of fact, I am interested in -noboundscheck switch. The motivation is so that people can easily confirm bound checks overhead is zero by themselves, because it seems many people find this hard to believe. I didn't submit a pull request implementing this (it is easy to implement) because I thought it was fait accompli. Was I mistaken and you will support such pull request?
I'd rather play a game that performs a little poorly than a game that crashes. I gave up on Dragon Age Origins due to how buggy it was, for example. I've also refrained from buying games that looked great due to bug reports. I can't tolerate a broken product, but I can tolerate one that doesn't perform quite as well as I'd like.
Therefore, I think giving up on safety in favour of performance is a bad idea. Sure, its possible to write good code in any language, but the fact is people make mistakes, a lot and software is, in general, extremely buggy.
Of course, I understand that not everyone thinks like me and the "average gamer" is possibly much less forgiving for performance problems than I am, so Blow of course is doing what he feels best serves his goals for the market he's in.
Profilers do exist.
At the moment, I think it would be a volunteer with a mission: I'm not aware of anyone who's even directly indicated that they'd like this feature anywhere official yet, let alone made a proposal. That doesn't mean it's bad, I just mean it's not directly on our radar at this time.
His tooling is so far behind anything all other languages have that I would never bother to learn this language, because it was "for games."
If I wanted to make a game I would learn any engine using any number of language bindings.
There's a reason it's not released.
And it's great that you can just pick up an engine, but someone's gotta write that engine, and there's a reason triple a studios aren't using unity for major releases; you'll never get quite as good performance out of a general purpose engine as you would from a custom one.
They are, however, using Unreal Engine for tons of major releases.
Still, it's a very profitable game by a triple A company.
They basically had to use an established engine because they didn't have the budget to build their own.
And I asked myself why Hearthstone stresses my system so much. Now it's clear.
Jai allow this for array indexing AND it also allow the reverse: reinserting array checks even when there is an 'unsafe access' operation: this way even if you made a mistake in adding an 'unsafe access' operation it's easy to find where the error is (assuming the error is reproducible of course).