[HN Gopher] The Vale Programming Language
       ___________________________________________________________________
        
       The Vale Programming Language
        
       Author : danny00
       Score  : 172 points
       Date   : 2020-11-20 13:25 UTC (9 hours ago)
        
 (HTM) web link (vale.dev)
 (TXT) w3m dump (vale.dev)
        
       | skohan wrote:
       | Looks like inferred return type on the `planets` function on the
       | first page?
       | 
       | I'm not a big fan of this. IMHO local inference is great, but it
       | makes things so much better when function signatures are
       | explicit.
        
         | np_tedious wrote:
         | I sort of agree, but enforcing this only on things public /
         | exported can be a nice compromise.
         | 
         | (I mean this as a general statement. Idk how the language
         | handles this)
        
         | ccmcarey wrote:
         | Looking at the language ref, you can specify the return types
         | if you want to.
        
           | skohan wrote:
           | This is not that helpful if you are working with someone
           | else's codebase
        
         | mhh__ wrote:
         | D would be ruined without it. The ability to return so-called
         | voldemort types is not only hugely beneficial for
         | expressiveness but also efficiency (i.e. particularly avoiding
         | the heap).
         | 
         | Syntax toa apply some kind of constraint to the return type
         | would be ok.
        
           | klodolph wrote:
           | When I looked up the example for D, it looks like something
           | that could be named with e.g. Rust's impl feature. In Rust
           | you can return an "impl" of an interface, which is an object
           | with concrete but _unnamed_ type that implements a known
           | interface. It similarly avoids the heap and avoids virtual
           | function calls, without exposing the concrete type.
           | 
           | https://doc.rust-lang.org/edition-guide/rust-2018/trait-
           | syst...
        
             | mumblemumble wrote:
             | If you have a publicly visible interface, that's a name. It
             | may be a name of a base type but it's still a name. IIRC,
             | you can't even typeof() an instance of a Voldemort type.
             | 
             | That has some implications for how Voldemort types work
             | that can't be replicated with anonymous interface
             | implementations. The main one is, Voldemort types are
             | _very_ thoroughly sealed. There is no way to create an
             | instance of one outside of the function where it 's
             | defined. With an interface, anyone else could come along
             | and create their own implementation.
        
               | wwright wrote:
               | You may be thinking of Java's idea of an interface, which
               | is a type (with specific subtyping behaviors). Traits in
               | Rust are _not_ types. There are two different ways to
               | reference an object which implements a trait indirectly
               | (actually more, but these are the dominant ones):
               | 
               | - a `Box<dyn Trait>` is like a Java object referenced by
               | an interface. Everything uses dynamic dispatch, and it is
               | an actual concrete type (though the actual "underlying"
               | type is type-erased).
               | 
               | - an `-> impl Trait` is an _existential_ type which uses
               | a trait as a bound, which should be equivalent to D 's
               | "Voldemort" types, except that it can still satisfy Trait
               | requires for other functions. For example, if you `->
               | impl Iterator<Item = u32>`, you can pass that result to a
               | function expecting an iterator of `u32`. However, the
               | type is fully defined by the callee and can't be
               | instantiated/inspected externally.
        
               | klodolph wrote:
               | > With an interface, anyone else could come along and
               | create their own implementation.
               | 
               | Not true in Rust, because the type returned by the
               | function is a concrete type.
               | 
               | I think we may be overloading "name" here, a bit. If you
               | return an "impl" in Rust, you have to name an interface,
               | but you can't actually create new instances of the
               | concrete type returned by the function.
        
               | mumblemumble wrote:
               | > Rust, you have to name an interface, but you can't
               | actually create new instances of the concrete type
               | returned by the function.
               | 
               | I think that's the distinction that really matters. The
               | thing that's neat about Voldemort types, and gives them
               | their interesting properties that are distinct from
               | anonymous types, is that they have no name at all. Not
               | even an interface or trait name.
        
               | skohan wrote:
               | What would be a concrete use case which benefits from
               | this? I am not experienced with D, but it just seems like
               | it would make code more obscure
        
               | mumblemumble wrote:
               | There's a bit more explanation on the D wiki:
               | https://wiki.dlang.org/Voldemort_types
               | 
               | I don't really intend to say whether they are better or
               | worse than other ways of accomplishing similar things.
               | Just that they're different.
        
               | klodolph wrote:
               | Yes, from that explanation it sounds like they are
               | equivalent to Rust's impl return types.
               | 
               | Note that interfaces in Rust are _not_ types, they do not
               | name types. A value cannot have interface type. What
               | happens when you return an "impl" type is that you return
               | some unspecified type, but that type must implement the
               | specified interface.
               | 
               | You could translate the D example to:
               | trait HasGetValue {             fn get_value(&self) ->
               | i32;         }         fn create_voldemort_type(value:
               | i32) -> impl HasGetValue {             ...         }
               | 
               | The "create_voldemort_type" function simply returns a
               | value of _unspecified type._ As far as I can tell, this
               | is equivalent to the D code, except it doesn't use type
               | inference for the function type.
        
               | moonchild wrote:
               | Not really. Part of the point of voldemort types is that
               | no information about the type is 'leaked' outside the
               | function. In this case, the trait 'HasGetValue' is leaked
               | and can be used by other code.
        
               | skohan wrote:
               | When would you want to have an interface such that
               | nothing about the return type of a function is known to
               | the outside world? I'm genuinely asking; I just don't
               | understand the utility of this concept.
        
         | aszen wrote:
         | I actually like the option to have both inferred parameter and
         | return types, primarily because they help in writing code while
         | prototyping quickly with several types.
         | 
         | Once the code is well defined I then start adding the type
         | annotations , often times using the ide tooling to auto
         | generate them.
         | 
         | I think a good balance would be that all published packages
         | should have type annotations added in their source code for
         | clarity while short scripts could do without them.
        
           | skohan wrote:
           | Idk I mean maybe it's a matter of taste, but I just never
           | felt like it was that cumbersome to write type names in the
           | function signatures. In a short script it's not like you
           | would usually have the dozens or hundreds of function
           | signatures it would take to make this feel like drudgery.
        
             | aszen wrote:
             | Well think about writing functions inside a repl or
             | interactive environments like jupyter notebooks or just
             | plain scripting. Enforcing type annotations add little
             | value in those cases and end up making the language ill
             | suited for such use cases.
             | 
             | Whole form type inference is actually a super power that
             | allows for writing extremely expressive code without giving
             | up type safety.
        
         | boboguitar wrote:
         | Worst part of Ruby for me, I hate inferred returns in general.
        
           | wwright wrote:
           | I think you may be thinking of _implicit_ returns, where the
           | `return` keyword is not necessary. An _inferred_ return is a
           | separate feature where the return type is known by the
           | compiler, but not stated explicitly by the programmer. (Note
           | that the code in question uses both.)
           | 
           | Ruby, of course, technically has both as well. However,
           | inferring a return type in a dynamically-typed language is
           | probably less noteworthy ;)
        
             | optimuspaul wrote:
             | I was going to pop in to say that. also going to add that I
             | hate implicit things like this. messes with my brain, how
             | hard is it to just add the return keyword? saving a few
             | keystrokes hardly seems worth the increased cognitive cost
             | to others.
        
         | melling wrote:
         | I like explicit types on functions too.
         | 
         | However, it might be what I'm used to.
         | 
         | Do you think this would be less of a problem with editor/IDE
         | support? Using colors, or other visuals, to infer and show the
         | types while editing might overcome this desire.
        
           | steveklabnik wrote:
           | Rust did not choose to infer types in signatures for UX and
           | stability reasons. If you infer types in signatures, then a
           | change in the body of the function can change the type of the
           | function, which makes dealing with backwards compatibility
           | harder. Also, it leads to weird "errors at a distance."
        
             | kroolik wrote:
             | I call this property "an accidental complexity" - when
             | changing one piece of code causes failures in other,
             | seemingly unrelated parts of the system. The property
             | causes fear of introducing changes, and is usually a sign
             | of tight coupling.
        
           | skohan wrote:
           | I tend to agree with the philosophy that a language should
           | not _require_ an IDE to be productive in.
           | 
           | With function signatures, I think it's particularly relevant
           | for documentation as well. I should be able to look at a
           | function signature in generated docs and know everything
           | about what goes into and comes out of that function. For me
           | the signature should be a complete contract, and changing
           | code within a function body should not be able to change the
           | signature.
        
       | aflag wrote:
       | The adjective modern is so popular, yet it's so devoid of
       | meaning. What does having a modern syntax even mean? The
       | impression I get when I read projects described like that is that
       | the authors are saying they are following the latest trends they
       | could find, but they don't quite know why.
        
         | zachrose wrote:
         | The adjective has a lot of meanings, nothing I'd call a void.
         | 
         | > More common, especially in the West, are those who see it as
         | a socially progressive trend of thought that affirms the power
         | of human beings to create, improve and reshape their
         | environment with the aid of practical experimentation,
         | scientific knowledge, or technology. From this perspective,
         | modernism encouraged the re-examination of every aspect of
         | existence, from commerce to philosophy, with the goal of
         | finding that which was 'holding back' progress, and replacing
         | it with new ways of reaching the same end.
         | 
         | https://en.wikipedia.org/wiki/Modernism
         | 
         | Seems applicable to "modern, readable syntax". It means not
         | afraid to buck what people are used to if there's a better way
         | to do it.
        
         | simias wrote:
         | I think it's effectively code for "it's not like C". Easy
         | iteration, lambdas, generics, patterns, type inference etc...
         | 
         | None of these features are technically novel but they do tend
         | to be shared by newer system languages, as opposed to
         | C/Pascal/Fortran/Cobol and friends. Then of course there's C++
         | that's both old-school and modern because C++ is slowly but
         | surely evolving to become the programming language equivalent
         | of the Borg and eventually all other programming languages are
         | bound to become a subset of C++.
        
           | nocman wrote:
           | "... eventually all other programming languages are bound to
           | become a subset of C++."
           | 
           | God help us all!!!!
           | 
           | (fortunately for my sanity, I have zero confidence that this
           | will be the case)
        
             | thotsBgone wrote:
             | Every language will eventually become a subset of C++, and
             | they will all compile to javascript.
        
               | recursive wrote:
               | The modern ones will compile to webassembly.
        
               | tempodox wrote:
               | Via JavaScript, on the client.
        
         | marmaduke wrote:
         | turn it up to 11 with "truly modern" or similar.
        
         | voldacar wrote:
         | modern usually seems to mean means algol syntax and not having
         | macros :)
         | 
         | aka the status quo of 60 years ago
        
         | Zelphyr wrote:
         | "blazing fast", "lightweight", etc...
         | 
         | Buzzwords are abound in modern technology circles anymore.
         | 
         | To your point; "modern" is especially insidious because it
         | implies that older technology is bad. I'd take vanilla PHP and
         | JavaScript over TypeScript and the frameworks any day. I
         | recognize that's an extremely unpopular opinion but those
         | languages are battle tested over 25 years and if I run into a
         | problem that I haven't seen before, there's a high probability
         | I'll get the correct answer from a search. For the "modern"
         | stuff, I get five different answers and none of them solve my
         | problem because the language and/or framework has changed as
         | many times since the question was first asked.
         | 
         | That said; given the choice I'd choose Clojure and
         | ClojureScript. It's a young pup compared to PHP and JS but it's
         | still based on a 60-year old language and just a joy to work
         | with.
        
         | gfody wrote:
         | "following the latest trends" basically works as a definition
         | for the word "modern" in the context of programming languages.
         | "involving recent techniques" etc. why modern? is a fair
         | question I guess but why not? are there any good arguments
         | against things like type inference, generics and lambdas?
        
           | aflag wrote:
           | I see the first paragraph of a language's website as sort of
           | the "elevator pitch" for that language. You probably want to
           | cut down any vague and uneeded words in that context and
           | focus in the defining aspects of your language. Following the
           | latest trends is also vague and, the more precisely you
           | define it, the more you will need a timestamp next to the
           | term. I think it's better to jsut spell out what are the
           | actual features you really care about.
        
           | fiddlerwoaroof wrote:
           | Are any of those recent techniques?
        
             | gfody wrote:
             | as far as programming language evolution goes I have to
             | assume "recent" refers to a span of 20 years or so -
             | otherwise I don't think we have any recent techniques
        
               | fiddlerwoaroof wrote:
               | I'm fairly certain we've had lambdas (lisp) for something
               | like 40 years. Type inference (ML/lisp compilers) for
               | 30-40 years. And generics, at least in the sense of
               | parametric polymorphism, (Ada/C++/Java/ML) for about the
               | same amount of time. As far as I can tell, the borrow
               | checker and some features around dependent types are
               | newish, but actually modern features are few and far
               | between.
        
               | aflag wrote:
               | Lisp had lambdas for 60 years, I think ML has had type
               | inference for about 50 (maybe there are earlier languages
               | that had it?), ML also had generics for that long. So,
               | none of your examples were recent developments by your
               | standards.
               | 
               | Even in C-like languages, generics were part of C++ (or
               | rather templates, in that case) since the beginning, I
               | think (that's 35 years ago). I think you can make a case
               | for type inference reaching the C language family
               | recently, though.
        
               | gfody wrote:
               | I mean sure "recent" could refer to a span of even 50
               | years why not. I wouldn't trade my Roslyn compiler for
               | AGOL68.
        
               | fiddlerwoaroof wrote:
               | Comparing a compiler to a language is comparing apples
               | and oranges.
        
               | gfody wrote:
               | I disagree I think it's more like comparing an apple to
               | an apple tree
        
               | fiddlerwoaroof wrote:
               | Either way, it's hard to compare a 30 year old language
               | to a modern compiler because the modern compiler has
               | benefited from 30 years of optimizations: you can't tell
               | how the old language would perform with a similar
               | investment.
        
         | fiddlerwoaroof wrote:
         | As a lisper, I find "modern syntax" means "looks vaguely like C
         | or JavaScript"
        
           | simias wrote:
           | I think it's more "borrows many ML concepts but uses C/C++
           | style syntax to look more mainstream, also no GC".
        
       | 02020202 wrote:
       | what about Zig? why so many new languages suddenly appear?
       | 
       | Vale looks ok and readable(unlike butt ugly rust) but it just
       | tries to be really smart and I don't like it. way too much
       | syntactic sugar for shorter code in exchange for readability and
       | clarity. too many implied things...that's why Go rulez. simple,
       | clean, readable.
        
       | kroolik wrote:
       | I wonder what made the authors of the language make the pattern
       | matching statement keyword `mat`. Like... they were 2 characters
       | away from a perfectly readable name, yet they've settled up on
       | something that's confusing (took me a while to grasp it). Guess
       | the time and space savings are worth it, though.
        
         | tgv wrote:
         | inl, imm, mut, mat ... I see a pattern.
        
       | [deleted]
        
       | epage wrote:
       | There are several domains of programming with similar but not-
       | quite-the-same requirements
       | 
       | - OS
       | 
       | - Embedded
       | 
       | - Game
       | 
       | In some respects, these are pretty niche and there is a lot of
       | value imo in having a single-language that spans them rather than
       | creating an even more niche language for each one. I saw C++ and
       | now Rust filling that role.
       | 
       | I've not dug into the implementation details enough to confirm
       | but when I see comments about runtime checks, I'm concerned there
       | might be things going on that make this cover only one domain
       | rather than covering these related domains. Even if its a matter
       | of "programming right" to fit all domains, that just seems
       | brittle.
        
       | etherio wrote:
       | When people build these type of languages it'd be nice if they
       | prominently insisted on the new approach / change the language
       | creates. Would be clearer.
        
       | rubiquity wrote:
       | It's not called out on the web page but the novel concept here is
       | the usage of regions for memory safety. Microsoft's Verona[0] is
       | also taking this approach. People seem to really like Rust but
       | it's important to keep experimenting and see if we can get the
       | same benefits but with better ergonomics.
       | 
       | 0 -
       | https://github.com/microsoft/verona/blob/master/docs/explore...
        
         | baby wrote:
         | So you're saying that code you wouldn't be able to write with
         | rust would crash at runtime in Vale right?
        
           | zozbot234 wrote:
           | Rust borrowck is conservative, so not quite. There's plenty
           | of memory-safe programs that can't be written (or require
           | runtime checking) in Safe Rust.
        
         | zozbot234 wrote:
         | I'm not entirely sure what's supposed to be "novel" about
         | region-based memory management. It was featured already in
         | Cyclone, a C-like memory-safe language that was a heavy
         | inspiration for Rust. Rust ultimately went for borrowck and
         | lifetimes as opposed to general regions _because_ of
         | ergonomics. Regardless, it 's always interesting and worthwhile
         | to see alternate approaches being revisited - for instance,
         | explicit regions might help with some scenarios that currently
         | require unsafe{} in Rust.
        
           | moonchild wrote:
           | FWIW cyclone also had unique pointers.
           | 
           | I don't know if explicit regions help very much with safety,
           | but you can certainly go places with a more expressive type
           | language. E.G. ats - http://www.ats-lang.org/
        
         | simias wrote:
         | I don't think I understand the difference between regions and
         | Rust's concept of lifetimes. In my mind they were two sides of
         | the same coin, but you seem to argue otherwise.
         | 
         | Note that my knowledge of regions comes mainly from Cyclone,
         | not Vale or Verona, are those different concepts with the same
         | name?
        
         | Verdex wrote:
         | My theory is that in order to replace C/C++ in the systems
         | language space we are going to need several different types of
         | languages.
         | 
         | Rust is pretty nice, but the options for allocation and it's
         | ownership type system make it a mismatch for certain types of
         | applications (probably games and OS's but we'll see how that
         | plays out).
         | 
         | I think regions are neat. And I'm looking for an opportunity
         | both for playing around with it myself and for the programming
         | language community at large getting more exposure to them.
         | 
         | More ideas exposed to more people leads to better ideas of how
         | to fit everything together and how to leverage what features to
         | solve some problems better.
        
           | aldanor wrote:
           | Games often use arena-based allocation systems, slotmaps etc
           | to manage myriads of instances. I don't see how any of that
           | is a problem in Rust?
        
             | megameter wrote:
             | It's mostly the ergonomics of Rust being fine-grained that
             | present a problem. While it's gotten better with revision,
             | fundamentally, you start in an assume-nothing mode in Rust
             | and then boilerplate appears to say "actually, this one is
             | mutable". This incurs friction on nearly every line of
             | state manipulation and when you're doing game-style
             | allocation, you mostly don't care. You have a tremendous
             | amount of mutable state; some of it you blow away every
             | frame, the rest you may want to lock sometimes.
             | 
             | What Vale does that is attractive is to make simplifying
             | assumptions that address this problem domain closer to the
             | level of granularity that it deserves.
        
               | danbolt wrote:
               | I think a pure ECS has its state manipulation well-
               | encapsulated and organizable. Part of me thinks that sort
               | of design would mesh pretty well with Rust's ownership
               | system.
        
               | steveklabnik wrote:
               | Rust folks think this as well; there has been a _lot_ of
               | activity in this area, and even spread some of the ideas
               | behind ECSes to areas outside of games.
               | 
               | https://kyren.github.io/2018/09/14/rustconf-talk.html
        
             | steveklabnik wrote:
             | It is not. The usual arguments against Rust for games are
             | more cultural. Rust makes a tradeoff of being a bit harder
             | up front, for less time debugging later. Many people say
             | that games specifically would prefer the opposite tradeoff.
             | 
             | We'll see as things continue to develop here.
        
           | ampdepolymerase wrote:
           | A modern alternative to C's FFI needs to be developed,
           | perhaps a standard like gRPC but as a compiler extension. C's
           | FFI contains so little information due to its weak type
           | system that it is wholly unsuitable for higher level
           | languages. Yet we use it because it is the lowest common
           | denominator. The C FFI has cost hundreds of hours of lost
           | productivity due to having to re-annotate all the types in
           | the non-C caller. This is before we even take into account
           | the mess that is function pointers and types generated using
           | the pre-processor. And no, tools like bindgen and c2rust are
           | stop gaps, not a real solution. A lot of low level code
           | cannot be effectively called safely in a higher level
           | language at all without hundreds of hours of manual work
           | wrapping and annotating each individual function. We need a
           | new standardized, zero cost, cross language interop format
           | that functions on the ABI/memory level. Rust's Cxx is a good
           | start but it doesn't scale m:n with regards to new languages.
           | Every new language has to implement a custom wrapper for
           | calling another high level language if they do not want to
           | lose 80% of the benefits of the respective language's type
           | system when passing through the primitive C FFI. For example,
           | calling Rust from Julia, calling Julia from V lang. The lack
           | of a common interop format is hurting the developer ecosystem
           | as more proliferation of programming languages simply leads
           | to greater fragmentation. The web solved this a long time ago
           | with JSON APIs, generated OpenAPI clients (and now Graphql),
           | and to a lesser extent, gRPC. We need to do better when it
           | comes to systems programming.
        
             | 10000truths wrote:
             | The whole _point_ of FFI is that it 's a lowest common
             | denominator - it's a _foreign_ function interface, meant
             | for interop between two potentially wildly different
             | runtimes, up to and including assembly language. That means
             | it can 't rely on quirks like language-specific type
             | information or bounds checking. The only thing that all
             | runtimes on a machine are guaranteed to have in common is
             | that they use the same set of memory and CPU registers, so
             | that is all that FFI can use to define subroutine
             | interfaces. Hence terms like 'ABI', 'calling convention'
             | and 'memory layout'.
             | 
             | The good news is that whatever issue you have can probably
             | be solved without resorting to FFI. There are plenty of
             | other interop options - for example, if you control the
             | library, you can use your operating system's IPC mechanisms
             | with an agreed-upon serialization format. Or, if your
             | library and application are within the same ecosystem, you
             | can use language-specific library management features such
             | as Python's import or Rust's crates. FFI is a bit like C
             | itself - if you're reaching for it as a solution to your
             | problem, then your finger is already on the trigger of the
             | footgun.
        
               | ampdepolymerase wrote:
               | And most people used to believe that ergonomic, zero cost
               | memory safety was impossible too. And yet it moves. There
               | is no reason why we have to settle for a poor FFI
               | solution just because it was the choice of our
               | predecessors.
        
               | 10000truths wrote:
               | Memory safety and FFI operate on two different layers of
               | abstraction entirely. What does it mean to enforce
               | 'memory safety' across the boundaries of two different
               | applications/libraries that may have entirely different
               | ways of keeping track of memory allocations and
               | deallocations? Again, FFI has to be agnostic to such
               | implementation details in order to work, and it does so
               | by forcing you to define interfaces in terms of the
               | lowest possible level of abstraction common to all
               | applications. That means explicitly specifying expected
               | memory layout and calling convention on both the
               | application and library sides, i.e. an ABI.
        
               | jrumbut wrote:
               | IPC is, I think, the concept that has been neglected and
               | led to the desire for some kind of really intelligent
               | FFI.
               | 
               | If you have code in Ruby and in Julia that you want to
               | mix together it's probably because both pieces of code
               | leverage the distinct capabilities of those two
               | languages, which have nice capabilities because they
               | accepted very tradeoffs.
               | 
               | Would you really want Julia with Ruby's Number class? It
               | would entirely kill performance. You want it to be an
               | integer maybe, or a double, or sometimes something else.
               | It's going to be application specific is the point,
               | because another user want some different subset of
               | Number's behavior. I don't think there's a shortcut here
               | besides making a very limited or opinionated FFI system.
        
               | rng_civ wrote:
               | I think there's a conflict between FFIs in practice and
               | theoretical FFIs. The few papers I've read for sound FFIs
               | between languages A and B rely on the fact that the
               | common interop target is a high-level language whose
               | features subsumes the features of A and B. ABI, calling
               | convention, etc. are merely implementation details.
               | 
               | So from this perspective, the interop target should
               | actually not be the lowest common denominator, but the
               | opposite: a target that can describe all possible user
               | languages in a common format.
               | 
               | In fact, I would actually argue that the implementation
               | details are NOT that interesting and only a distraction:
               | that we need an abstract way of declaring compatibility.
               | For instance, one can imagine a high-level FFI target
               | where function types are parameterized by their calling
               | convention i.e.:
               | 
               | `foo: (VOID<C>->VOID<C>)<C>`
               | 
               | `bar: (UNIT<Rust> -> UNIT<RUST>)<RUST>`
               | 
               | and attempting to call `bar` from `foo` involves a
               | compiler intrinsic like `RUST_CALL(bar)()` to convert the
               | type (and the calling convention) appropriately.
        
             | chubot wrote:
             | This is a very real problem, particularly the M:N issue.
             | 
             | But I think it's inevitable you have to do things on both
             | sides of the language boundary, i.e. pushing them towards a
             | lowest common denominator. (e.g. Microsoft's COM, which
             | actually worked pretty well)
             | 
             | Really what it pushes you toward is wire protocols and NOT
             | relying on the type system. That is the C and C++ ABIs are
             | related to but different than the APIs (type system).
             | 
             | My experience tells me that transparent interop is kind of
             | a pipe dream. The problems always pop up somewhere. By
             | "transparent", I meant "Rust function calls C++ function"
             | and "C++ function calls Rust function" without other
             | metadata/bindings. The codegen becomes a big problem in
             | practice.
             | 
             | Fundamentally a lot of languages LOOK the same but they ACT
             | completely differently. A Rust function is not a C++
             | function is not a Python function is not a Go function.
             | (And funny thing -- as of C++ 11, C++ now has many
             | different notions of "function", because of move
             | semantics).
             | 
             | And functions are actually "easy" compared to types (e.g.
             | inheritance vs. typeclasses vs. interfaces)
             | 
             | ----
             | 
             | Basically I would say the problem is that you either spend
             | time manually wrapping or annotating your code (as you
             | say), OR you put an ever growing list of heuristics in the
             | code generator, a la SWIG.
             | 
             | Those heuristics have bugs, and will make your program
             | unreliable. They're also "someone else's problem", which
             | leads app developers to come up with horrific workarounds.
             | 
             | So I go with the simple manual wrapping, and reducing the
             | number of things to wrap by changing the structure of your
             | program. This also has other benefits like efficiency, i.e.
             | crossing the language boundary less often.
             | 
             | (Related: I think better build systems can go along way
             | toward solving this problem. Unfortuately there seem to be
             | a lot of language-specific build systems and package
             | managers now, which only exacerbates the interop problem.
             | If you have one language-neutral build system, it's not
             | that bad.)
        
             | simias wrote:
             | >We need a new standardized, zero cost, cross language
             | interop format functions on the ABI/memory level
             | 
             | I don't think that's doable unless the underlying language
             | already has the same ownership and lifetime guarantees as
             | Rust does, otherwise these bindings have to protect against
             | memory issues by effectively taking ownership of the data
             | to garantee its lifetime, which is not zero cost.
             | 
             | I simply don't think that you can auto-generate zero-cost
             | safe C or C++ bindings automatically.
        
               | estebank wrote:
               | > I simply don't think that you can auto-generate zero-
               | cost safe C or C++ bindings automatically.
               | 
               | As stated, that's likely an accurate statement, _but_ if
               | you separate the requirements for the bindings the
               | problem looks _way_ more tractable:
               | 
               | - auto-generate: I'm pretty positive that this point is
               | only hard given the following, and I feel you would agree
               | with that assessment, so I'll just focus on the other
               | ones.
               | 
               | - zero-cost: doing zero-cost ffi is the best option, but
               | a lot of advanced constructs that people want to use
               | cannot be well represented in that way because they rely
               | on the internal consistency of the host language. That
               | means that dynamically loading a library written in Rust
               | might make it so that you can _only_ interact with ADTs,
               | trait objects and whitelisted provided traits on those
               | ADTs, potentially only through trait objects. That 's not
               | zero-cost, but it is super powerful. ObjectiveC has lived
               | its entire existence going through vtables and that has
               | even enabled runtime introspection that was super useful.
               | 
               | - safe: safety can be accomplished easily enough if you
               | don't constrain yourself to zero-cost _or_ if you put
               | constraints on _what_ is supported for zero-cost ffi. You
               | could say that method calls on trait objects is safe, but
               | type parameters are out of scope because ffi and
               | monomorphization are not compatible. You could restrict
               | yourself to either no borrows crossing ffi, or no mutable
               | data (only internal mutability through trait methods)
               | allowed.
               | 
               | - C or C++: I would focus on _other_ languages,
               | personally. Having easy interop with Java, C#, Python and
               | JavaScript would open opportunities that do not have
               | anything to do with systems programming per-se, but that
               | would make it more likely that the next numpy isn 't
               | written in pure C.
               | 
               | - automatically: the need for extra annotations in either
               | end of the interop simplifies part of the problem and
               | might even help with documentation. Adding some light
               | ownership information to APIs in non-Rust languages would
               | be great for non-Rust users of those APIs.
        
               | bee_rider wrote:
               | Hey! Surely there's some Fortran left in some of the
               | libraries that back NUMPY.
        
         | dgb23 wrote:
         | > People seem to really like Rust but it's important to keep
         | experimenting and see if we can get the same benefits but with
         | better ergonomics.
         | 
         | Is my intuition correct that one could implement this type of
         | memory handling in Rust as well?
        
         | thechao wrote:
         | I'm drawn to regions because they seem to intuitively match how
         | I write my high performance systems software. In those sorts of
         | SW, I really need precise and cheap ownership rules, but
         | without any restrictions in topology.
         | 
         | It'd be super if regions were a mathematically robust way of
         | describing that engineering solution.
        
         | tomp wrote:
         | From my reading of the docs, Vale is _not_ memory safe. It
         | offers some tools to _assist_ with memory management, but is
         | fundamentally closer to the safety level of C++ rather than
         | Rust.
        
           | rafaelvasco wrote:
           | Not being fully memory safe but assisting in it, is the way
           | to go for the broad scope of applications imo;
        
             | vlang1dot0 wrote:
             | I don't really agree. The vast majority of applications are
             | fine being written in whatever flavor of high-level,
             | garbage collected, memory safe language you want. There are
             | many nice options with pretty much any set of feature and
             | style choices you could want.
             | 
             | The rest of these applications have either hard realtime or
             | hard performance requirements or both. What I don't see in
             | these apps, is for memory safety issues to be 'ok'.* It's
             | 2020, using a memory safe language should be table stakes
             | for new projects at this point.
             | 
             | ----------
             | 
             | * The one exception I can think of is single player video
             | games where the worst that can happen is basically just a
             | crash to desktop. Multiplayer games are a different story
             | especially with the trend toward paid DLC where these kinds
             | of issues could result in anything from exploits in
             | multiplayer matches (hurting the community and thus the
             | game overall) or players circumventing DLC restrictions
             | (resulting in a loss of profit).
        
       | mansoor_ wrote:
       | Language looks Rusty :)
        
         | hhas01 wrote:
         | Well this is it, isn't it. Because really, what the hell _is_
         | its USP+? The world already has a perfectly cromulent Rust
         | language. Adding a second, less popular one merely dilutes both
         | efforts; and to what purpose? Ego? Control? Simple
         | unwillingness to accept a direct competitor has _already_
         | beaten their ass to market and mindshare?
         | 
         | Everyone knows the name Charles Darwin. Now ask them who Alf
         | Wallace is, and why they should they should care. Or Yohan
         | Blake. Or Atty Osborne... and so on.
         | 
         | Where's the advantage in being an also-ran? It's a tough but
         | necessary lesson to swallow: accept your lovely technology is
         | just too late to be the successful product you hoped for. Treat
         | the whole exercise as a valuable learning experience, and move
         | on to your next Big Idea as quickly as you can, this time, of
         | course, making sure to get to market _before_ your direct
         | competitors can, so as to leave _them_ in the dust instead of
         | you.
         | 
         | --
         | 
         | + Their website doesn't say. Just a technical features list,
         | and yep, one look: Rust, but a lot less mature with waaay less
         | ecosystem and support. That's not a winning proposition; that's
         | a sucker's deal. Damn but every computer geek needs to do a
         | marketing course.
        
           | lopatin wrote:
           | Upvoted because I'm pretty sure this comment was written by a
           | neural network. Commented because I'm hoping for a reply.
        
             | hhas01 wrote:
             | Negative, I am a meat popsicle.
        
             | ddalex wrote:
             | All comments are written by neural networks,in the end.
        
               | [deleted]
        
           | ddalex wrote:
           | > Simple unwillingness to accept a direct competitor has
           | already beaten their ass to market and mindshare?
           | 
           | I have not seen any shred of competition suggestion here. But
           | even if there is competition, that should be encouraged -
           | competition is healthy, and it promotes development. Who is
           | to say that Rust has all the good ideas and nobody else can
           | have any good idea ?
           | 
           | You should encourage competition not stiffle it "because
           | somebody else is more advanced"
        
           | nicoburns wrote:
           | I had to do some digging, but I found this:
           | 
           | > A memory model and first-class regions which together make
           | it as fast and safe as Rust, without the borrow checker and
           | its aliasing restrictions.
           | 
           | (https://www.reddit.com/r/vale/comments/i95ue8/use_case_of_th
           | ...)
        
           | megameter wrote:
           | You're showing a lot of attachment here. Rust is not your
           | precious child in need of defending by attacking upstarts.
           | There are many tools of this kind and there will be many more
           | to come.
        
             | hhas01 wrote:
             | I'm not a Rust user. I have no particular nag in this race.
             | What I do understand, or at least am start to learn, is the
             | difference between a Technology and a Product, and between
             | a Product and Success.
             | 
             | So once again: What is Vale's USP+? Because it isn't on
             | their frontpage; which it would be had they thought to ask
             | that question of themselves.
             | 
             | --
             | 
             | TL;DR: Goddamn it, all you noobs, but learn _How To Sell_
             | already. Some of us are just too damned old and tired to
             | want to hold your diapers till you learn to grow up. Try
             | making our lives a bit easier for once; not just to benefit
             | us but your own products as well.
             | 
             | .
             | 
             | (+ And if you don't even know what "USP" means, well there
             | you are. As someone who has already tried to bring truly
             | groundbreaking new tech to market and flubbed it, and is
             | just about to roll up sleeves and try, try again, I'm not
             | asking these questions just to be obtuse but to be
             | _helpful_. However, if you'd rather just insult than ever
             | amount to squat then by all means carry on.)
        
               | creata wrote:
               | I don't know what Vale's "USP" is, and I think you're
               | right to point out that it doesn't really sell itself on
               | its front page. But you're being a _massive_ dick about
               | the marketing of a language which is clearly a work-in-
               | progress, and hasn 't even hit v0.1. You know you can
               | give advice _and_ be nice about it, right?
        
               | hhas01 wrote:
               | Why? Will the _market_ be any nicer to them? They've
               | failed to make their case as to why _anyone_ should care
               | that Vale exists; never mind actually differentiate it
               | from the current swathe of robust, established Rust-style
               | languages _already_ in full production use and battling
               | each other for the market's next 20 years of attention.
               | And they've barely reached v0.1, and expect to make a
               | difference when make their grande entrance into that
               | bullpen? Who's fooling who here?
               | 
               | Look, if they just want to be another D then by all means
               | have at it. It's great that they have a personal hobby,
               | but at least have the good grace to put up a notice
               | saying they're making this thing to please nobody but
               | themselves. That way anyone else looking at it knows not
               | to invest their own time into a toy project that doesn't
               | even take itself seriously, never mind have the chops to
               | make the rest of the world believe in it too.
               | 
               | Oh, and by the way, I've said nothing about Vale that
               | I've not said of my own projects... right before I've
               | pulled the plug on them for failing to hit their overall
               | objectives. And the best of that work's been technically
               | excellent, with sitting users royally pissed that I've
               | just chucked their investments on the scrapheap along
               | with my own. But I'm a realist; and it's better to pull
               | the trigger now and move on ASAP to the next thing, than
               | drag out a slow but inevitable death and then have to
               | junk an even larger investment further down the line. See
               | also: sunk cost fallacy.
               | 
               | You want to ask other people to believe and invest in
               | you? You'd damn well better bring more than just a tick
               | list of features and your delicate feels. Else you're
               | just messing them around for your own personal ego.
               | 
               | /fin
               | 
               | --
               | 
               | TL;DR: When someone offers you difficult questions and
               | brutal honesy, take it and ask for more, 'cos that's the
               | best gift they can offer. But if all you want is a pat on
               | the head, then go ask your mom as I'm sure she thinks
               | everything you do is wonderful.
        
       | voldacar wrote:
       | I don't want to sound mean but I think the world has enough algol
       | clones already :/
        
         | jbotz wrote:
         | I admit that I also automatically lose a bit of interest if I
         | see "familiar C-like (algol-like) syntax" as a supposed feature
         | in a new programming language, there is also no point in being
         | original just for originality's sake, and the space of possible
         | syntaxes for programming languages has been pretty well
         | explored. But in terms of semantics this really doesn't look
         | much like an "Algol clone" at all, rather it seems to want to
         | explore the conceptual space between imperative and functional
         | languages where Rust has been breaking genuine new ground, and
         | which clearly has more room for experimentation.
        
           | rienbdj wrote:
           | Having spent time with languages that use c syntax and ones
           | with whitespace based syntax, I much prefer the latter. I
           | think c syntax is seen as plus not because it is better, but
           | because it is familiar to more people. See also ReasonML
        
             | spijdar wrote:
             | Just for a dissenting opinion, I use both types of scope
             | syntax on a regular basis and prefer the Algol-ish one. I
             | _personally_ find it easier to reason about where code
             | blocks begin /end when they're explicitly marked. Makes
             | moving code around easier, too.
             | 
             | Note that most of my problems could be fixed with enough
             | tooling/editor plugins/IDE magic, I just don't use them.
        
       | rayman22201 wrote:
       | Nim tried regions based memory management and ended up going a
       | different direction. The feature still exists, but the core devs
       | ended up considering it a bit of a dead end: https://forum.nim-
       | lang.org/t/6930
        
       | iphorde wrote:
       | Why do we need to denote a function, with fn, def, function, ...?
       | we can do better than this.
        
         | Groxx wrote:
         | main() {         something() {           // implementation
         | block for something(), or anonymous scope?         }
         | something() // first or second execution?       }
        
           | iphorde wrote:
           | something() { } obviously is a definition, something() is
           | obviously a call.
           | 
           | Why is that hard for you?
        
             | Groxx wrote:
             | or is it obviously executing `something()` followed by an
             | anonymous scope with a less-common indentation pattern,
             | e.g. equivalent to                 var x = 1;
             | something();       {         var x = 2;       }       // x
             | is now 1 again, as the scope       // containing the new
             | variable x=2 is gone       something();
             | 
             | or, as mentioned in another comment, is it passing an
             | execution block to `something()`? (I didn't mention that in
             | my original since it's a bit less common of a language
             | feature, but it's valid too)
             | 
             | enforced semicolons and/or significant whitespace/newlines
             | can resolve this in some cases, but it of course depends on
             | the language. and diverging too far from common langs has
             | its own downsides too, especially where you're changing the
             | interpretation of what are already common patterns.
        
             | steveklabnik wrote:
             | That is actual Ruby syntax for an invocation of something,
             | so it may or may not be obvious depending on what you're
             | used to. (Though most Rubyists would drop the ()s)
             | 
             | Also, as mentioned, in many languages it is valid syntax
             | for an invocation of something, followed by a new scope.
        
           | rafaelvasco wrote:
           | Perfect answer;
        
           | [deleted]
        
       | adamnemecek wrote:
       | The project has a discord channel for those interested
       | https://discord.gg/SNB8yGH
        
       | _zachs wrote:
       | Interesting! Is this supposed to be an easier-to-read Rust?
        
       | [deleted]
        
       | jgilias wrote:
       | Can someone give a quick TLDR what are the main differences to
       | Rust?
       | 
       | EDIT: Or rather, what are Vale's selling points to someone using
       | Rust?
        
         | duckerude wrote:
         | One core difference seems to be that references are checked at
         | runtime. In Rust you have to be able to prove that a reference
         | to a value can't outlive the value, but Vale is more trusting,
         | and simply crashes if a reference outlives the value in
         | practice.
         | 
         | You have constraint references, which crash the program if they
         | still exist when the value is freed. And you have weak
         | references, which turn into null. Constraint references can
         | optionally be compiled into raw pointers.
        
         | [deleted]
        
         | merelydev wrote:
         | The author posted this on reddit [0] a few months ago:
         | 
         | Vale's main goal is to be as fast as C++, but much easier and
         | safer, without sacrificing aliasing freedom. It does this by
         | using "constraint references", which behave differently
         | depending on the compilation mode:                   Normal
         | Mode, for development and testing, will halt the program when
         | we try to free an object that any constraint ref is pointing
         | at.              Fast Mode compiles constraint refs to raw
         | pointers for performance on par with C++. This will be very
         | useful for games (where performance is top priority) or
         | sandboxed targets such as WASM.              Resilient Mode (in
         | v0.2) will compile constraint refs to weak refs, and only halt
         | when we dereference a dangling pointer (like a faster ASan).
         | This will be useful for programs that want zero unsafety.
         | 
         | Vale v0.2 will almost completely eliminate Normal Mode and
         | Resilient Mode's overhead with:                   Compile-time
         | "region" borrow checking, where one place can borrow a region
         | as mutable, or multiple places can borrow it as immutable for
         | zero-cost safe references. It's like Rust but region-based, or
         | Verona but with immutable borrowing.              Pure
         | functions, where a function opens a new region for itself and
         | immutably borrows the region outside, making all references
         | into outside memory zero-cost.              "Bump calling",
         | where a pure function's region uses a bump allocator instead of
         | malloc/free.
         | 
         | [0]
         | https://www.reddit.com/r/ProgrammingLanguages/comments/hplj2...
        
           | [deleted]
        
           | scott_s wrote:
           | The author also compares and contrasts at the end of a blog
           | post: https://vale.dev/blog/zero-cost-refs-
           | regions#afterword:borro...
        
       | cryptograthor wrote:
       | Looks like a language heavily influenced by Rust! I'm interested
       | to see if we see more drift in this direction. Rust's by no means
       | conquered the world (yet), but things keep moving in that
       | direction, I'm curious if we'll see looser or otherwise quick-n-
       | dirty (https://users.rust-lang.org/t/prototyping-in-rust-versus-
       | oth...) Rust-like languages
        
         | [deleted]
        
       | xeeeeeeeeeeenu wrote:
       | Not to be confused with Vala:
       | https://wiki.gnome.org/Projects/Vala
        
         | jopsen wrote:
         | Wow, that's an extremely poor choice of name for a programming
         | language.
         | 
         | I was 100% sure this was the gnome thing.
        
           | oscargrouch wrote:
           | In portuguese 'vala' is the hole you dig on the ground or a
           | naturally occuring one. Which can also be used as a synonym
           | to "cova" which translates to "grave". I bet it will be hard
           | to make a community for it here in Brazil or Portugal.
        
             | xeeeeeeeeeeenu wrote:
             | People overestimate the impact of brand names having weird
             | meanings in foreign languages.
             | 
             | For example, OSRAM unambiguously means "I will shit" in
             | Polish, and despite that, it's one of the most popular
             | lightbulb brands in Poland.
        
         | Lapsa wrote:
         | too late
        
       | qalmakka wrote:
       | Even though I think the market for programming languages is
       | saturated and it will be for the next decade or more, I think
       | it's always nice when someone tinkers and creates something new,
       | so, my congrats to the authors!
        
         | mikewarot wrote:
         | There is plenty of idea space to explore in programming
         | languages.
         | 
         | ColorForth, for example... lets you do some of the work a
         | parser would do, at edit time, by adding additional attributes
         | to the source.
         | 
         | Verilog, Ladder Logic, and Register Transfer Language all allow
         | the programmer to specify a flow of logic and expressions that
         | is always running, instead of a flow of instructions that we're
         | all used to. Mixing this paradigm with the traditional code
         | we're used to offers powerful possibilities.
         | 
         | Transforming spreadsheets to a set of statements that are
         | always executed, and vice versa could be fruitful as well.
        
         | zomglings wrote:
         | It's important not to think of it as a market. It is pretty
         | valuable (and not in terms of dollars right now) to create
         | things like this.
        
         | mumblemumble wrote:
         | The market for programming languages has been saturated at
         | least since I got into programming. Which was not all that
         | recently.
         | 
         | The market for music has been saturated for even longer. But
         | nobody really complains when someone wants to start a band,
         | because we recognize that creative work has intrinsic value,
         | even when it produces little economic return, even if only by
         | enriching the life of its producer. Experimenting with
         | programming languages is only very superficially different from
         | that.
        
           | neutronicus wrote:
           | No reason to complain until people start bugging you to go
           | see their band or use their programming language.
        
         | dgb23 wrote:
         | I think this is a weird way of looking at it.
         | 
         | PL are evolving continuously on some level or another. New
         | languages pop up with new concepts or ways to do things, old
         | languages can then incorporate some of these things.
         | 
         | It works with all things similarly, there is a conventional
         | main-stream that most adhere to, for efficiency gains but the
         | creative risk takers are the ones who drive things forward, or
         | fail to do so.
        
           | qalmakka wrote:
           | Yes, I mostly agree with you, but I think that if we look
           | closely to how programming languages have evolved over the
           | years, we can more or less define them into "generations"
           | i.e. periods where certain concepts have more or less
           | dominated the interest of the community and have dictated how
           | software and languages in general are designed.
           | 
           | These are usually linked with one or several languages
           | springing out and becoming popular, either by embracing new
           | paradigms or by strongly rejecting a mainstream concept whose
           | usefulness have been cast into doubt either by the industry
           | or the community.
           | 
           | Outside these periods, the overall interest tends to stagnate
           | while the newer languages become stable and gain mainstream
           | acceptance. In such a situation, a new contender must either
           | find itself a niche, by covering very specific needs in very
           | effective ways, or it must compete in mindshare in order to
           | justify itself among the newest big names (i.e. any new
           | compiled, strong typed and memory safe language nowadays is
           | almost forced to compare with Rust and I dare say Zig).
           | 
           | That's what I meant with "market saturation": I think the
           | stagnant landscape of the 00s, dominated by classic, OOP
           | languages, gave birth to a huge wave of "safe" languages in
           | the 10s, many of which share similar concepts and ideas; I
           | think we're now in a moment where some of these have made a
           | name for themselves and have been established as mainstream,
           | serious solutions (see Rust or Go), requiring newer
           | contendents to be really innovative in order to capture
           | mindshare and not be considered "me too" languages.
           | 
           | These are, obviously, just my two cents; I really love
           | compiler development and language design, and I think we
           | should always support new languages and the work people do
           | towards the goal of designing better languages and improving
           | existing ones.
        
       | mikewarot wrote:
       | Why would a programmer ever worry about "ownership"? I've never
       | had to do that.
        
         | freeone3000 wrote:
         | Garbage collected languages (Java, JS) have significant
         | overhead, and unpredictable latency spikes.
         | 
         | Scope-based memory management (C++) has copying overhead and
         | destruction overhead, and a whole lot of complexity to avoid
         | those.
         | 
         | Ownership-based memory management removes most of the overhead
         | associated with copying and destruction in a less-complex
         | fashion.
        
           | ben-schaaf wrote:
           | Note C++'s semantics are akin to ownership, it just has
           | different defaults and none of the safety guarantees. A
           | std::vector is owned by the current scope, ownership can be
           | passed around using std::move and references can be taken
           | using &.
        
           | rwmj wrote:
           | _Bad_ garbage collector implementations, but not GC in
           | general. malloc /free can have latency spikes too.
           | 
           | Also not every programming problem in the world is a memory-
           | constrained hard real time problem - in fact, I would say
           | almost all of them are not.
           | 
           | Memory ownership is certainly an interesting thing to have in
           | your arsenal, but a whole class of problems (especially
           | anything with a graph or modestly complex interlinked data
           | structure) can't easily be reasoned about using this model,
           | or you end up copying stuff anyway to get around the borrow
           | checker.
           | 
           | Having said all that, I'd really like to see a language that
           | lets you use a garbage collector 99% of the time for ease of
           | use, but allows you to use other models for the small
           | sections of the code which need it or within certain
           | designated real time threads.
        
             | vips7L wrote:
             | You're looking for D!
             | 
             | https://dlang.org/spec/function.html#nogc-functions
        
             | megameter wrote:
             | I beg to differ. For a sufficiently large time scale,
             | _every_ programming problem is a memory-constrained hard
             | real time problem.
        
             | mhh__ wrote:
             | D let's you do that if you want.
        
           | mhh__ wrote:
           | Ownership is a conservative restriction of allowed behaviours
           | (i.e. rust still has ref counts), the three approaches don't
           | do exactly the same job
        
         | ben-schaaf wrote:
         | Then you haven't ever written a line of C/C++ I presume?
         | Ownership is just a formalization of the way almost all
         | resources (including memory) are managed in C: A single
         | function has the responsibility of doing cleanup; that
         | responsibility can be moved around to other functions of
         | course, but only one ever has that responsibility at a time.
        
           | mikewarot wrote:
           | >Then you haven't ever written a line of C/C++ I presume?
           | 
           | Correct... I'm a Pascal programmer. I create objects when a
           | program starts, delete them at the end. I've never really had
           | any of the pointer problems that seem to plague C/C++.
        
             | wwright wrote:
             | I assume you write fairly "static" software that knows its
             | job pretty well in advance. Ada programs tend to use a
             | similar allocation strategy.
             | 
             | A lot of programs written in C and C++ are _very_ dynamic,
             | and may need to massively increase or decrease the number
             | of objects they use while running. For example, consider an
             | audio workstation: when you first start it, it has very
             | little to do, but the user can add literally hundreds or
             | thousands of tracks, each with dozens of effects and
             | modifications.
             | 
             | Each of these features is composed of many objects.
             | _Ownership_ comes in when these objects have complex
             | relationships, where one object may need to be referenced
             | by many others. When it is time to clean up some of these
             | objects -- for example, when a user deletes a track in the
             | audio workstation -- you have to know _which_ of these
             | shared objects to delete. Ownership is one way of modelling
             | that problem.
             | 
             | Languages that talk about ownership try to optimize the
             | "best case" where an object has exactly _one_ owner,
             | because then it 's very simple for the compiler to free
             | that object. The trick is that you have to _prove_ that no
             | one else is using it, or else you have memory errors.
        
             | pwdisswordfish4 wrote:
             | > Correct... I'm a Pascal programmer. I create objects when
             | a program starts, delete them at the end.
             | 
             | Then I guess you should instead say you're a 'single-shot,
             | compiler-like batch job executable' programmer. I imagine
             | that colours your perception more than the choice of
             | programming language itself. If you were to write a program
             | that has to manipulate deeply nested data structures, or a
             | long-running service that has to acquire and dispose of an
             | unbounded number of various kinds of resources over the
             | course of its runtime in a deterministic manner, you'd
             | start longing for an ownership system very quickly.
        
               | mikewarot wrote:
               | I'm trying to imagine when I'd worry about ownership. The
               | only thing that comes to mind for me is having to provide
               | buffers for string results from OS calls, etc. In Pascal,
               | you can return a string, assign it, append it, etc.. and
               | never have to allocate/dispose of them... its taken care
               | of under the hood by automatic reference counting.
               | 
               | I'd really like to understand this... what specific type
               | of thing were you doing when you found yourself longing
               | for an ownership system?
               | 
               | [edit] It occurs to me that anytime I have objects, they
               | eventually trace their ownership to a single global
               | variable. Perhaps that has something to do with this?
        
               | steveklabnik wrote:
               | It is an alternative, in many cases, to automatic
               | reference counting. It's sort of like saying "why would I
               | need automatic reference counting? I have a tracing
               | garbage collector."
        
               | mikewarot wrote:
               | That makes sense... thanks!
               | 
               | So, in general, if something is too big to fit to easily
               | be copied, or stored in a single variable of known size
               | (like strings, dictionaries, lists, trees, etc.) its
               | either GC or ARC to the rescue?
        
               | steveklabnik wrote:
               | No problem. :)
               | 
               | That's not _quite_ it. It 's more about compile time vs
               | runtime. Arc and GC are _runtime_ tracking of  "when can
               | this be freed." Ownership is compile-time tracking of the
               | same. Rust has refcounted types in its standard library,
               | but you only need to use them relatively rarely. Here's a
               | small example with not _too_ much syntax. The core idea:
               | fn main() {             // String is a heap allocated,
               | mutate-able string type             let s =
               | String::from("foo");                      } // s goes out
               | of scope here, and so will be freed here;           //
               | the compiler generates the code to free the heap
               | allocation at this point
               | 
               | s is the "owner," and there's only one, so this can be
               | tracked fully at compile time.
               | 
               | Onwership can move, too. Let's introduce a function:
               | fn foo(bar: String) {             // body would go here,
               | elided to keep this simple                      } //
               | because bar is of type "String", this function "takes
               | ownership" of the           // value passed as 's', and
               | so the compiler will generate the code to free
               | // its heap allocation at this point              fn
               | main() {             let s = String::from("foo");
               | // we pass s to foo...             foo(s);
               | } // ... and because we did, it no longer exists in main,
               | and the compiler           // knows this, so no code to
               | free the allocation is generated here. if           // it
               | were, this would lead to use-after-free.
               | 
               | All of this is trackable, 100%, at compile time. So
               | there's no runtime overhead here at all.
               | 
               | But imagine that foo() creates a new thread inside of it,
               | and we want to access said string from inside that
               | thread, as well as from within main. Now we have
               | _multiple_ owners, not a single one, and it 's not
               | possible at compile time to know when the string should
               | be freed. The simplest solution here is to reach for
               | reference counting, and you'd end up with Arc<String>,
               | that is, a String that's wrapped in an atomic reference
               | count.
               | 
               | (Also, references _don 't_ take ownership, so if you
               | didn't want to have foo free its argument, you'd have it
               | accept a reference, rather than a String directly. This
               | would let you temporarily access the string, without
               | freeing the backing storage when the function's body has
               | run its course.
        
               | adamnemecek wrote:
               | The examples are numerous but for example databases or
               | GUI frameworks. You end up in situations where a parent
               | needs a reference to a child and child needs a reference
               | to its parent and it gets unwieldy.
        
             | randomNumber7 wrote:
             | > Correct... I'm a Pascal programmer.
             | 
             | Real men don't use pascal ;)
             | 
             | Have you ever closed a file?
        
         | epage wrote:
         | So everyone else is focusing on the memory allocation side of
         | ownership. The other side to this is aliasing / borrowing /
         | handling references and mutability.
         | 
         | In Python, you might have a `list` that you built up and them
         | pass its data to multiple functions. You assume these functions
         | are do not mutate their arguments and you keep passing the same
         | `list` over again. In this case, the caller is controlling the
         | invariants of the `list` and therefore "Owns" it.
         | 
         | Deep down, one of those functions needs to mutate a `list` to
         | do its calculations. Where the mutation is happening, it
         | assumes it is the "Owner" and can modify the `list` without
         | violating any invariants. Unfortunately, a "Borrowed" list was
         | passed in and now the caller's invariants are violated.
         | 
         | Rust's ownership model helps to catch this kind of problem at
         | compile time. By default, everything is single-owner though you
         | can change that with a `Mutex`.
        
           | creata wrote:
           | Yep. Even when you're doing something as simple as iterating
           | over some data structure, you have to remember not to mutate
           | it. Rust enforces that, but Python just either corrupts the
           | data structure / iterator, or _if you 're lucky_ it'll throw
           | an exception.
        
         | ycombonator wrote:
         | Valid question. if you started programming dynamic languages
         | like Python you don't have to worry about memory control.
        
         | kzrdude wrote:
         | It's an object lifecycle concept.
         | 
         | You worry about ownership if you have a resource and need to
         | think of when to free/dispose/close it.
         | 
         | You worry about ownership if you have an object that many have
         | a reference to, and some of the references shouldn't keep the
         | associated resources alive, and some other of the references
         | should keep it alive. Those that keep things they referenced
         | alive are (shared) owners.
        
         | mhh__ wrote:
         | https://xkcd.com/371/
        
           | hhas01 wrote:
           | Also: https://xkcd.com/927/
        
         | krisoft wrote:
         | It's a memory safety concept.
         | 
         | In languages like C you allocate memory yourself, and then you
         | have to make sure to free it up too. This is error prone.
         | 
         | In garbage collected languages like Java there is a garbage
         | collector who figures out when is a piece of memory no longer
         | in use. This has run-time cost.
         | 
         | The third possible way is to make the ownership of that part of
         | the memory explicit. This way the compiler can check memory
         | safety at compile time.
         | 
         | There is a much better description of this in the Rust book:
         | https://doc.rust-lang.org/book/ch04-01-what-is-ownership.htm...
        
       | itwy wrote:
       | Isn't this the same language heavily used by ElementaryOS devs?
        
         | rudedogg wrote:
         | You're thinking of Vala (https://valadoc.org/) not Vale.
        
           | itwy wrote:
           | Ugh ridiculous naming then
        
         | detaro wrote:
         | nope, that's Val _a_
        
       | z_kro wrote:
       | Sounds good, but the name may confuses it with Vala
       | https://wiki.gnome.org/Projects/Vala
        
       | tempodox wrote:
       | Is it interpreted or compiled, AOT or JIT, native or byte code?
       | The landing page doesn't say, but I'd like to know such details
       | and a host of other information that isn't mentioned either. All
       | this doesn't motivate me to dive deeper.
        
       ___________________________________________________________________
       (page generated 2020-11-20 23:00 UTC)