Hacker News new | past | comments | ask | show | jobs | submit login
Mun Programming Language (mun-lang.org)
148 points by doppp 10 days ago | hide | past | web | favorite | 81 comments

One of the creators here. I appreciate the upvotes but its way too soon for that. Mun is currently in the very very early stages of development. It originated out of frustrations with Lua game development at Abbey Games. Lua is a great language but lacks performance, refactoring functionality and doesn't scale well with modern technology. However, there is no real alternative when it comes to code iteration times.

I do understand some of the comments questioning the publication of a website for a programming language that isn't even finished. Our goal was to have a platform to share progress and gauge interest on the topic to further help us develop Mun. We feel like there is no point in developing a programming language in private. Instead we want to actively engage with the community while developing Mun.

The website does state that its still in very early development. Should we emphasize this more?

From the Syntax section:

> We take inspiration from a scala of application, scripting, and systems programming languages

The word "scala" reads really oddly in that sentence; none of the English-language meanings of the word [1] fits, and to a technical reader it's just asking for confusion with the Scala language. Maybe replace with a clearer and less formal "bunch"?

The syntax shown looks very Rusty, and I believe this started as a thought experiment for Rust. Do you see value in keeping that link explicit? That is, using Mun as a prototyping language for early iteration, then "freezing" it to vanilla Rust with minimal syntax changes once happy with the result?

Also, if the goal here is fast iteration, it'd be interesting to see some ballpark figures for compilation times, which is one of Rust's major Achilles heels today.

[1] https://en.wiktionary.org/wiki/scala#English

Agree. Or, if need for something more formal, ‘range’.

Or ‘variety’ or ‘plethora’

Can I suggest that what you wrote here is actually a much better opening motivation than what’s on your site?

1) We like this thing that fits into the following use case 2) But we feel it has the following limitations 3) Which we’re planning to address like this.

I think it’s really important to establish what ecosystem slot you’re aiming at. If it makes it to others, fine.

The two things I would recommend for clarity.

State that it is not suitable for production yet. Perhaps a link to show the most advanced program that currently exists to show where the limits are.

If you are seeking donations, be clear about _who_ you are. Otherwise you could be seen as a scam project.

Thank you, we will incorporate that. Can you elaborate on what the things are you are seeking about who we are?

> Lua is a great language but lacks performance

Come again?

I was under the impression that Lua, especially luajit, were incredibly fast languages

Sure, it's quite good, but maybe they want performance closer to Rust?

Still, there's probably a way of phrasing it that doesn't make it sound (to those not in the know) like Lua is slow.

>The website does state that its still in very early development. Should we emphasize this more?

Yes the Work in Progress Part should swap its places with Pillars. And it should include "Pre Alpha" in it. So we know what stage it is in.

What does mun plan to do that will improve performance over luajit?

LuaJIT performance on PC is very fast when its using the JIT. However, on consoles and some mobile platforms JITing is not allowed due to not being allowed to write to executable memory for security reasons.

Mun compiles to machine code with LLVM so it should be very fast as well, hotloading overhead can be completely removed in builds where hotloading is not required (production builds for instance). Mun should therefor be able to run as fast as native code on all platforms.

Since Mun targets LLVM could it also be output to WASM to be using in-browser for HTML5 builds?

In theory yes, but we have to look into that some more. At this point we only target Windows, MacOS and Linux but WASM is definitely on our list.

LuaJIT is not available on every platform. Love2D for example is pretty slow on iOS, especially at computing paths etc for custom draw calls.

Defold is slightly different, still allowing Lua scripting, but not more than that, which is the appropriate place for Lua in a mobile-dominated market.

CoronaSDK uses Lua for IOS, Android, Windows and Mac. Our experience is its performance is sufficient for lots of games

After reading the web site, I looked at the sources (e.g. mun/crates/mun_syntax/tests/data/parser/ok/) because my disbelief was unusually stretched, and it seems that the examples and explanations in the almost nonexistent documentation cover fairly well the almost nonexistent features.

Why publish a project that, while already showing technical proficiency (the Twitter timeline suggests only 2-3 months of work), is still a very long way to do something useful, let alone compete with other programming languages? The fashionable web site layout adds insult to injury instead of looking good.

I've been working on a game project over the past year. Everyone I had shown videos to was supportive. I felt like I got a lot done in a short few months. But no one other than myself had gotten their hands on the game proper.

