Hacker News new | past | comments | ask | show | jobs | submit login
Kit Programming Language (kitlang.org)
115 points by BerislavLopac on Sept 20, 2018 | hide | past | favorite | 69 comments

>designed with game development in mind

What design decision and features were made according to that? Basically, what "designed for game development" means?

Also checking the commit history, first commit [1] says that it is after a rewrite in Haskell. What was the original language and why made the change?

[1]: https://github.com/kitlang/kit/commit/4d3de98f218f2427529ac4...

Hi, creator here.

>Basically, what "designed for game development" means?

I've been doing a lot of work in Haxe, but have struggled with performance issues due to GC and memory churn. I wanted a lower level language with more control, but without sacrificing the ergonomics and abstractions I'm used to. Term rewriting and implicits are examples of features that let me layer abstractions onto a language but still maintain complete control.

>What was the original language and why made the change?

It's not up on GitHub, but the prototype was begun in Rust. Ultimately I found I'm much more productive in Haskell and made the switch.

This looks like it takes influences variously from Haxe, Rust, and Haskell, which are all great in my book. But the first thing that crossed my mind was, "could it compile to other languages besides C?"

The reason being that I think the way to really move up the baseline is to take another page from Haxe and aim for cross-compatibility between different systems languages, becoming a "language that unites them all". So that could mean relatively new and hip ones like Rust, D or Zig, or older ones like Pascal(Delphi), Fortran, Cobol...

And those are niches relative to C, but they're nearly unserved niches AFAIK.

AFAIK languages "compile to C" mainly because they use C as an intermediate representation and the C compiler as the last stage of the compile/link process, so kitlang itself doesn't need to support code generation for various CPUs, and also doesn't need to implement an LLVM frontend. Instead it uses the target platform's C compiler, which is a lot less work but has basically no downsides.

Also the C IR code might make it easier to interop with other languages, since C is basically the 'lingua franca' that all other languages can talk to in some form.

> Instead it uses the target platform's C compiler, which is a lot less work but has basically no downsides.

The downsides of leveraging a platform's given C compiler as your backend is that now you'll be spending a large chunk of time learning the hard way about all the various incompatibilities in C compilers, and adding workarounds in your frontend for the otherwise-unpatchable behavior encountered in every old version of every major compiler on every platform you wish to support.

Conversely, the advantage of using a single known backend is that you can automatically know what code your users are running when they submit a bug report, and you can fork and ship the patch yourself rather than trying to convince an upstream C compiler to accept the patch, then convince the upstream distro to ship the new version of the compiler, then convincing all your users to update their platform C compiler.

Walter Bright concurs: https://news.ycombinator.com/item?id=16195031

Kit may have an easier time of it if it's intended only for games, since that narrows down its supported target platforms substantially. The harsh truth is that most game devs only care about one platform (Windows) and one toolchain (MSVC), so at least it can tailor its output to appease MSVC specifically.

No, I'm targetting C89 (because of msvc) and there almost no platform quirks than some line length limit on msvc. c99 would be nicer of course.

Most game devs also care about consoles, which adds several more platforms and toolchains.

I've used Haxe a lot and at this point I see its wide array of targets as not only a strength but at times a major weakness. I used the C++ target most often, but didn't have access to all of C++ features because they had no analog on other targets like Lua or Python - essentially Haxe becomes a least common denominator of all its targets. Focusing entirely on C lets me have a great interop story, and C is highly portable already.

It probably wouldn't take a huge amount of effort to compile into C++!

> "Memory management in Kit is manual (no automatic garbage collection), with some convenience features to make this easier."

I was curious, but there aren't any examples of this on https://www.kitlang.org/examples.html

I am far more interested in the comparison between kit and Zig.

I'm planning to get a more detailed comparison with languages in the same space. Kit and Zig overlap quite a bit; the main difference I see is philosophical. A major goal in Kit is to be concise, expressive and eliminate boilerplate; Zig perfers to be straightforward and readable, where a function call at runtime always looks like a function call in your code. Term rewriting and implicits are examples of features in Kit that probably wouldn't be implemented in Zig. Also, Zig aims to replace and compete with C, Kit just wants to leverage it, so the scopes are quite different.

Zig is awesome - I've used it and would use it again, I'm funding the creator on Patreon, and I see these two languages as filling slightly different niches and having different pros and cons.

Jai is another popular one that originally compiled to C and is aimed at game development. Any thoughts on that?

EDIT: Your responses in these threads have been great, by the way!

