Okay, so I have ZERO experience with this kind of stuff, so, to me, you're talking alien language in these videos... but that doesn't mean I don't appreciate what you're doing here. I mean, one of the most incredible game developers out there donating so much of his time to teach people? That's SO awesome! I admire you quite a lot, sir. Can't wait for The Witness and greetings from Brazil :)
My transcription (didn't have the patience to listen to the full Q&A): * Array Bound Checking (ABC): By default arrays(both SoA and AoS) and strings are bound checked, for optimisation there is a 'no array bound checking' directive: #no_abc, you can also disable globally ABC, or enforce always ABC (ignoring the #no_abc directive). SoA pointers are also bound checked as they're 'fat pointers' aka arrays. * Here strings: # string ... Currently no indentation support and the must be at the beginning of the line. Strings are Unicode strings. Can be empty. * overloaded function: Overloading works as usual (and also with 'inheritance': Jai 'using' feature). One main improvement: with integer literals, the smaller int type which can support the literal is called. Works with multiple parameters. If there are several possible overload with the same level of conversion, it's a compilation error. Integer conversion are preferred to float conversion. There are 'surprising' features related to overloading on which JB ask feedback: 1) overloading is scoped: if you can find a match in the local scope, it is selected, even if there is another better match in the outside scope baz :: (a: u8) { ... } { baz :: (a: u16) { ... } baz(100) // this use the u16 version. } 2) overloading only work on constant function definition (not on functions pointers, lambda). 3) overloading induce a 'file scope'? [renox. I didn't catch this point] In the Q&A, it was precised that parametrized type cannot be overloaded currently.
I'm not the guy who asked about Rust traits but I'll explain them anyways. Basically, they're a way to define how a function applies to a certain type (basically the same as type classes in Haskell). You can imagine it as an interface in a way. It defines the basic type signatures for all the common functions found in types implementing that trait. However, due to type system limitations these are really just like methods in OOP, rather than an a way to do function "overloads". Basically to use them you first define an interface of what it will do: trait Formatable { fn fmt(&self) -> &'static str; } and then give it a definition for different types: impl Formatable for MyStruct { fn fmt(&self) -> &'static str { "my struct" } } and then you can call the function with an instance of MyStruct myStruct.fmt() On another note, I do think closures are a very useful feature for a lot of things. Having the ability to, for example, bind a function to an event with information from the current scope can be pretty useful for games in my opinion. And they are also a great way to deal with lots of data (arrays, lists, hashtables) in a generic way. As for nullable types, I think a good way to deal with it would be type-safe unions. Maybe you could do something like #no_abc on unions to make them work like C unions as an optional feature to favor performance.
I've got a couple of questions if that's okay: When does a `defer`ed statement get called? End of scope (i.e. D) or end of function (i.e. Go)? As there is function overloading, will there be operator overloading or is not needed? Can you convert strings to codepoint arrays and vice versa? What # declarations are there so far? Will you be able to add your own or is it even needed? How is the galaga game? Is there a bonus level?
Wow! Your work-in-progress compiler uses custom error messages for some features that are not implemented yet (eg math in compile-time constant declarations)? If everyone cared that much about maximizing the helpfulness of error messages, the world would probably be a happier place. Keep up great work!
I'm very excited about this project. Can't wait to try it. I'm an experienced, albeit self-taught C# developer and I've always wanted to use a language that's "closer to the metal", but I really dislike C/C++. A lot of the things you've implemented in the language are similar to what's already in C#, so I find it very easy to follow what you're trying to accomplish. A few questions: 1) I don't recall you mentioning the name of this language in the videos, so forgive me if this was already answered. Is it going to be called "Jai"? If so, how did you come up with that name? 2) Do you feel that this language would be good as a starter language to learn for new programmers? 3) I discovered these videos after I started watching the HandMade Hero videos and reading about the Handmade movement. Have you thought about porting Handmade Hero to this language? I think it would be an interesting project to test the language.
What happens if you have a struct that has two *using* statements both referring to the same struct. So as an example you have some struct Point then you have another struct that is "using" two times Point for "start" and "end", lets call this struct Direction. What happens when you pass Direction to a function that has overload for Point. Similarly what happens if you have a struct A that is using Point "x" and a struct B that's also using Point as "y" but also using A as substruct. Does passing B to a function that has a overload for point, does it error out or try to use Point y from B and ignores A has a point.
Jonathan Blow I must have missed something, but I do not get why the .. operator includes the last element ? I feel like it is a bit error prone, and a bit more verbose (since you might have to call for 0..N-1 everytime) Thanks !
Jonathan Blow have you modified #modify to not map to names? As this might cause you some trouble if you start using multiple #modify statements on the same functions and they expect different variable names. Also, have you turned off the numbering of the placeholders in the format string of your print function? if so, why?
Serge Ratke Numbering in the format string is optional. Most of the time you just want to do the numbers in order... If that is all you want, you can omit them. But if you put the numbers in, they will be used.
Does string have an ending 0 character just for the compatibility with C libraries? I love #string, D have this too. And this is a most have for meta-programming.
Hello Jonathan, I was wondering if you had given any though to push/pass semantic on function calls. I sent an email a while back and was interested if you thought the functionality was worthwhile to implement/experiment on.
When you do not want your debug build to be painfully slow. I thought I said this pretty straightforwardly in the presentation. The slower your checks are, the less you want to run with them as a matter of course.
i wonder if your ever in contact, with other great programmers like carmac, gabe, sid myers, you know game programmers, or even linus, people who would start using your programming language? Or give you any ideas or advice, on what a programming language is missing?
I'd like to know if function overloading works with named parameters, and default arguments. ie: baz :: (a: u16 = 4, b: u64) {} baz:: (a: string = "hey", b: u64 {} Where you could call: baz( b: 54) One could argue, that this is the programmer being an idiot, but does the compiler detect that and call the programmer out on it?
Plasticcaz This will produce the result you would expect: tests/demo.jai:22,10: Error: Procedure call matches multiple possible overloads: tests/demo.jai:18,15: Matched here. tests/demo.jai:20,14: Matched here.
Do other languages support function overloading across scope boundaries? I didn't even know that was a thing. I suppose if you have functions that aren't a method of a class, and you have nested scopes in which they can reside, then obviously the possibility exists, I guess. It definitely seems like choosing the most local overload that fits is by far the most obvious and intuitive way to handle it. Defining function overloads across module boundaries!? Which may be loaded at run time!? Lol, jeepers. Hmm. Can you just bind to whatever makes the most sense at the time? And then let the programmer sort it out, lol. Just give them enough information to be able to tell what happened, which it seems like you already do. I guess that would leave things in kind of an unpredictable spot, though. Well, I guess by now, this has long since been dealt with. I'll be curious to find out how..
#no_abc is a bad choice for syntax!!! People will glean from it that this language might for one moment stop closing. But we know that in JAI, always be closing.
Okay, so I have ZERO experience with this kind of stuff, so, to me, you're talking alien language in these videos... but that doesn't mean I don't appreciate what you're doing here. I mean, one of the most incredible game developers out there donating so much of his time to teach people? That's SO awesome! I admire you quite a lot, sir. Can't wait for The Witness and greetings from Brazil :)
My transcription (didn't have the patience to listen to the full Q&A):
* Array Bound Checking (ABC):
By default arrays(both SoA and AoS) and strings are bound checked, for optimisation there is a 'no array bound checking' directive: #no_abc,
you can also disable globally ABC, or enforce always ABC (ignoring the #no_abc directive).
SoA pointers are also bound checked as they're 'fat pointers' aka arrays.
* Here strings:
# string
...
Currently no indentation support and the must be at the beginning of the line.
Strings are Unicode strings. Can be empty.
* overloaded function:
Overloading works as usual (and also with 'inheritance': Jai 'using' feature).
One main improvement: with integer literals, the smaller int type which can support the literal is called.
Works with multiple parameters.
If there are several possible overload with the same level of conversion, it's a compilation error.
Integer conversion are preferred to float conversion.
There are 'surprising' features related to overloading on which JB ask feedback:
1) overloading is scoped: if you can find a match in the local scope, it is selected, even if there is another better match in the outside scope
baz :: (a: u8) { ... }
{
baz :: (a: u16) { ... }
baz(100) // this use the u16 version.
}
2) overloading only work on constant function definition (not on functions pointers, lambda).
3) overloading induce a 'file scope'? [renox. I didn't catch this point]
In the Q&A, it was precised that parametrized type cannot be overloaded currently.
hopefully these'll be more frequent once the witness is out.
I'm not the guy who asked about Rust traits but I'll explain them anyways.
Basically, they're a way to define how a function applies to a certain type (basically the same as type classes in Haskell). You can imagine it as an interface in a way. It defines the basic type signatures for all the common functions found in types implementing that trait. However, due to type system limitations these are really just like methods in OOP, rather than an a way to do function "overloads".
Basically to use them you first define an interface of what it will do:
trait Formatable {
fn fmt(&self) -> &'static str;
}
and then give it a definition for different types:
impl Formatable for MyStruct {
fn fmt(&self) -> &'static str {
"my struct"
}
}
and then you can call the function with an instance of MyStruct
myStruct.fmt()
On another note, I do think closures are a very useful feature for a lot of things. Having the ability to, for example, bind a function to an event with information from the current scope can be pretty useful for games in my opinion. And they are also a great way to deal with lots of data (arrays, lists, hashtables) in a generic way.
As for nullable types, I think a good way to deal with it would be type-safe unions. Maybe you could do something like #no_abc on unions to make them work like C unions as an optional feature to favor performance.
I am very much looking forward to actually trying the language :) goodbye c++
Lau Maack-Krommes Except that most APIs and libraries for game development are built with C or C++.
+Lau Maack-Krommes I like c++. I also like jai. I haven't seen any convincing arguments for quitting either.
I've got a couple of questions if that's okay:
When does a `defer`ed statement get called? End of scope (i.e. D) or end of function (i.e. Go)?
As there is function overloading, will there be operator overloading or is not needed?
Can you convert strings to codepoint arrays and vice versa?
What # declarations are there so far? Will you be able to add your own or is it even needed?
How is the galaga game? Is there a bonus level?
loving those here strings
Wow! Your work-in-progress compiler uses custom error messages for some features that are not implemented yet (eg math in compile-time constant declarations)? If everyone cared that much about maximizing the helpfulness of error messages, the world would probably be a happier place. Keep up great work!
wohoo, I've been waiting for 2 months!
I'm very excited about this project. Can't wait to try it.
I'm an experienced, albeit self-taught C# developer and I've always wanted to use a language that's "closer to the metal", but I really dislike C/C++. A lot of the things you've implemented in the language are similar to what's already in C#, so I find it very easy to follow what you're trying to accomplish. A few questions:
1) I don't recall you mentioning the name of this language in the videos, so forgive me if this was already answered. Is it going to be called "Jai"? If so, how did you come up with that name?
2) Do you feel that this language would be good as a starter language to learn for new programmers?
3) I discovered these videos after I started watching the HandMade Hero videos and reading about the Handmade movement. Have you thought about porting Handmade Hero to this language? I think it would be an interesting project to test the language.
What happens if you have a struct that has two *using* statements both referring to the same struct. So as an example you have some struct Point then you have another struct that is "using" two times Point for "start" and "end", lets call this struct Direction. What happens when you pass Direction to a function that has overload for Point. Similarly what happens if you have a struct A that is using Point "x" and a struct B that's also using Point as "y" but also using A as substruct. Does passing B to a function that has a overload for point, does it error out or try to use Point y from B and ignores A has a point.
Reddit discussion: www.reddit.com/r/programming/comments/3fuldr/jon_blow_jai_bounds_check_here_strings_overloading/
44:09 It's not a right decision unless you can tag a scope as #strict or something that tells to compiler do not leak anything in its body.
***** But it might be a right decision because why would `print` function enter the scope then.
Jonathan Blow I must have missed something, but I do not get why the .. operator includes the last element ? I feel like it is a bit error prone, and a bit more verbose (since you might have to call for 0..N-1 everytime)
Thanks !
***** this was also discussed in the reddit topic. One idea would be to have x..y == [x,y]
x..
Jonathan Blow have you modified #modify to not map to names? As this might cause you some trouble if you start using multiple #modify statements on the same functions and they expect different variable names.
Also, have you turned off the numbering of the placeholders in the format string of your print function? if so, why?
Serge Ratke Numbering in the format string is optional. Most of the time you just want to do the numbers in order... If that is all you want, you can omit them. But if you put the numbers in, they will be used.
Does string have an ending 0 character just for the compatibility with C libraries?
I love #string, D have this too. And this is a most have for meta-programming.
Hello Jonathan,
I was wondering if you had given any though to push/pass semantic on function calls. I sent an email a while back and was interested if you thought the functionality was worthwhile to implement/experiment on.
43:00
If I wanted to explicitly say 'consider that u8 version of bad in this scope' could I do that?
+MrSnowman I was thinking this, probably not possible intentionally.
What are some of the scenarios where you would not want bounds-checking in a debug build?
Soul Studios Presents Yeah, that seemed awkward to me.
When you do not want your debug build to be painfully slow. I thought I said this pretty straightforwardly in the presentation. The slower your checks are, the less you want to run with them as a matter of course.
49:04 "it's just verboten". I am always surpruised how many German words somehoe made it into the English language
This one particularly threw me off because it sounds just like the English "forbidden" so I'm not sure what the point was of borrowing this word.
Does anyone know which font he's using? I mean the font in emacs!
Just wondering, eventually will it be possible to convert C++ code into JAI?
i wonder if your ever in contact, with other great programmers like carmac, gabe, sid myers, you know game programmers, or even linus, people who would start using your programming language? Or give you any ideas or advice, on what a programming language is missing?
you might want to use mg (MicroGnuEmacs) if that works on windows? I don't know, maybe.
How is there literally nothing usable in C++!
I'd like to know if function overloading works with named parameters, and default arguments.
ie:
baz :: (a: u16 = 4, b: u64) {}
baz:: (a: string = "hey", b: u64 {}
Where you could call:
baz( b: 54)
One could argue, that this is the programmer being an idiot, but does the compiler detect that and call the programmer out on it?
Plasticcaz This will produce the result you would expect:
tests/demo.jai:22,10: Error: Procedure call matches multiple possible overloads:
tests/demo.jai:18,15: Matched here.
tests/demo.jai:20,14: Matched here.
Do other languages support function overloading across scope boundaries? I didn't even know that was a thing. I suppose if you have functions that aren't a method of a class, and you have nested scopes in which they can reside, then obviously the possibility exists, I guess. It definitely seems like choosing the most local overload that fits is by far the most obvious and intuitive way to handle it. Defining function overloads across module boundaries!? Which may be loaded at run time!? Lol, jeepers. Hmm. Can you just bind to whatever makes the most sense at the time? And then let the programmer sort it out, lol. Just give them enough information to be able to tell what happened, which it seems like you already do. I guess that would leave things in kind of an unpredictable spot, though. Well, I guess by now, this has long since been dealt with. I'll be curious to find out how..
27:54 voice crack
Are you still compiling to C ?
#no_abc is a bad choice for syntax!!! People will glean from it that this language might for one moment stop closing. But we know that in JAI, always be closing.
closures not important? :( I was hoping we would get rid of that dreaded "data" arg on all callbacks.