I had planned on doing a single point of release when it was finished. I'd done that with a game release before however. After months of work release day came, the game flopped, and by a week later it was more or less lost to the void. Not wanting the same to happen on this project I changed my mind and released it as it was one random weekend.

It had very little documentation, and even worse known bugs and crashes. But a couple people downloaded it and one guy liked the concept enough to kick me $5. By the next week I had some more info on what those people liked and what they could live without. I had motivation to fix some bugs that I had learned to work around in my using of the game. My development rate on the game has gone up significantly since releasing it in an unfinished state, and the community is very small but two months later the game hasn't dropped into the internet void.

I can sympathize with the mindset of "I've been working on this in a vacuum and just want someone else to see it, warts (or lack of content) and all". In my case it's worked out for the benefit of the project as well.

Why not publish? What's the problem with developing in public? I think it's just welcoming for potential contributors, if anything.

Compare with a language like Jonathan Blow's "Jai", which is developed in private with update videos published every now and then. Sure, that's one way to do things, but personally I much prefer being able to follow the progress of a project more on my own terms, with the source in my hands.

There's not that much work done to be able to comment something about this language; maybe it would be interesting after about a year or two.

It is entirely possible to create a statically-typed language with C-like performance and scripting-language-like interactivity (the most similar is Julia, which also uses LLVM under the hood), but the details would be pretty complex enough to make this quite a big project.

Still, it's good to see there are languages other than Jai trying to compete in the rather niche gamedev programming space.

Can we have a consistent function notation

fn name(a: int, b: int) -> void {}

This also helps with clean functional type arguments.

swift and rust support this.

A single consistent notation will be helpful for new polyglots.

IMHO, "fn add(a: int, b: int): int" is far more consistent than "fn add(a: int, b: int) -> int". At least it is self consistent.

Having -> denote a return variable has the benefit that you the syntax "a -> b" is non-ambiguously a function type.

For example, a function that accepts a function as an argument can be written:

    fn foo(f: int -> string)
Or if the argument name isn't needed in this context (e.g. think interface declarations):

  fn foo(int -> string)
If you see ":" as meaning "has type", then using it for a return type isn't necessarily more consistent, because it's not the function that has a type.

In functional programming (the origin of this syntax),

  add(a: int, b: int): int
can be read as a function 'add' when applied to the parameter tuple (a: int, b: int) has type int, I believe Ocaml, SML, actually support this syntax, whereas '->' (arrow) is a function type constructor in functional programming with 'A -> B' denoting a function from A to B. The type of add by itself in a language like Haskell would be:

add :: (int, int) -> int

Not quite, in ML languages, a function declared like this:

  let sum a b = a + b
...has the type:

  float -> float -> float
Same in Haskell.

These languages "emulate" multiple arguments through partial function application. OCaml does not use tuples for arguments.

You can certaintly have tupled function arguments in SML/Ocaml, in fact that seems to have been the more common style there, whereas Haskell uses curried functions more commonly.

As far as the original sugestion, using '->' (arrow) to denote a return type (like Rust) is nonsense in a functional language and kind of butchering the functional inherited syntax IMHO.

I've never heard of OCaml tuples being more common in arguments. If anything, my impression is they're discouraged (in OCaml, not SML) as a replacement for curried arguments. E.g. see [1].

> is nonsense in a functional language

SML/OCaml and Haskell all use ->, so I'm not sure what you mean by this?

[1] https://stackoverflow.com/questions/10666913/why-prefer-curr...

It is quite common in SML/ML code I've encountered, probably not as common in modern OCaml. BTW, in OCaml

  let add ((a:int), (b:int)) : int = a + b
Works just fine, whereas:

  let add ((a:int), (b:int)) -> int = a + b
is nonsense, because '->' is a type constructer in OCaml (a function from types to types) not part of an ad-hoc syntax for function declarations (like Rust).

Right, I'm not sure with OCaml is inconsistent there. -> is also used in pattern matching and in the syntax "fun x -> x + 1", perhaps it's some historical thing to avoid ambiguity?

The above usage of -> is a syntax error in OCaml, -> can be used in the left hand side of a let expression, but only as part of a type expression. As you say the other usage is used to construct terms (clauses) that are used in pattern matching, of course Haskell does something similar.

The Rust syntax seems to emulate functional programming, but inconsistently since -> is not used purely as a type constructor or term constructor something like a mix of both in the defintion of functions, also it doesn't seem to support currying.

Some reasonable, but I see a new inconsistency here. Shouldn't

    fn foo(fn (int) -> string)
be more consistent?

It's not inconsistent, just terser. You could say that "fn" declares a function by name; the type of foo is int -> str.

In Haskell, this is written:

  foo :: int -> str
Of course, Haskell is based on lambda calculus, so multiple arguments are just a generalization of partial function application:

  foo :: int -> int -> str
(A function taking two int arguments and returning a string, which is indistinguishable from a function that takes a single int and returns a function that takes a single int and returns a string.)

Ah, looks both have their own rationality. ":" is ok for single-value returns. AS3 also uses ":".

The Haskell language looks interesting. Maybe I should spend some time to study it.

Thats precisely the reason its written like that in Mun

Can we have a consistent function notation

void name(int a, int b) {}

C, C++, Java, and C# support this.

A single consistent notation will be helpful for new polyglots.

Or func add(x int, y int): int { return x + y }

This way it would be consistent with how variable types are declared.

I was honestly just trying to show how ridiculous of a request GP is making.

What's the purpose of the stylized ASCII arrow "->" / why is it needed?

Intuitively, `a -> b` is normally interpreted as "from `a`, I can get `b`".

A function of type `Int -> String` allows you to get a `String` from an `Int`.

The proposition `A -> B` (`A` implies `B`) means that `A` being true allows `B` to be true; we can deduce `B` from `A`.

For the link between functions and implication, see: https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspon...

I don't think it makes sense to say `fn read(s: string) -> int` as in Rust though. If an arrow were used in such a function declaration, it should probably look something more like:

  fn read: (s: string) -> int
As another commenter has indicated, `fn read(s: string): int` states that `read(s)` is of type `int`, which is logical.

The thing about adopting the ASCII Art pseudo arrow is that it bakes in an assumption that the dash character lines up vertically with the point on the angle bracket character. This simply isn't the case in plenty of fonts. So it often looks like crap if you pay attention.

Which fonts does it not look good in? Haskell, Rust, Swift, Ocaml, and I'm sure some others, all use this notation. And I've never seen the '->' look odd in any font I've ever used.

> And I've never seen the '->' look odd in any font I've ever used.

Funny; I'm reading this in a HN android app; I don't know which font it uses but I swear I'm staring at such a misaligned example.

I just went to the Rust homepage and clicked until I found an example of a function. It's being presented in Monaco where the dash is noticeably higher than the centre of the angle bracket.

I haven't used anything other than linux for more than a decade so that probably explains it. Still, I've never heard this complaint before.

Looks like it denotes return type? Are you implying it can be omitted syntactically because the closing paren implies the return type would follow?

Depends on the language but in Haskell, the (->) arrow is a function type constructor (i.e. constructs function at type level) where a -> b constructs a function type from a to b.

This is often chained to produce functions that 'take multiple arguments'. i.e. a -> b -> b. I put that in quotations because in reality all functions take only one argument, this is called currying. It gives functions flexibility in that you can partially apply them at will.

In languages like Rust and Swift, the syntax is (a: A, b: B) -> B. Because these languages are "uncurried", they use the syntax of uncurried functions. Meaning, they cannot be readily partially applied.