it's a bit of an overstatement to call jai popular, seeing as how it hasn't benen released yet. but yes, it's a very interesting looking language, and the development notes are great.

Also Myrddin and C2 seem to target a similar niche.

I've written about c2 before. It has some things that might be nice to have in c (header files, remove ->), and some things that make Zero sense to have in a language that aspires to be c (dynamic arrays as a language feature). Ultimately, it doesn't provide anything nearly compelling enough to leave the wide support of the c world.

Or kit and nim.

Levenshtein would argue they differ the same way.

I feel like there's a gold rush on three-letter language names. It's going okay so far, but Nit and Zit and Nag had better have some nice features.

And I'm just still sittin' here waiting for Jai: https://inductive.no/jai/

Aw snap, the gold rush is real..

Apart from Nag, I second.

Ben, could you go a little into detail on what you had in mind with the term rewriting system? The sin/cos example seems a little underwhelming, since these should be evaluated at compile-time in the first place.

They seem like a variant on C macros, but without the restriction on function syntax. Maybe one could implement Python's with statement in userland, which is very nice.

It also seems to me that you could replace C++ templates, yet you do have generics. How come? What's the difference?

My intuition is that ambiguities are at least possible, so what about precedence, which AST term is evaluated first? I'm thinking of some situation where two subtrees match the rule, but you end up with different results depending on which is transformed first. E. g. if you were to define a cross product rule, and apply it to a × b × c.

What about infinite loops in rule sets? What about recursion?

What about a situation where multiple rules could be applied? Is there any way to debug the transformations? Is that what the `using` scopes are for? If the compiler was to detect ambiguities, that seems pretty expensive, because it would need to match every rule to every subtree, right?

This thing seems very, very powerful, I just find it a bit hard to grasp what you can do with it in practice, and what the limitations are. I would be very interested to hear what you ran into so far.

I think this thread captures a more interesting application of term rewriting: https://twitter.com/bendmorris/status/1041130408463687681

>My intuition is that ambiguities are at least possible, so what about precedence, which AST term is evaluated first? I'm thinking of some situation where two subtrees match the rule, but you end up with different results depending on which is transformed first. E. g. if you were to define a cross product rule, and apply it to a × b × c.

This is absolutely a potential issue, and the examples I have up now are quite bad. This is why it's important for rules to be strictly scoped. The only rules that can affect an expression are the ones you've explicitly brought in with a "using" block, or those that are defined for the types you're directly working with. Given the scoping, I think overlapping rule applications will be uncommon in practice.

>What about infinite loops in rule sets? What about recursion?

There's a sanity limit on the number of times an expression can be rewritten, and it'll show an error in that case which displays the transformations that triggered the limit (including the first, last, and any non-repeating transformations going backward from the last - so it should be very clear.)

>Is there any way to debug the transformations?

This is definitely an area for improvement. I'm planning to (1) add enforced "rewrite this" metadata that will fail to compile if the expression isn't rewritten, and (2) enable dumping not only the final AST but also all of the transformations that occurred.

It seems you've independently rediscovered extensible programming which had seen much research in the past and again a few years back. There have been a number of languages that did same thing as in your tweet (e.g. [1]) but most aren't developed anymore.

[1]: http://seed7.sourceforge.net/examples/declstat.htm

Neat, another one for my list. Seed7 allows the extension of the grammar [1]. The compiler understands a simple EBNF which doesn't distinguish between different non-terminals. The semantic checks and the transformation into a known AST are deferred to another stage.

[1]: http://seed7.sourceforge.net/manual/syntax.htm

Does the compiler build the initial AST based on a grammar, before the transformations happen? That would mean you can't expand the grammar with user-defined rules. The reason you can "implement for loops in user land" is because they're already part of the grammar, is that correct?

How abstract is that initial AST? Can you use these rewriting transformations to expand the grammar?

That is correct. I think there are tradeoffs in making the language too extensible; in this case it's changing some of the details but not the high-level semantics of how the language works. If every library looked completely different lexically, it would be a nightmare to reuse code. Users of Rust macros may already start to feel this; many libraries are implemented as essentially DSLs.

