The V Programming Language: Vain Or Virtuous?

If you stay up to date with niche software news, your ears may recently have twitched at the release of a new programming language: V. New hobby-project programming languages are released all the time, you would correctly argue; what makes this one special? The answer is a number of design choices which promote speed and safety: V is tiny and very fast. It’s also in a self-proclaimed alpha state, and though it’s already been used to build some interesting projects, is still at an early stage.

Tell me more

V’s website, vlang.io, states that it is a

Simple, fast, safe, compiled language for developing maintainable software.

Each of these keywords is a cornerstone of V’s philosophy, which will crop up throughout this article.

“Maintainable software” hints at V’s very deliberate design choices, which force developers into certain ways of thinking. In many ways, V is similar to Go, which makes similar design choices that some would consider bold. (For example no exceptions and no traditional classes/inheritance.)

V claims to be inspired by Go and influenced by Oberon, Rust, and Swift.

So just how fast is it?

V’s headline fact is that it can compile around 1.2 million lines of code per second per CPU core (of an i5-7500).

Since the V compiler itself is tiny, at 400 kB, this author got V to compile itself in well under a second. Is that fact more than a gimmick to anyone trying to write anything with V? No – but it proves a point about simplicity.

Git cloning V and then running make first compiles V using a C compiler, then uses the resulting V executable to compile itself. I had no issues running it on Linux, but had to work a little harder to get an error-free build on Windows. Actual direct machine code generation is currently only available for x64/Mach-O. However, by the end of 2019, V 1.0 should be released with support for all x64, which I can believe given the current pace of development.

Features and design choices

V is very keen on forcing you to write good code; so keen that some could argue that it can be pushy at times – I’ll leave that up to you to decide. For instance, unused variables result in a compilation error rather than a warning.

Due to the simplicity of V, the docs are very short. In fact, it is claimed that it’s possible to read them in half an hour and absorb the whole language. I’m not entirely sure this is something to boast about, given the clear immaturity of the docs due to the project being in the very early stages. But nonetheless, reading them still highlights some interesting features:

Safety

Strict policies are put in place to attempt to make V as safe as possible, especially with respect to threading. These policies include:

  • No global variables or global state (including at module level)
  • Variables must always be declared with an initial value
  • Variables are defined as immutable by default. You have to use mut to explicitly specify otherwise.
  • No variables with a name already in use in the parent scope

Memory

V isn’t garbage collected, a significant difference from Go, or even reference-counted. Instead, it’s more similar to Rust, managing memory at compile time. Unfortunately, this only currently works for basic situations; manual management is required for more complex cases, which are another WIP.

V’s creator [medvednikov] is quick to concede that memory management isn’t secure enough yet, but that it’s under constant improvement. It’s certainly something that needs to be worked on to lend credibility to the “safety” features of the language. And if there’s anything we’ve learned from the last thirty years of computer security, it’s that memory management bugs abound.

Error handling

V does not have exceptions, much like Go. We think [Dave Cheney] does a good job of explaining why.

Instead, there’s a combined Option/Result type, which is as simple to use as adding ? to the return type and optionally returning an error. Here’s an example of how it might work:

fn find_user_by_id(id int, r Repo) ?User { 
	for user in r.users {
		if user.id == id {
			// V automatically wraps this into an option type  
			return user 
		} 
	} 
	return error('User $id not found') 
}

The function returns the type ?User, which could be a user, or an error. When calling the function, this could be propagated to the next level up by calling find_user_by_id(id, repo)? (in this case the parent function must have an Optional as its return type). This means that propagating errors is still easy, and doesn’t require using the try-catch exception model.

Features coming soon

  • Inline assembly code support
  • Hot reloading – code changes without re-compiling (edit: now implemented!)
  • A package manager

These all seem like non-trivial features to implement and release quickly, but the speed of development on the project is impressively rapid.

Projects built using V

V’s creator, [medvednikov], has used it to build a number of projects.

V was actually created in order to develop Volt, a 300KB desktop messaging client capable of handling/scrolling through thousands of messages without lag. It’s interesting to note that V makes a big deal of its existing cross-compilation capabilities, and claims to be largely cross-platform, but that Volt is currently only available for Mac.

Vid is a 200KB cross-platform code editor, another project designed to be lightweight and snappy. This is due to be open sourced in July, any day now.

Vtalk is forum/blogging software used to power the V blog, also due to be open sourced soon.

Future

Here’s the graph of GitHub stars against time for V.

Img courtesy of star-history.t9t.io

GitHub stars aren’t an indicator of merit, but they’re certainly an indicator of interest, which can lead to quality input from the open-source community. There are a large number of features marked Work In Progress scattered throughout the website and docs, and I’ve got to say that some of them look really awesome; most are expected to be released by December.

It’s very easy to claim that your language is lightweight when it lacks features and has large numbers of bug fixes awaiting it; on average, every pull request and bug fix that goes into an open source project adds code rather than removes it. But if V can retain its zero dependencies and small size whilst enduring ongoing development, it may have a place in the future.

Conclusion

It’s easy to forget that all of V’s development up until very recently has been the result of one person: [medvednikov]. After playing with the language for a while, this author wouldn’t feel comfortable writing a new project in V in its current state. But if [medvednikov] can keep up the current breakneck pace of progress on the project, there may well be something to get excited about very soon. I’m not quite ready to jump on the bandwagon, but will certainly follow it from a respectable distance.

81 thoughts on “The V Programming Language: Vain Or Virtuous?

  1. The problem with all those “safe” programming languages is that people will do their best to re-invent global variables, exceptions etc. and then it becomes a mess. Ugly languages like Python, C or C++ will prevail because they just don’t care. You want to do something stupid? Go ahead but don’t cry if you get burned.

    1. This.
      I love Perl as a scripting language for exactly that reason, it just let you do your frigging job without standing in your way. It hands you a rope and lefts you to your own devices.

      1. To carry your analogy a bit further…

        And with C, once you touch the rope, it automatically wraps around your neck and ties a slip knot.
        (thanks to the “devices” of previous programmers!) It is up to you to keep from jumping off the chair, or being pushed off by someone else!
        B^)

  2. “Hobby-project” language? No need for complex memory management? Github as a metric? WIP stuff being counted on to be released ‘soon’? Geez, you kids are so easy. You wanna buy some sunny and dry and warm property in northern Scotland?

    This guy got off to a rather dubious start, see https://news.ycombinator.com/item?id=20229632

    There are so many other good language projects in development that are legitimate projects. Please look further and farther.

  3. “Variables are defined as immutable by default.”

    Sooooo….. they’re not really “variable”, are they? You might even say they’re “constant”?

    (Or are they all objects, and you reload one with a fresh object when you need to update it, like Java’s String?)

    1. “Sooooo….. they’re not really “variable”, are they? You might even say they’re “constant”?”

      Not that I disagree, but “variable” doesn’t quite mean the same thing as “mutable.” Mutable implies variable, variable doesn’t imply mutable. If a variable is declared as privately mutable, for instance, it’s variable outside the module (*it* can change) but can’t be changed outside the module.

      Bizarre naming conventions are pretty common in languages, though: declaring something “const volatile” in C is hilarious. Constant, but able to change at a moment’s notice!

      1. That’s not bizarre in the least. C’s volatile keyword is a qualifier that tells the compiler that the value of the variable may change at any time–without any action being taken by the code the compiler finds nearby. It means the compiler should not optimize it away by replacing the constant with the declared value, but instead refer to a piece of memory which some -other- process may change. This is exceedingly important, because the variable in question may be memory mapped IO.

        “const” on the other hand makes sure that YOU don’t attempt to change the value by accident, because the compiler throws an error at you when you do.

        1. You don’t see the inherent oxymoron in something that’s constant being able to change at any time?

          The problem isn’t the concept, it’s the keyword. “Const” actually means “read only,” not “constant.” Same thing as this language’s “variables are unchangeable.”

          1. This.

            Constant means read only.
            Volatile means don’t optimize me, bro.

            But as long as we’re here, “variable” doesn’t mean what it sounds like either. Variables are all constant mappings from a string to a number, which happens to be a memory address where data can be stored. Deep down in the compiler, the variable doesn’t change, just the stuff in the memory location that it references.

            Doesn’t some modern “safe” language treat variables as what they are — shared memory locations? Like, you’d obviously want a mutex for something like that…

          2. OTOH if it turns out that words are allowed to have more than one meaning, then “const” means exactly what C defines it as meaning. Same for volatile.

          3. “OTOH if it turns out that words are allowed to have more than one meaning, then “const” means exactly what C defines it as meaning. Same for volatile.”

            And same for variable in this language, and now we’re back to the original point that sometimes languages use keywords with different meanings than their colloquial usage.

  4. The three important points mentioned in the “Safety” part of the article are nice, and would avoid a lot of erros / compiler warnings. If they could be inserted in a normal, “official” language, the better.

    The 4th point, about variables not being variable, sounds strange ….

        1. No, a boolean would would contain probability amplitudes for both true and false. The true and false probability amplitudes are independent [i.e. not correlated].

          Scalars of n bits would encode values of 2^n-1 bits.

      1. If they are quantum variables, each should hold all possible values and when used, it should have the most probable value. Therefore they don’t need to be mutable – each will hold the value that is needed at a given point in space-time continuum…

        OTOH if they were Schrödinger’s variables, each would be both variable and constant and probably not declared at all at the same time…

      1. “Censorship is telling a man he can’t have a steak just because a baby can’t chew it.” — whenever a new language purportedly forces us to write ‘good’ code, it feels a bit like that. Don’t have much use for intentionally nerfed tools

        1. I’ve seen a lot of programming languages, but I’ve yet to see one that can even force you to write code in the first place, never mind the quality.

          Java is in the direction of attempting to make things “nerf.” This is more like Golang, where the things they don’t want you to have, they simply didn’t include. It isn’t that it is “nerfed,” it is that it is not nerfed, doesn’t come with a fold-out LED flashlight, and doesn’t even have a secret compartment with an emergency toothpick! It’s just the adze.

          For me the problem with it is that it is so reliant on the CPU that it only supports a subset of x86; even though it first compiles from C. That does not give me confidence that it can mature and still be fast/safe/good/etc. I vote Vain.

    1. I think the issue is what does bad V look like? Because bad c and c++ is hard to catch.

      For larger community projects it’s ideal that someone can easily spot bad code and the less opportunity to shoot you read in the foot the easier they are to spot!

      This is also kind of why Linus insists the kernel is written in C. When they were starting out he could spot bad C far easier than bad C++

      1. It’s rather more complicated that simply Linus’ opinion. As usual…

        One of the issues is time constraints. On a previous occasion it was estimated that porting the kernel to C++ would take a minimum of two years.

        The C++ advocates refused (and still refuse) to accept this of course, claiming they could do it in half the time. Yeh. Right…

  5. Yep, another alpha-quality “safe” clone of C, and this one isn’t even building on LLVM (which gets you compile targets and optimisations for free)…

    “1.2 million lines of code per second” is the shittiest compiler performance metric I have ever seen.

    1. That claim reminded me of this old joke:
      Person 1: Hey, I heard you were extremely quick with math
      Person 2: Yes, I am the fastest out there
      Person 1: What’s 13×29?
      Person 2: 51
      Person 1: That’s no even close!?!
      Person 2: Yeah, but it was fast!

    2. It has a C backend – so it isn’t a clone of C, it’s targeting C.

      So it does target LLVM via a C compiler, which gets you compile targets and optimizations, when you want them – while the extremely fast native x64 compiler gets you quick turnaround during development, running tests, hot reloading, etc.

      Frankly, it’s something other languages could learn from. Compilers today are extremely slow compared to compilers 15-20 years ago – this one is only as fast as compilers ought to be, if their performance hadn’t degraded so badly over the years.

      For all the value that LLVM brings, it’s partially to blame for the drastic performance slump of modern compilers – computers are thousands of times faster than they were in the days of Turbo Pascal, and compilation today is *slower* than it was in the 90s.

      I’m glad to see someone at least trying to bring us back towards the compile speeds we ought to be seeing today.

      1. Is compiling really slower than it was in the 90s? Or do you mean it’s not as fast as a modern compiled 90s compiler would be on the same hardware?

        I am certain compilers are faster in raw time than I remember from the 90s

  6. yeah, I wouldn’t call this “breakneck pace”. according to the author, the language has been in development for almost 2 years, and if you skim through the released code, it’s basically a buggy go-like syntax preprocessor for C that relies on gcc to do a lot of compiler work. if you watch Jon Blow’s first demo of his pet language, in a month of side-work he had way way more stuff going than this project has now

  7. Overall this simply reminds me of how disgusted I am with my brief exposure to Rust — a language whose complete lack of virtue is obscured only by its lack of implementation. But this really takes it to a new level: “unused variables result in a compilation error rather than a warning.” I’m all for gcc’s -Wall and -Werror, if you want to. Lord knows I run into warnings that represent real bugs. But this just gives you a nightmare while you are working. Just another damn hoop to jump through if you need to comment out a big block of code while you’re debugging something. As bad as Java’s “constant boolean is an error” rule. I don’t honestly believe any language is worth severely limiting your environment for (Rust on ARM is still a one-off hack, for example), but it’s really making a farce of it when the only people who want to invent a new language are the people who don’t have enough experience to know why all the previous languages sucked.

    1. This.

      But first, I’d be forgiving if it was just a cool “hey, I just read the (formerly Red) Dragon Book and made my own toy compiler/language check it out” show-and-tell project but the website is making such grandiose, and IMO naive, claims that:

      xkcd.fetch(“One More Standard”);

      I want to add good-ideas-in-theory things like errors on (harmless) constant integer-to-float conversion ( float v = 0; ) or double-to-float ( float f = 2.5; ) and throwing an error in one language while typing the same suffix in another c-family language is an error.

      Try spending your working day writing in four or more similar languages at the same time dealing with different completely incompatible nit-picky safety/syntax rules (eg: C# for Unity, GLSL/HLSL/CG for shaders, C++/C for microcontroller, JavaScript for the nodeJS server/page, all parts talking to each other, and it’s going live in a week).

      You can *almost* but not quite cut & paste that packet de/serializer, that validation check, that animation curve interpolation code, that raycasting/collision formula, + various other snippets.

      You know what my day needs? Yet another programming language!

      If you’re going to put time in and market solving some computer language problem by inventing yet another one make sure it’s not causing more practical issues than it solves.

      And Sudos pointed out this: https://christine.website/blog/v-vaporware-2019-06-23
      A good analysis of the outlandish claims.

      Don’t claim your language enforces good programming practices and STATICALLY ALLOCATE A FIXED SIZE ARRAY in the compiler for your function statement array giving a hard-coded statement limit per function.

      No wonder it’s “fast”.

  8. I’m a programming language researcher. One comment that springs to my mind when reading about fast compilation is that it certainly doesn’t do much optimization. Current compilers spend most of the compilation time in their optimizer. What we gain from that is the performance of the compiled code, which, for C-like languages, is typically as good or better than hand-written assembly. I doubt the V compiler, in its direct-to-machine-code mode, gets any points for compiled code performance; and if/when it does, it won’t be as fast anymore (and probably will reinvent LLVM in the process.)

      1. This may feel wrong, but is actually true. Computer architectures of today are so complex, with all the cache and memory coherency issues, out-of-order execution, speculation, etc. that people have a VERY hard time predicting the performance of their code. Good optimizing compilers are much better at this.
        Even for older architectures there is not much point in writing assembly for performance anymore. I have a friend who is both an university teacher and a demoscene coder, creating award-winning demos for Amiga computers. He writes in C, and reads the resulting assembly to fine-tune his code.

    1. Perhaps the pure speed of compilation is there to allow ongoing real-time compilation, enabling as you code error feedback. When a compilation that generates a binary is called for, the full optimization is applied.

      1. In my use cases whenever compilation time becomes an issue it’s because someone included Boost in the project.

        All that compiler time is spent parsing 1000s of over-engineered templates, many of which are recursive.

        On those projects turning on optimizations barely registers compilation time wise.

        On more reasonable projects optimizations can double the compilation time, if you are updating 1 game AI behaviour file it goes from 1/8 second to 1/4 second compile time.

        Everything else involved in the process of enabling ongoing real-time compilation & live patching takes way longer.

        Build speed looks like a non-issue to me at least as far as the compiler itself is concerned.

  9. Heaven help us. Not another new programming language with all the usual claims and bravado. Shoot them now before they reproduce. Will it never end? Didn’t Java make all the same promises?

    1. I wish I could upvote you.
      I’ve read that article a few days ago, it’s a pretty interesting read.
      I especially like this nugget:
      “more than 50 000 statements in function `main`”
      So the 1.2 Million claim is not achievable because it stops at 50000.

      1. It’s obviously a standardization to the nearest full unit. You take a program of x lines of code, calculate how many milliseconds it takes to compile and then calculate to how many lines you can compile per second. Nobody needs a car to drive for an hour to calculate its speed, it’s the same for calculating compiler speed.
        Even worse, the author uses a program with 1.2 million exactly the same lines of code. That’s a very bad way to measure speed, completely not representative of compiling an actual program.

  10. K&R formatting in the example code is a bad sign. It’s a nasty hold-over from BCPL>B>C>C++>Java and indicates a lack of respect for block structuring (and usually a failure to define an LL1 syntax).

    YYMV (but if it does, you’re an illiterate peasant.) (-:

      1. 90% of the semantics of a block is concerned with scoping variables. The rest – conditions and loops – is trivial by comparison. The use of braces to delimit blocks is a wonderful convenience, and I’d hate to go back to Pascal’s …, but it tends to cause programmers to underestimate the importance of blocks. K&R formatting makes things worse.

        C was an ugly cut-down version of B, which was a cut-down BCPL, which was a shitty language to start with.
        Not a great foundation for a 21st Century language.

        The LL(1) grammar issue gets overlooked now we have CPU to burn and parser efficiency is a non-issue, but context dependent junk like C’s overloading of “*” makes reading code a chore for humans.

        Let’s hope that the designers of V learned from the mistakes of the past and haven’t felt obliged to, e.g., restrict themselves to symbols from the PDP-8 character set.

        I see from the example that they’ve resolved the “terminator” or “seperator” question by dropping semi-colons altogether. A punchy start.

  11. People hating on this so hard simply for what it claims. Who cares what anything claims to do? It’s all meaningless anyway. The only real way to judge a language is to actually use it.

    Actually trying to program in this is really quite nice (save for all the broken libraries which will hopefully be fixed in due time lol). Like geez, give it a chance at least, guys. Don’t put it down for what it’s trying to do; criticize it for what it actually does.

    My hot take is that honestly, I really like it. I didn’t think I would since I’m really a big C guy, but I actually think it’s quite a nice language once you start trying to actually do something in it.

  12. Compare this language with Skew, please:

    http://skew-lang.org/

    It’s got many of the same values and ideals – but Skew has a much cleaner, structured codebase, a complete set of working high level language features, excellent error messages and IDE support.

    Yet, this language barely ever saw the light of day. I don’t think most devs gave this 5 minutes of attention when it was first announced.

    How or why is this rough, incomplete, messy little language getting so much attention?

    Put an x64 backend in Skew to get the fast compile times, and you’d already have a far more elegant and useful language – with a beautiful, maintainable codebase.

  13. So we have no exceptions, instead we have re-implemented poorly a mechanism identical to exceptions using the return statement and monads. Yay, that sounds so much better. Oh, and we added the retarded “throws” from Java, disguised as a question mark, except it doesn’t provide any improvement while still being obnoxious, because all our exceptions are the same type. Splendid.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.