Few questions (maybe out-dated, sorry): - Do you consider to bootstrap jai compiler? or do you have a serious side project that you develop in jai? - Is the compiler capable to optimize the loop conditions (non reloading variables at each iteration when const)? - Does the compiler capable to track the immutability to do some automatic compile time evaluation? To concatenate strings of log messages with __FILE__, __LINE__ by exemple. D string format method can statically allocate the output buffer if the size of all parameters can be determine at compile time. Such thing is great to improve performances of debug,... As there is no restriction with the way you have implemented the compiler directive I think that it can be pretty useful to enforce a lot of things on how the dev team want to manage his code base. It allows to build and execute unittests, pre-process some assets, setup development environnement,.. and maybe also enforce some coding conventions like the visibility of API through modules,... and even more, if really wanted extend the language like the Qt's moc. Maybe a good part of functions to manage the build and unittest for exemple might be enough common needs to be a part of the standard library, is it something that you consider to package with jai?
I really don't like that you have to use ^ for references, since on Nordic keyboard that require pressing shift and then another key twice, which leaves you with "^^". And you HAVE to press it twice, or else it none of them will appear.
Key locations on international keyboard are a big issue in general. If it wasn't for special native characters and the need to retain motor memory for local keyboards, I would own a keyboard with US American layout by now; it would be a lot simpler.
***** Generally programming on a German keyboard layout is just a mess. all the character {[]}\ are really a pain in the ass to type. That's why at some point I read about keyboard layouts and found out that it is insane that keyboard layouts didn't change since the 1800s. So I switched to the neo layout and live happily since then. Never looked back since I got over the beginning. A lot of people I know did the same. Maybe you should look for something similar in your language.
I'm very interested in your current work on the compiler especially all the features about application building! How do you decide what is part of the compiler and what isn't? For example, the compiler is smart enough to handle dependencies. Should it handle the package/library resolution (fetching a package/library and all their dependencies from a central place)? Another example is how localization using _ and N_ in the GNU world that requires a separate app to parse the code and gather the localized strings. Should the compiler handle that (via a like #check directive)? After all no one will do a better job at gathering the strings.
I'm very much enjoying these talks and I would love to help contribute somehow. If/when you implement objects, would you go for the "classic" style with methods and public/private/etc., the golang way with interfaces and declaring methods outside of the struct declaration, or do it more C way with functions on the objects? The "classic" style I can guess you already would not use. The golang way is very useful as you can keep adding methods when needed and interfaces can infer what the types could be without polymorphism (kind of). The c way is similar to the golang way but you have to explicitly pass the object to the function rather than the implicitly (i.e. obj_method(obj, ...) Vs obj.method(...)). If this style was used, it could work but it seems to verbose and cause the same problems as c has when trying do "OOP". I think golang has gotten a lot of things correct except for maybe 2 things which is why it is not useful (as you have previously said). Forced GC (which would be that bad for many used but it's mark and sweep) and it's concurrency model. Both of which are a no no for game dev.
there's more options ... overloaded free functions which gives you method(obj), .. and UFCS would let you call that obj.method(), defined as method(obj) outside of the class.(I really hope C++ gets this). At that point there is no difference between a 'function' and a 'method'. I agree it would be great to define functions outside of the class and separately gather them into a vtable if you want , with no upfront syntax choices. The asymmetry between functions & methods is SO annoying in C++. Rusts' system with "struct/impl" is also interesting, but they start placing restrictions on you aswell. I don't think vtables will be a priority for him anyway as they're bad for caches? sort by type.. divide into components..
walter0bz vtables are not bad for performance. The Rust impl or the Go (t *Type) would be a good thing for method implementation. I do not know which style would be better (or even something else completely) but this would be much better than the C++/Java/etc. way of defining the method within the class/struct definition.
About string comparison - in D there two comparison operators: 1) a == b tests if the objects pointed by a and b are equal (including member-wise array comparison (strings are arrays in D)). 2) a is b tests if a and b point to the same variable. Here’s an example: dpaste.dzfl.pl/f3da295ed54e
GingerGames In C the ++ operator increments a pointer by size of the object it points to (not by one). Yes, you could do it manually quite easily, but it is convinient. It frees your mind to think about more important stuff. Also the rule of least suprise - the two comparison operators do what you expect them to.
45:00 - then maybe define a validator function for a variable so that when attempting to assign a value it will first check the value before performing the assignment. It would be invisible to the user except in the case of an invalid value, but then that shouldn't be too different from trying to access an array index that is out of bounds or assign a wrong type to a variable when the index or value could be something that is determined either at compile time or run time.
YES! PLease just make everything public. I Never have problems because something was public. I all the time have problems because something was f$^& private. "But that leads tight coupling!" The situation I commonly run into is "Oh wait, I actually do need access to that, come to think of it, and in this circumstance accessing it from here doesn't really represent overly tight coupling for what I'm doing here. Now, where was that thing defined again... augh.."
You mentioned at the end that you can currently set the count of an array, my only real quarrel with that is the old = vs == thing with if (array.count = 5), which might be better fixed some other way such as making the assignment and comparison operators slightly different, or even just not letting you assign a value inside an if() or while(). I think either of those changes would eliminate a class of bug that likes to stay in hiding without adding any friction to any sort of normal case.
I usually just rewrite the conditional to have the constant first if (5==array.count) that way if you forget or typo the second = you get an error about assigning to a constant.
Say if you wanted to stack changes to an array while you're looping over it. You can't just defer the change, because the loop's internal scope closes on every iteration, editing the array as you loop over it, but if you double defer it, the loop will finish, and when the containing scope closes the changes to the array will happen in reverse order, safely out of the loop.
What about a predictable 'defer remove' which just does all the removes as it leaves the block? It means your array will still be well formed the entire time, but all deletions happen at the end of the loop. I'd think that would generally be fine for the 80% use case where you're not going to be looking back at prior element arrays you're expecting to be deleted, but instead just perfoming an action for each of them. Could also work fine for doing all those actions concurrently because you can then operate on every element of the array and know they aren't going to shift around until every element has been worked on.
This is just as bad because now your items are in the array when you wanted them to not be in the array. Which is really not good if you don't expect it. Also this method would require potentially a lot of storage. Really the right thing here is just to leave the "problem" in there and keep the situation as simple as possible. At least that is how it looks to me.
I find your talks quite interesting. It is inspiring to watch as your language is developed. But it seems that you are reinventing D. I understand that you want to do *your* thing; a language that does not solve all problems but provides good solutions for the problems that you face in your daily work. But from watching your talks it seems that 98% of the improvements that you need over C are already present in D. The major differences being the syntax (which AFAIU is WIP) and the ability describe the build process natively in the language. I think it would be beneficial for you if you look more thoroughly at what D provides. Even though you want to create something new, you will see how most of the features you need are implemented and how they interoperate. Perhaps this can give you a more clear idea how you want the different things in your language to work. That said, you should know that many people are passionate about using D for game development and that many of them want to make D a better fit for that, by contributing either open-source libraries, making the language better, etc. Since D is an openly developed language you can make positive impact on its development far more easily than in other communities. Or you can just fork the existing tools to reuse the hard work put into them ;) Some helpful links: github.com/zhaopuming/awesome-d wiki.dlang.org/ dlang.org/spec.html wiki.dlang.org/Get_involved
He mentioned that garbage collection, or anything else that might hurt performance, was a no-no for him. As a layprogrammer, I agree with that. Less safety and sanity checks, less feature bloat, more performance please.
Adrian I am not a fan GCs either, so the thing that I like most about D is that it gives me the freedom to choose the appropriate mechanic for the thing that I am building. Since its inception, it is possible to use D without the GC just by calling C's malloc() and friends (yes even alloca if you are careful)[1]. You can build smart pointers and custom memory management schemes on top of them. Unlike many non-performance oriented languages, you can link directly to other C (and to some extent C++) libraries with zero overhead (no wrappers or other interop crap). This means you can use OS-specific headers (like Win32 or Linux Kernel). Because there are a few language features that rely on the GC and it can sometimes be hard check for these, more recent versions of the compilers provide the @nogc attribute, which you can use to annotate functions. For example: void doWork()@nogc{/*... */ } Now the compiler will make a static analysis on your call tree to check if you call non-@nogc functions or if you use features that require GC, making them compile-time error. So you can mark your main() function as @nogc and stop worrying about it ;) As for array bounds checking and contract-programming checks[2], they can be disabled in release mode and are normally used for debugging in debug mode (which is the default). To sum up you can use D for games, drivers and even kernels[3]. [1]: rosettacode.org/wiki/Memory_allocation#D [2]: dlang.org/contracts [3]: github.com/xomboverlord/xomb/
Pyrosource666 I keep explicitly saying that I don't think this language is that much like D, and that you'll see that ever-more as development goes on. The fact that a few people insist on ignoring me when I say that just makes me annoyed.
+Jonathan Blow I was actually curious if I could apply this language in software defined radio which is more inclined towards low latency highly optimized code. Not being able to slice matrixes like matlab is a big pain for me when I am programming in c++. But you don't seem to be focused on scientific stuff which is fair enough
I love these talks. Just wish they were without all those sound effects. I don't enjoy listening to someone moving liquids around their mouth before swallowing or constantly producing loud clicking noises in an attempt to give me a headache.
It's big pleasure to watch each related video. !'m looking forward to see what you will achieve.
Few questions (maybe out-dated, sorry):
- Do you consider to bootstrap jai compiler? or do you have a serious side project that you develop in jai?
- Is the compiler capable to optimize the loop conditions (non reloading variables at each iteration when const)?
- Does the compiler capable to track the immutability to do some automatic compile time evaluation? To concatenate strings of log messages with __FILE__, __LINE__ by exemple. D string format method can statically allocate the output buffer if the size of all parameters can be determine at compile time. Such thing is great to improve performances of debug,...
As there is no restriction with the way you have implemented the compiler directive I think that it can be pretty useful to enforce a lot of things on how the dev team want to manage his code base. It allows to build and execute unittests, pre-process some assets, setup development environnement,.. and maybe also enforce some coding conventions like the visibility of API through modules,... and even more, if really wanted extend the language like the Qt's moc.
Maybe a good part of functions to manage the build and unittest for exemple might be enough common needs to be a part of the standard library, is it something that you consider to package with jai?
I really don't like that you have to use ^ for references, since on Nordic keyboard that require pressing shift and then another key twice, which leaves you with "^^". And you HAVE to press it twice, or else it none of them will appear.
You can press shift + ^ followed by spacebar to get it to output. But like you said. It's still quite slow to write on nordic keyboards.
Oh didn't know you could to that. It's still a huge pain though.
Key locations on international keyboard are a big issue in general. If it wasn't for special native characters and the need to retain motor memory for local keyboards, I would own a keyboard with US American layout by now; it would be a lot simpler.
*****
Generally programming on a German keyboard layout is just a mess. all the character {[]}\ are really a pain in the ass to type. That's why at some point I read about keyboard layouts and found out that it is insane that keyboard layouts didn't change since the 1800s. So I switched to the neo layout and live happily since then. Never looked back since I got over the beginning. A lot of people I know did the same. Maybe you should look for something similar in your language.
***** just remap your layout, everyone should use his own layout imo. We should all know US qwerty and use our own layout.
I'm very interested in your current work on the compiler especially all the features about application building!
How do you decide what is part of the compiler and what isn't?
For example, the compiler is smart enough to handle dependencies.
Should it handle the package/library resolution (fetching a package/library and all their dependencies from a central place)?
Another example is how localization using _ and N_ in the GNU world that requires a separate app to parse the code and gather the localized strings.
Should the compiler handle that (via a like #check directive)?
After all no one will do a better job at gathering the strings.
I'm very much enjoying these talks and I would love to help contribute somehow.
If/when you implement objects, would you go for the "classic" style with methods and public/private/etc., the golang way with interfaces and declaring methods outside of the struct declaration, or do it more C way with functions on the objects?
The "classic" style I can guess you already would not use.
The golang way is very useful as you can keep adding methods when needed and interfaces can infer what the types could be without polymorphism (kind of).
The c way is similar to the golang way but you have to explicitly pass the object to the function rather than the implicitly (i.e. obj_method(obj, ...) Vs obj.method(...)). If this style was used, it could work but it seems to verbose and cause the same problems as c has when trying do "OOP".
I think golang has gotten a lot of things correct except for maybe 2 things which is why it is not useful (as you have previously said). Forced GC (which would be that bad for many used but it's mark and sweep) and it's concurrency model. Both of which are a no no for game dev.
there's more options ... overloaded free functions which gives you method(obj), .. and UFCS would let you call that obj.method(), defined as method(obj) outside of the class.(I really hope C++ gets this). At that point there is no difference between a 'function' and a 'method'. I agree it would be great to define functions outside of the class and separately gather them into a vtable if you want , with no upfront syntax choices. The asymmetry between functions & methods is SO annoying in C++. Rusts' system with "struct/impl" is also interesting, but they start placing restrictions on you aswell. I don't think vtables will be a priority for him anyway as they're bad for caches? sort by type.. divide into components..
walter0bz vtables are not bad for performance. The Rust impl or the Go (t *Type) would be a good thing for method implementation. I do not know which style would be better (or even something else completely) but this would be much better than the C++/Java/etc. way of defining the method within the class/struct definition.
About string comparison - in D there two comparison operators:
1) a == b tests if the objects pointed by a and b are equal (including member-wise array comparison (strings are arrays in D)).
2) a is b tests if a and b point to the same variable.
Here’s an example:
dpaste.dzfl.pl/f3da295ed54e
I don't see the advantage of this over doing it manually. How is the is operator better or even be beneficial?
GingerGames In C the ++ operator increments a pointer by size of the object it points to (not by one). Yes, you could do it manually quite easily, but it is convinient. It frees your mind to think about more important stuff. Also the rule of least suprise - the two comparison operators do what you expect them to.
34:41 - why not just use the address operator to get the addresses if you want to compare addresses and otherwise compare by value?
45:00 - then maybe define a validator function for a variable so that when attempting to assign a value it will first check the value before performing the assignment. It would be invisible to the user except in the case of an invalid value, but then that shouldn't be too different from trying to access an array index that is out of bounds or assign a wrong type to a variable when the index or value could be something that is determined either at compile time or run time.
YES! PLease just make everything public. I Never have problems because something was public. I all the time have problems because something was f$^& private. "But that leads tight coupling!" The situation I commonly run into is "Oh wait, I actually do need access to that, come to think of it, and in this circumstance accessing it from here doesn't really represent overly tight coupling for what I'm doing here. Now, where was that thing defined again... augh.."
You mentioned at the end that you can currently set the count of an array, my only real quarrel with that is the old = vs == thing with if (array.count = 5), which might be better fixed some other way such as making the assignment and comparison operators slightly different, or even just not letting you assign a value inside an if() or while().
I think either of those changes would eliminate a class of bug that likes to stay in hiding without adding any friction to any sort of normal case.
I usually just rewrite the conditional to have the constant first if (5==array.count) that way if you forget or typo the second = you get an error about assigning to a constant.
6 years late but `const` gives you read-only data in C and it can be used with struct/union members.
Can you defer defer statements in the language?
why would you?
Say if you wanted to stack changes to an array while you're looping over it. You can't just defer the change, because the loop's internal scope closes on every iteration, editing the array as you loop over it, but if you double defer it, the loop will finish, and when the containing scope closes the changes to the array will happen in reverse order, safely out of the loop.
You can, it's in a few of his previous videos iirc
What about a predictable 'defer remove' which just does all the removes as it leaves the block?
It means your array will still be well formed the entire time, but all deletions happen at the end of the loop.
I'd think that would generally be fine for the 80% use case where you're not going to be looking back at prior element arrays you're expecting to be deleted, but instead just perfoming an action for each of them.
Could also work fine for doing all those actions concurrently because you can then operate on every element of the array and know they aren't going to shift around until every element has been worked on.
This is just as bad because now your items are in the array when you wanted them to not be in the array. Which is really not good if you don't expect it. Also this method would require potentially a lot of storage.
Really the right thing here is just to leave the "problem" in there and keep the situation as simple as possible. At least that is how it looks to me.
Does jai support setting a variable equal to a "null" value?
32:30 is it only me or did he get muted
Can we start some sort of charity program to buy him a pro mic?
I find your talks quite interesting. It is inspiring to watch as your language is developed. But it seems that you are reinventing D. I understand that you want to do *your* thing; a language that does not solve all problems but provides good solutions for the problems that you face in your daily work.
But from watching your talks it seems that 98% of the improvements that you need over C are already present in D. The major differences being the syntax (which AFAIU is WIP) and the ability describe the build process natively in the language.
I think it would be beneficial for you if you look more thoroughly at what D provides. Even though you want to create something new, you will see how most of the features you need are implemented and how they interoperate. Perhaps this can give you a more clear idea how you want the different things in your language to work.
That said, you should know that many people are passionate about using D for game development and that many of them want to make D a better fit for that, by contributing either open-source libraries, making the language better, etc.
Since D is an openly developed language you can make positive impact on its development far more easily than in other communities. Or you can just fork the existing tools to reuse the hard work put into them ;)
Some helpful links:
github.com/zhaopuming/awesome-d
wiki.dlang.org/
dlang.org/spec.html
wiki.dlang.org/Get_involved
He mentioned that garbage collection, or anything else that might hurt performance, was a no-no for him. As a layprogrammer, I agree with that. Less safety and sanity checks, less feature bloat, more performance please.
Adrian I am not a fan GCs either, so the thing that I like most about D is that it gives me the freedom to choose the appropriate mechanic for the thing that I am building.
Since its inception, it is possible to use D without the GC just by calling C's malloc() and friends (yes even alloca if you are careful)[1]. You can build smart pointers and custom memory management schemes on top of them.
Unlike many non-performance oriented languages, you can link directly to other C (and to some extent C++) libraries with zero overhead (no wrappers or other interop crap). This means you can use OS-specific headers (like Win32 or Linux Kernel).
Because there are a few language features that rely on the GC and it can sometimes be hard check for these, more recent versions of the compilers provide the @nogc attribute, which you can use to annotate functions. For example:
void doWork()@nogc{/*... */ }
Now the compiler will make a static analysis on your call tree to check if you call non-@nogc functions or if you use features that require GC, making them compile-time error. So you can mark your main() function as @nogc and stop worrying about it ;)
As for array bounds checking and contract-programming checks[2], they can be disabled in release mode and are normally used for debugging in debug mode (which is the default).
To sum up you can use D for games, drivers and even kernels[3].
[1]: rosettacode.org/wiki/Memory_allocation#D
[2]: dlang.org/contracts
[3]: github.com/xomboverlord/xomb/
Pyrosource666 I keep explicitly saying that I don't think this language is that much like D, and that you'll see that ever-more as development goes on. The fact that a few people insist on ignoring me when I say that just makes me annoyed.
Pyrosource666
Thank you for the very informative reply. For some reason I didn't get a notification until Jonathan's reply now.
Not having slices makes this language not very appealing to people doing linear algebra
+Francisco Paisana This is not a language for Python programmers...
+Jonathan Blow I was actually curious if I could apply this language in software defined radio which is more inclined towards low latency highly optimized code. Not being able to slice matrixes like matlab is a big pain for me when I am programming in c++. But you don't seem to be focused on scientific stuff which is fair enough
I love these talks. Just wish they were without all those sound effects. I don't enjoy listening to someone moving liquids around their mouth before swallowing or constantly producing loud clicking noises in an attempt to give me a headache.