With that said, down the line I plan to add procedural macros, and those will likely be lexical (they take a series of tokens as input, which doesn't need to parse into valid AST.) If I do go that route, such macros would have to be invoked explicitly.

Well designed language! I particularly like that you took great features from Haxe such as Abstracts. So far i didn't see any WTF!?'s in the language syntax, which is rare these days. People these days can get too inventive when designing new languages. I like that you kept things readable (looking at you Rust :) . Nice work!

How is this better than Clay, other than the fact it is being maintained?



Anyone is actually using it? If so, could you compare it to Nim that also compiles to C?

If it is truly embeddable in a C program (there was some note about using this as a library in a C program), then this would be a fantastic way to augment development of software in C -- it seems to improve on the C programming language. I like the support for generics and type inference and have always wished C had that. The C interop story looks very good too.

This seems to be competing in a similar space to Zig, and especially Jai. How does it compare to them?

I commented on Zig elsewhere in this thread. Since Jai is unreleased I don't know a lot about it, but their AoS/SoA convertibility was an interesting feature (you can do this in user space in Kit via term rewriting) and I wanted to make it similarly ergonomic to pass around custom allocators.

Interesting language! I saw a "throw" in an example, but I don't see exeptions mentioned anywhere? Woulb be interesting to know why a language with performance focus has exceptions (or are they implemented differently?).

Good "catch" ;) "throw" in Kit is vestigial; there's no error handling mechanism implemented yet, and I've gone back to the design phase to consider some alternatives.

This is the first language posted on HN I like. Really nice. How is utf8 supported. What about graphical apps? Android? Web server? How's the performance?

This looks amazing! Does it support parallel/multicore programming?

Ben, would you cite Scala at all as a source for inspiration?

Certainly. I don't used Scala much but the inspiration is probably easy to see.

Any examples of games that were created using Kit lang?

It seems it is a very new language, started only few months ago so probably there is nothing created with it yet.

Kit looks interesting. But i am going to stick with Haskell.

Another programming language. God! I have no idea - what's happening to the world?

Are people not skilled enough to propose or send commits to an existing or alternative programming language?

There is Rust, Go, Julia, Clojure, and many other...

What is the primary reason to create a new programming language?

Another "too many programming languages" comment. God! I have no idea - what's happening to the world? Are people not skilled enough to evaluate new languages?

There are new type systems and static checks, integrated build systems and package managers, backwards-compatibility features, debugging tools...

What is the primary reason to complain about new programming languages?

>Are people not skilled enough to propose or send commits to an existing or alternative programming language?

How would those "alternative programming languages" you propose have been created if people followed your "advice"?

We'd still be sending patches to C and C++ or perhaps Algol?

>What is the primary reason to create a new programming language?

1) Because you feel like it and you don't need to have approval for anybody to do so.

2) Because you want to explore some particular syntax/semantics combination other languages don't offer.

3) As a training exercise.

4) To cover some very specific needs you have, and don't like how other languages do it.

5) To introduce some new ideas into PL design, which might or might not be adopted by users or by a more mainstream language.

C++ had a purpose though, to create object oriented C. A lot of these modern languages seem to be mainly made because someone could.

With so many there is also a very low chance of any of them actually picking up because the useless ones drown out the C++es.

I think people should do what they want though. If you want to make a programming language you should, just don’t expect everyone to view your endeavors as useful.

As far as your fifth point goes, new languages aren’t a good way to influence programming in general. Stuff like lambdas weren’t born in some hipster language, they came from JavaScript. Because if you want to influence, you have to make sure people actually see your stuff.

That being said. Making a PL language is a much better use of your time than whining on HN.

> Stuff like lambdas weren’t born in some hipster language, they came from JavaScript.

They did not come from JS. JS took them from Scheme. Scheme took them from ... lambda calculus? Anyways, not knocking on JS, but they did not invent lambdas by any stretch of the imagination. I do agree with the rest of your comment btw.

I didn’t mean to imply that JS invented it, I meant to imply JS made them popular to the masses.

>Stuff like lambdas weren’t born in some hipster language, they came from JavaScript.

Lambdas predate JavaScript by decades. Basically according to your reasoning JS shouldn't exist. It was created by Netscape to compete in the web browser market with Microsoft script language the moment you had Python, Ruby, Pike etc. There were no afaik novel concepts to be found in JS.

Before JavaScript embraces lambdas, everyone thought they were a bad idea. You could say something similar about jit.

I know JS gets a lot of hate on hn, but if you look at the history of a lot of modern pl paradigms, many of them got traction after years of ridicule because JavaScript brought them to the masses.

Python had lambda in 1994. JS didn’t even exist then.

Face it - people use JS because the browser happened, not because it’s original in any meaningful way.

JS didn’t invent lambdas, it made them popular. Or is it just a coincidence that every major language that didn’t have them, adopted them after they got real use in JS?