You mean like in Go?

    func add(x int, y int) int {
        return x + y
I doubt this is more readable, but everyone has their own taste.

This is written in Rust, and the reloading mechanism looks like it aims to hot reload Rust libraries. So this could be used as a development workbench to glue together Rust libraries, think Python gluing a bunch of C++ libs together.

Language wise, it looks like it is in the Swift/Julia/Haxe space but with first class support for Rust. This looks interesting, I wish them luck and would love to use this in the future.

Two other languages to check out are

Dyon, https://github.com/PistonDevelopers/dyon

Gluon, https://github.com/gluon-lang/gluon

Dart, Java, and I assume other languages have some support for hot reloading. It would be interesting to read how they plan to do it better.

It looks like the intent of this language is something that can replace Lua as an embedded language in games and other applications that require scripting, without the overhead of requiring JIT compilation to be performant (which you can't have on iOS). The JVM is a bad candidate for that. I believe Dart uses JIT as well.

Dart can do AOT compilation as well.

I think a modernized Lisp (the program is composed of many tiny expressions that can be reevaluated) can shine when hot-reloads are highly desirable.

Isn't static typing kindof clashing with the hot reloading focus anyway? Maybe make it possible to add the types later.

I just started learning and using Nim[0] (which recently hit release 1.0), this language appears to be very similar - statically typed, can use llvm, cross-compile, similar looking syntax. I'll be keeping an eye on this language as it looks like it will pair well with Rust. Looking forward to seeing some documentation. Keep up the good work!

[0] https://nim-lang.org/

Standard "new programming language" question(s): What's the memory management aspect like? Is there garbage collection?

LLVM has some support for garbage collection, but I've never heard of any language implementors actually being happy with what it offered in terms of features, correctness, and performance. (Counterexamples would be welcome.)

To me the most ideal form of hot-reloading and runtime compilation is probably the approach found in Scopes. While it leverages the LLVM MCJIT, it takes the approach of having compilation done when the programmer specifically wants it to be done, making it less of a "JIT" and more of a "runtime AOT"

From the goals and bits of code, this looks a lot like Zig. What about Mun makes it distinct from Zig and the other little imperative LLVM languages that have been coming out recently (Zig, V, and a couple others come to mind)?

Mun is primarily focused on hotloading, the ability to change your code while its running. Our goal is to enable hotloading of all constructs including structs (similar to how Lua works) and without having to annotate anything.

So, why do we need yet another language to reap hot-reloading, instead of adding it to say Rust, Zig or (blow me) Jai? Is there something about those languages that complicates hot-reloading?

Jai is actually closed source, so that was not an option. But in general there are no predefined best practices for achieving hot reloading of both functions and data. Experimenting with those while also fighting with complex compilers makes the problem space exponentially more intractable.

The syntax of code snippet looks like go and typescript, they don't support hot reload thought. Why do you choose to create a new language, instead adding features you miss into existing language ?

Too early for KSP jokes? Munshot language?


1. Mun exists because of frustrations with Lua.

2. Lua means "moon" in Portuguese.

3. The "moon" in KSP is named: Mun.


"Mun" means "my" in Finnish.

How do you pronounce "Mun"? Does it rhyme with "sun" or "soon"?

like sun and mundane

Off topic but it would be cool to have function types use just > for brevity, such as “add: int>int>int” and have equality operators use two characters, such as << >> >= <= ==.

To be honest, I was fatigued the moment it looked like just another programming language. After seeing there is absolutely no documentation, I don't even understand why anyone would upvote this.

I think negative top level comments are discussion derailing not constructive.

That's true, but it's easy to blame the comment more than the upvotes, which are arguably the worse problem.

Nearly any first post comment will get upvotes, if the sentiment of a first post comment is negative, it steers the whole discussion in being over critical. First post and top comments provide a positive feedback loop that is often too hard to overcome.

I don't know what the answer is, but I think internet points make things worse in general. I'd love to see a forum with sentiment analysis built in and automoderators that dynamically reorder or weight posts so as to not encourage gaming the system.

Maybe upvotes on critical comments should count for less?

The problem is identifying the critical comments. Sentiment analysis doesn't work, as far as I can tell.

You're right that the problem is much worse when it's a first post. Threads are so sensitive to initial conditions.

The site says that it's in the very early stages of development. Would it be better if they iterated completely in private?
skrebbel 10 days ago [flagged]

Why are you on site called "hacker news"?

Please don't respond to a bad comment by breaking the site guidelines yourself. That only makes this place even worse.


Good point, thanks.

Documentation encourages hacking, not the other way around. People are usually substituting previously-learned docs when there isn’t any. Especially for a language, though, understanding the intended use and the direction the language is growing helps prevent undocumented or unintended usage, and early obsolescence.

Edit: seems like some basic syntax docs could be generated from their source, actually. https://github.com/mun-lang/mun/tree/master/crates/mun_synta...

Oh come on, people can't show off their projects anymore until they're perfect? This habit of immediately searching for the flaws of whatever gets posted is not helping anyone. If you want polished well presented shit, go to techcrunch or something.

Of course, but this project is like a car maker inviting the press to present a new model and showing a couple different windshields ("we aren't sure about the angle") and not even a picture. There are standards: a car needs complete prototypes, and a programming language needs something that it does better than the competition and a decent explanation of how cool it is.

Every user will prefer Turing completeness (first order functons with no control structures aren't enough) to hot reloading.

Let's say technical documentation says

>Message content is ended with \0 byte, followed by a digit between 0-10 describing font colour.

What hacker does is pass `\0\0` to check if null byte is valid digit or painfully crashes system an if invalid values are handled correctly when error handling mechanisms aren't described in documentation. I think what you mean by hacking is closer to RE.

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