nickmqb / muon

Modern low-level programming language
MIT License
772 stars 25 forks source link

Summary of thoughts so far #13

Closed wilberton closed 4 years ago

wilberton commented 5 years ago

Ok, so I've spent a few evenings toying around with the language and hacking on the compiler and here's a summary of my thoughts.

Firstly, on the whole I think the language is very well designed. It strikes just the right balance for me between simplicity and expressiveness. There are a few things I'd like to see that I think would improve it, but there are certainly no egregious design decisions that would immediately turn me away. I'm a game developer, so my use cases are mostly around writing games, or tools for games. My ideal language would be something like C99, but with the addition of generics, sane function pointer syntax, lambdas, no makefile nonsense and fast compile times. Muon seems to be tantalizingly close.

The main pain points I've hit with muon so far are:

  1. no multi-line comments. I frequently comment in/out blocks of code as I'm trying things out, and having to do it one line at a time is painful. Nestable / / would be my preference.
  2. significant white-space. I'm totally in favour of being strict about the formatting of code that is checked in to source control, but while I'm trying to iterate quickly having to fix bugs in the white-space is annoying. If it could be made a warning instead of an error it wouldn't be so bad. Also, if a single line if x {blah} was allowed, that would be good too.
  3. discriminated union for value types. sometimes you just need an array of tightly packed things, not that often, but when you do, you do.
  4. matching over enums or other types. I think I saw this on your todo list somewhere.
  5. compile error for missing default in match. As I mentioned in the other issue, I would 100% prefer a compile time error to a runtime abort, even if that means putting in empty default clauses to keep the compiler happy.
  6. lambda functions and closures. Would love to see these, I think the C# syntax for these is really good.
  7. args file. In general this is fine (and 1000 times better than make files), but ideally I'd like to be able to add a directory here and have it compile everything inside - that way I don't need to keep editing it as I add new files.

So yeah, hopefully that's helpful feedback. Also I would be happy to contribute if you're looking for people to help.

nickmqb commented 5 years ago

Appreciate you taking the time to try out the language, and thanks for the feedback, definitely helpful!

1+2. I hear you. I'm trying to find the right balance between good parser error recovery and not bothering users about whitespace issues. Once the language server is ready (#14) we should get a better idea of how to make this trade-off. If I do end up dropping the whitespace requirement, multi-line comments+single line ifs should be easy to support. 3+4+6. Correct, these are on the roadmap. Lambda functions should be fairly straightforward (mostly just parser changes and making sure that we can still recover from errors), closures are harder and won't be added for a while: some more thought around memory management/closure lifetimes is needed.

  1. I'm on the fence on this after discussing this with you in #10. I've left that open, so we can track.
  2. Filed #15 to track.

I've filed #16 to outline what I'm looking for in terms of contributions, let me know if you see anything that you'd be interested in helping out with.

wilberton commented 5 years ago

I've got one more: type names - I really prefer i8, u8, i16, u16, f32, f64 etc. I think it fits the data oriented philosophy well, plus I like being explicit about what my code is doing. I'm still getting used to inferred return types, I find them quite nice when writing code, but find they make it harder to read unfamiliar code because I need to look much further to figure out what something is doing.

nickmqb commented 5 years ago

Both are fair points.

  1. Once the type alias feature lands, people can define their own aliases for any type, including primitives. At that point there is a good chance that I'll switch to i8, u8, etc. People that want to keep using int, long, etc. can do so by defining a type alias.

I wonder what you (and others) think of the following counter argument though. Primitives in Muon are well defined; the only thing that one must remember is short == 16 bits, int == 32 bits and long == 64 bits. Learning the above mapping is a minuscule amount of effort required on the part of the programmer, considering all the things one must learn to become proficient in a language. On the upside, types like int, long, etc. are easier to mentally parse. i32, i64, etc. feel a tiny bit noisier to me, especially in the context of a declaration, e.g.:

count i32, capacity i32, capacityMask u32 vs count int, capacity int, capacityMask uint

After having paid the upfront cost of fully internalizing the above mapping, I think I can read/understand the second line a tiny bit quicker.

  1. A language server should help here, because it can show the inferred return type. Also, perhaps we can build some tooling that automatically adds return type declarations where missing. This would enable things like having a commit hook that adds type declarations. Finally, I think that explicitly specifying a return type for library functions is almost always a good idea. The standard library is a good example: it would be improved by adding explicit type annotations.
nickmqb commented 4 years ago

Closing, feel free to reopen if needed.