Everyone that never put their foot into a CS degree.

Even Clipper had support for closures.

>"Stuff like lambdas weren’t born in some hipster language, they came from JavaScript"

Lambdas are actually so hipster that they were cool before we even had programming languages: https://en.wikipedia.org/wiki/Lambda_calculus

As far as I know, Lisp was the first language to actually implement the idea. I actually struggle to think of any language concepts that were introduced by Javascript.

I also tend to disagree with the overall sentiment that new languages aren't a good way to influence programming. Haskell, for example, is quite a departure from a language like C. I don't think we would've ended up with the great, proven options we have today if everything was just incremental changes on some base. Sometimes you need to rethink things from scratch. It's part of the reason we don't have one language that fits perfectly for all problem sets.

C++ initial purpose was for Bjarne never to write plain C code, after his experience rewriting his nice Simula code into BCPL, he swore never to use such low level languages again.

There are plenty of interviews where he tells how C with Classes came to be.

Many of those new languages are created because C++ failed to improve C in the areas that really matter:


Actually it improved, what C++ compilers cannot prevent is for people to write C code with a C++ compiler, beyond outlawing it as bad practice.

Copy-paste compatibility with C is a burden on modern computing, but it was also what contributed to C++'s adoption during the early 90's.

Suspect that in the majority of cases it's a bit like people inventing their own (human) constructed language - it's an interesting intellectual exercise in its own right and allows the inventor to indulge in a bit of wish fulfilment by emphasising features that they personally value.

As in the human conlang case, it would be alarming or bizarre if the inventor genuinely expected others to start coding in their language, especially if it has no compelling features that are not found elsewhere: although Perl, C++, Rust and others came primarily from motivated individuals "scratching an itch", those langs were able to flourish because they fill(ed) an empty evolutionary niche.

What I do find peculiar is other people then piling in with all sorts of suggestions for enhancements and tweaks that imply that the particular hobby language in question does have a legit future out in the field.

Rust, Go, Swift, etc... are like super-tankers compared to those small "better-C" languages. IMHO, having a number of small languages that can be learned in an afternoon is much better than yet another super-tanker designed by huge consensus-driven committees/communities that try to do everything for everybody.

Rust has safety and zero-cost abstractions at it's core, they provide a by now quite stable interface. You can't just move fast and break things. You need to stabilize at some point or it's impossible to use it in real world projects that are also commitments of a certain kind. And for that stability you need some kind of consensus of what to work on and what not to do.

I think the primary value of these new toy languages is they can explore aspects freely that can't just be explored in a more mature language. Sometimes after a concept has proven useful a mature language might be willing to incorporate it.

But I wouldn't use them on a serious project, because there will probably be few libraries and maybe no long term support for it.

These are valid concerns, particularly stability and long term support. Availability of libraries applies less to Kit or Zig thanks to first-class interoperability with C. I think this is the way forward for small new languages; you can avoid the challenge of creating an entire ecosystem for your language, and just fit it into an existing one.

I'm surprised that you would lump Go in as a "super-tanker" language. I find it incredibly small and simplistic when compared to something like Rust. I think it actually has fewer keywords than C.

Go the language OK but Go rely on a GC which required lots of work..

>Are people not skilled enough to propose or send commits to an existing or alternative programming language?

I'll just comment on this part. I'm a contributor to Haxe (not so mainstream perhaps but more so than Kit.) Kit was a chance to try out some features that don't fit in well to Haxe (and in fact I did propose several of these features as additions to Haxe, and they were explicitly rejected.) Sometimes the answer really is to write a new language, because language simplicity is still important and one language can't be everything to everyone.

And of course, Haxe wouldn't exist if its creator hadn't been unsatisfied with existing languages at the time...

> Oh shit everything is already made guess I'll watch Netflix while I wait to die

have fun with that

I also find the march of new languages a little exhausting. But I handle that by just taking a glance at them and moving on. Kit never has to trouble me again and I'll have already forgotten it by the time I hit reply here. And my life will go on.

> What is the primary reason to create a new programming language?

The reason is that creating a new programming language is easier than learning C++.

For this same reason none of these languages will ever amount to anything useful. If you have the patience and foresight to bring a new programming language to fruition, then you have the patience and foresight to learn C++. You grow up and start programming in a real language.

I, uh...I know a little C++ :)

I like to think that when I'm writing Kit, I'm writing C, so I am writing in a "real language." Total interop, no real drawbacks.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact