13 votes

The Val Programming Language

7 comments

  1. [6]
    skybrian
    Link
    Not a whole lot to see and nothing to try out yet since the compiler isn't done. But it's neat seeing what post-Rust language design looks like.

    Not a whole lot to see and nothing to try out yet since the compiler isn't done. But it's neat seeing what post-Rust language design looks like.

    Our goals overlap substantially with that of Rust and other commendable efforts, such as Zig or Vale. Besides, other programming languages have value semantics (e.g., R or Whiley) and/or provide excellent support for generic programming (e.g., Swift or Haskell). So why another one?

    What sets Val apart in the current landscape is its focus on mutable value semantics for the purpose of writing efficient, generic code. Val is a zero-cost abstraction language that fully acknowledges the physical constraints of computer architecture. Yet, it presents a user model that marries these constraints with the benefits of value-oriented programming.

    4 votes
    1. [5]
      updawg
      Link Parent
      Uh...can you maybe repeat that a bit slower?

      What sets Val apart in the current landscape is its focus on mutable value semantics for the purpose of writing efficient, generic code. Val is a zero-cost abstraction language that fully acknowledges the physical constraints of computer architecture. Yet, it presents a user model that marries these constraints with the benefits of value-oriented programming.

      Uh...can you maybe repeat that a bit slower?

      7 votes
      1. skybrian
        Link Parent
        I don't know how much background you need, but I'll give it a try. A value is something like a number or a string. It could also be something big like a table. A value could have lots of smaller...

        I don't know how much background you need, but I'll give it a try.

        A value is something like a number or a string. It could also be something big like a table. A value could have lots of smaller parts to it.

        A mutable value is something like a counter. Numbers are timeless and never change, but a counter can be incremented, and then everyone sees that the counter now has a higher value.

        To pass around a "view" of a counter, normally we use pointers or references. This gets confusing and becomes a source of bugs, because two pointers might point to the same thing and you might not realize it.

        To avoid this confusion, there are languages that decided to get rid of mutable values and just have immutable values. So you don't increment a counter. Instead you return a copy with the new value that the counter should have. Such languages need a smart compiler to turn that into efficient code, particularly when you're making copies of big values like tables.

        The creators of Rust came up with a type system to safely work with mutable values, using lifetimes to place restrictions on what you can do, keeping you out of trouble. This was pretty popular, but Rust is a bit hard to work with since compiler errors can be hard to understand. Other people designing new languages are looking into simpler ways to do what Rust does.

        Val has immutable values, mutable values, and lifetimes, but its way of doing the sort of thing you might do with pointers is to have "subscripts" that yield the location of a value instead of an unrestricted pointer or reference. It seems to be another way of restricting what can be done so you don't get into trouble. I'm not sure exactly what they mean by "value-oriented programming" but it has something to do with that.

        Supposedly, this should be efficient to implement without having a particularly smart compiler. But the compiler isn't done yet, so we'll see.

        7 votes
      2. [3]
        gravitas
        Link Parent
        (this reply is kinda obsoleted by @skybrian's answer because I was too slow on the draw :) Mutable Value Semantics Almost all languages nowadays have some form of reference semantics. For example,...

        (this reply is kinda obsoleted by @skybrian's answer because I was too slow on the draw :)

        Mutable Value Semantics

        Almost all languages nowadays have some form of reference semantics. For example, objects in JavaScript have an identity --- if I have some code that gives someone else an object, and they modify that object, my reference to the same object reflects those changes.

        To contrast this, an array (not like C/C++'s arrays) in Swift has value semantics. If they're passed to a function, and that function modifies it, it doesn't affect the array that it was copied from. If the array's items are reference types, they won't be cloned, however.

        Swift also has implicit memory management. While JavaScript uses garbage collection, Swift uses reference counting --- code is added to your functions that keeps track of how many referents exist to any reference-typed value. It also keeps reference counts for data structures like arrays, so that instead of copying the array all the time, it can only copy it right before it's modified. That's called Copy-On-Write (COW).

        As a lower-level example, Rust doesn't have reference types. If you pass a nontrivial value (roughly any type that implements Drop --- which run code roughly whenever they go out of scope) anywhere, you can't use it again, ensuring that it'll only be "dropped" once.

        But Rust still has first-class references, a way to safely pass pointers around that are verified, at compile time, to be "shared XOR mutable". Mutable references are guaranteed to not be shared, and values are guaranteed to not be modified whenever any references to that value exist. This system is the source of a lot of Rust's complexity.

        Val only has second-class references. This means that it doesn't have to deal with anything like Rust's lifetimes, removing a lot of complexity from the language. Val also has similar "move semantics" to Rust, meaning it doesn't have to do any implicit reference-counting like Swift.

        Zero-Cost Abstraction

        In JavaScript and Swift, garbage collection and reference counting respectively are costs that can't be opted out of. In Swift, passing an array around adds code to increment and decrement the reference count, and modifying it adds code to check if it's aliased, and if so, to copy it.

        Rust and Val have the same "zero-cost abstraction" philosophy.

        For example, Rust has generic code, which can be passed arguments of different types. But a generic function is equivalent to manually duplicating it and changing all the types, so these don't add any overhead at runtime.

        As another example: in languages like Haskell, Ocaml, and Python, almost all values are "boxed" which is a fancy way to say each individual value has its own memory allocation. This adds pointer lookups to nearly all code. (I believe Ocaml at least has small-int optimization, where small integers are instead unboxed.) Whereas in Rust, memory allocation is generally opt-in.

        The rest...

        ...is beyond me. :)

        6 votes
        1. Wish_for_a_dragon
          Link Parent
          I really appreciate the comparison with the other languages here. As someone with only basic Python knowledge, this helps to make more sense of the changes this language brings. Bravo!

          I really appreciate the comparison with the other languages here. As someone with only basic Python knowledge, this helps to make more sense of the changes this language brings.

          Bravo!

          1 vote
        2. updawg
          Link Parent
          It feels good to know that none of us understand what some of it was saying. Thanks for the in-depth explanation.

          It feels good to know that none of us understand what some of it was saying. Thanks for the in-depth explanation.

          1 vote
  2. fleg
    Link
    The name will definitely cause some misunderstandings with the Vala programming language, which has some similarities (low overhead etc.). Vala is mildly popular in certain Linux desktop...

    The name will definitely cause some misunderstandings with the Vala programming language, which has some similarities (low overhead etc.).

    Vala is mildly popular in certain Linux desktop development circles, mainly around Gnome or Elementary.

    1 vote