Explorations in Vale

Vale was created to be the first fast, safe, and easy programming language.

Generally, languages today have one or two, but not all three.

This article will dive into the details and compare these languages.

Note that Vale is not finished, it's only at v0.1. We make it clear in the asides when we're talking about the design, rather than the implementation.

Easy Safe Fast
C++ No No Yes
Javascript Yes Yes No
Rust No Mostly Yes
Vale Yes Yes Yes

Keep in mind, this article is written with love; I picked these three languages because they're my favorite in some way:

  • C++ has the feeling of raw power and freedom!
  • Javascript is like a soft autumn breeze, easy and refreshing. 0
  • Programming in Rust feels like an addictive puzzle game! 1

This post is not meant to be a hit piece, just an honest comparison. Also note that these are just my opinions, and not objective truths!

Notes
0

(I hope this isn't quoted on PCJ!)

1

It's fun to push the borrow checker's boundaries, especially when traits and closures are involved!

Easy

Vale aims to be safe and fast while also remaining easy. 2

To get a sense of what easy means:

  • Javascript is very easy. It only takes a few days to learn enough to make a medium-sized program in Javascript. It recently became even easier with the class keyword, to avoid the (usually) unintuitive prototypal inheritance.
  • C++ is very difficult. If one sticks to the more modern features and avoids multiple inheritance, it might only take a few months to become comfortable enough with C++ to be able to write a medium-sized program. However, to write a safe program in C++ is nearly impossible. One can get very close, with good use of smart pointers, valgrind, asan, etc, but it's still difficult to avoid undefined behavior.
  • Rust is also very difficult. It's as complex as C++, but throws it all at the programmer at once. Unless you're brilliant (or come from certain backgrounds which fit well with Rust's restrictions), it's going to take you many months to learn what patterns the borrow checker likes, what kinds of tricks to use to work around it, and when to give up and re-architect your program. Eventually, you internalize these things, at which point it has "clicked".

Vale is 100% safe, which removes most of C++'s difficulties.

Vale's region borrow checker doesn't have the mutability xor aliasability restriction, which which is the source of Rust's difficulties.

Vale makes a few concessions here:

  • It's centered around single ownership (moreso than C++ and Rust), in a way that isn't complicated by the orthogonal complexity burdens of C++ (difficult syntax and compiler errors) or Rust (the borrow checker).
  • Vale is statically typed, which isn't as easy as a dynamically typed language like Javascript (in the short term, at least).
  • Vale does have more advanced features, such as inl, the region borrow checker, and mutability. However, you can write entire programs without ever needing to know these, they're just for optimization. 3

In the end, Vale is almost as easy as Javascript, and much easier than Rust and C++.

2

Vale is still v0.1 (a prototype), and its tooling (compiler, debugging, IDE support, etc.) is very young. This section factors in only the languages themselves.

3

This principle is called "gradual complexity." Other languages that do this well are C#, Swift, and Go.

Safe

Vale is 100% safe, like Javascript, and much safer than Rust and C++.

  • C++ is completely unsafe. By default, the code you write will risk a lot of memory unsafety. There are ways to mitigate it (the aforementioned smart pointers, valgrind, asan), but most C++ code will be unsafe.
  • Javascript is entirely sandboxed, and never shares memory with unsafe code. 4 You can largely trust Javascript code that someone else wrote. We do it all the time, with our browsers.
  • Rust is somewhere between. It's safe by default, except:
    • It has unsafe code which allow unsafe operations.
    • It allows bugs in unsafe code (and FFI 5) to trigger memory unsafety in safe Rust code.
    • A Rust program will bring a lot of unsafe code in via dependencies.

Vale has no unsafe, and uses extern isolation to make it so bugs in C code can't trigger memory unsafety in Vale code. You can read more about this at Absolute Safety in Vale.

4

Specifically, Javascript can use FFI into other languages with webassembly, but it doesn't share memory with them, it only sends immutable values back and forth.

5

This stands for Foreign Function Interface, and refers to how Rust can call into C code.

Fast

Vale aims to be as fast as Rust, almost as fast as C++, and much faster than Javascript. 6

  • Javascript uses dynamic typing and garbage collection, which both cause some overhead.
  • Rust is very fast. The borrow checker indirectly incurs only a little run-time overhead. 7
  • C++ is the fastest. It lets you do anything you want, with zero overhead.

Vale's hybrid-generational memory uses generational references and scope tethering to make very fast code, with very little run-time overhead. 8

Vale also uses regions to make it much easier to harness alternate allocation strategies.

In practice, Vale could be:

  • Faster, because it can use faster allocation strategies more easily.
  • Slower, because the default behavior is to let the compiler use aggressive static analysis to decide whether something's "inline" or on the heap. 9 10 11
  • About the same!

For more thoughts on Rust and Vale (and other languages), check out Beyond Rust: Innovations in Safety, Speed, and Flexibility!

Intended Use Cases

It's important to keep in mind that Vale, C++, Rust, and JS have different strengths which makes them suitable for different use cases.

Compared to Vale:

  • Javascript is very simple: dynamically typed and garbage collected. This makes it better than Vale for scripting, prototyping, and UI.
  • Rust imposes a lot of extra complexity on the programmer, but makes memory handling more explicit. This is better for things like embedded development or other overly-memory-constrained environments.
  • C++'s strength is in the freedom it gives the programmer, to get maximum speed. Vale has constraint references and an unsafe mode with zero overhead to get equivalent speed. However, C++ allows low-level unsafe operations where Vale does not, so it would be better than Vale for cases that need unsafe low-level operations. 12

Vale's combination of speed, safety, and ease are universally useful, but it will particularly shine for:

  • Servers. Servers handle a lot of untrusted input, so 100% safety is critical. Vale aims to be the fastest 100%-safe language.
  • Games, because it's extremely fast, with memory safety to prevent odd bugs, while still being easy and flexible enough to allow quick iterating and innovating.
    • When a game needs maximum performance and cares less about safety, one can switch to unsafe mode, to get C++'s speed. 13
  • Web/Android/iOS apps, because of its cross-compilability and easy interop with host environments. 14

I hope you enjoyed this article, and as always, feel free to leave any comments in the r/vale subreddit or swing by our discord server!

6

Until we finish HGM and have benchmarks, this is a goal, not a claim.

7

See Beyond Rust: Innovations in Safety, Speed, and Flexibility for more on the borrow checker's indirect run-time overhead.

8

This is still being implemented, but you can read about the design at Hybrid-Generational Memory!

9

This behavior keeps single ownership and move semantics easy.

10

One can override this with the inl or yon keywords for a specific allocation. (yon is a temporary name, we're still weighing better keywords.)

11

Vale could have a file- or function-level compiler directive to require inl or yon keywords on every allocation.

12

Vale instead uses FFI to call into another language (such as C, C++, or Rust) to do the low-level operations for it.

13

With regions, it could be faster than C++ in some cases.

14

See Seamless Speed, Safety, and Reuse Without Frameworks for more on the apps case.