I'm aware that there are a few languages that come close to this (crystal iirc), but in the end it's adoption and the ecosystem that keeps me from using them.
I'm aware that there are a few languages that come close to this (crystal iirc), but in the end it's adoption and the ecosystem that keeps me from using them.
[1] https://doc.rust-lang.org/book/ch15-04-rc.html
[2] https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
You’re telling people to just ignore the paved road of Rust, which is bad advice.
The method documentation alone in reference counting is more pages than some entire programming languages. That’s beside the necessary knowledge for using it.
Mutexes and reference counting work fine, and are sometimes dramatically simpler than getting absolutely-minimal locks like people seem to always want to do with Rust.
I tell everybody to .clone() and (a)rc away and optimize later. But I often struggle to do that myself ;)
I do think that a superset of Rust that provided first-class native syntax for ARC would be much more popular.
(To be clear, using RC for everything is fine for prototype-level or purely exploratory code, but if you care about performance you'll absolutely want to have good support for non-refcounted objects, as in Rust.)
Edit: Googled it. Found an answer:
> The only distinction between Arc and Rc is that the former is very slightly more expensive, but the latter is not thread-safe.
[1] https://doc.rust-lang.org/rust-by-example/std/rc.html
But these days .NET is a great server-side option. One of the fastest around, with a bit of tuning.
F# being on top of the CLR and .NET is a benefit. It is very easy to install .NET, and it comes with a huge amount of functionality.
If you're asking if the language F# could be ported to another VM, then I'd say yes, but I don't see the point unless that VM offered similar and additional functionality.
You can use F# as if C# didn't exist, if that's what you mean, and by treating .NET and CLR as an implementation detail, which they effectively are.
Other than that, the question is indeed strange and I agree with your statements.
That's what ReasonML is? Not quite "exploding" in popularity, but perhaps more popular than Ocaml itself.
Still, the language is great. Plus, it has Java interop, JVM performance, and Jetbrains tooling.
You could still have your IDE showing you type hints as documentation, but have inferred types to be more fine grained than humans have patience for. Track units, container emptiness, numeric ranges, side effects and idempotency, tainted values for security, maybe even estimated complexity.
Then you can tap into this type system to reject bad programs ("can't get max element of potentially empty array") and add optimizations (can use brute force algorithm because n is known to be small).
Such a language could cover more of the script-systems spectrum.
Or is this about libraries and API compatibility?
* I have seen examples of spooky-action-at-a-distance where usage of a function changes its inferred type, but that goes away if functions are allowed to have union types, which is complicated but not impossible. See: https://github.com/microsoft/TypeScript/issues/15114
If I download a random project and delete the interface files, will that be enough to see issues, or is it something that happens when writing new code?
The problem is when it doesn't complain but instead infers some different type that happens to match.
Despite type systems being powerful enough to figure out what types should be via unification, I don't think asking programmers to write the types of module declarations is too much. This is one area where forcing work on the programmer is really useful to ensure that they are tracking boundary interface changes correctly.
There are a lot of adjectives you can use to describe Scala - mostly good ones! - but "small" just isn't one of them.
0: https://docs.scala-lang.org/tour/tour-of-scala.html#what-is-...
The whole point of rusts type system is to try to ensure safe memory usage.
Opinions are opinions, but if I’m letting my runtime handle memory for me, I’d want a lighter weight, more expressive type system.
I do also believe this might be a sweet spot for a language, but the details might be hard to reconcile.
Edit: I would also prefer shared nothing parallelism by default so the GC can stay purely single threaded.
Same for Box, but in fact Rust went the opposite way and turfed the Box ~ sigil.
Which I actually feel was a mistake, but I'm no language designer.
Aaaah, I'm realizing in typing this that the `@foo` syntax was actually implemented via reference counting? I think my intuition at the time was that the intention was for those to eventually be backed by a mark-and-sweep GC, which I did think was a poor fit for the rest of the language. But as just a syntax for reference counting, I honestly think it might have been an ok fit.
Or maybe not, I'm ambivalent. But the syntax thing in my comment is more of a red herring for what I think is more of a cultural "issue" (to the small extent it is an issue at all), which is that most Rust projects and programmers seem to try to write in a style that defaults to only choose reference counting when they must, rather than using a style of optimizing them out if they show up in a hotspot during profiling.
Regardless of the specifics here, the same problems apply. Namely that it privileges specific implementations, and makes allocation part of the language.
It wouldn't be a good fit for projects like the ones at Oxide :) I'm very glad Rust itself exists, with good support for use cases like those!
Lifetimes elision works pretty well so you don't often need to specify lifetimes
It usually pops up when you use generics / traits (what concrete type does it match to?)
But I don’t think it prevents any more logic bugs than any other type system that requires all branches of match and switch statements to be implemented. (Like elm for example)
It isn't though. The whole trait system is unnecessary for this goal, yet it exists. ADTs are unnecessary to this goal, yet they exist. And many of us like those aspects of the type system even more than those that exist to ensure safe memory usage.
I think traits muddy that goal, personally, but their usefulness outweighs the cost (Box<dyn ATrait>)
I should’ve probably said “the whole point of rusts type system, other than providing types and generics to the language”
But I thought that went without saying
It ... just ... isn't, though.
I mean, I get what you're saying, it's certainly foundational, Rust would look incredibly different if it weren't for that goal. But it just isn't the case that it is "the first and foremost goal of every language choice in rust".
I followed the language discussions in the pre-1.0 days, and tons of them were about making it easier and more ergonomic to create correct-if-it-compiles code, very often in ways that had zero overlap with safe memory usage.
Traits don't "muddy that goal", they are an important feature of the language in and of themselves. Same thing with the way enums work (as arithmetic data types), along with using Option and Result for error handling, rather than exceptions. Same thing with RAII for tying the lifecycle of other resources to the lifecycle of values.
The memory safety features interact with all these other features, for sure, and that must be taken into account. But there are many features in the language that exist because they were believed to be useful on their own terms, not in subservience to safe memory usage.
And it's not just about "providing types and generics to the language", it's a whole suite of functionality targeted at static correctness and ergonomics. The ownership/lifetime/borrowing system is only one (important!) capability within that suite.
You might have to lose a few parens though!
For me it seems like the perfect match.
https://pcwalton.github.io/_posts/2013-06-02-removing-garbag...
That has changed through the years: https://graydon2.dreamwidth.org/307291.html
Well, since you can't really use without high adoption even if something comes up with all features you want, you still won't be able to use it for decades or longer.
There is Rune, but like you mentioned the issue is adoption, etc.
Most people don't. That's not the fun part of language design.
Whenever I've had to write kotlin for Android in the past I did quite enjoy it. It seems like the entire ecosystem is very enterprise-y when it comes to web though. Forced adherence to object orientedness and patterns like 100 files, 5 folders deep with 10 lines of code each keep cropping up in most kotlin projects I've seen.
Also, syntax does actually matter, because it's the first thing people see, and many people are immediately turned off by unfamiliarity. Rust's choice to largely "look like" c++/java/go was a good one, for this reason.
But I like ocaml both in theory and practice (also in part due to having my eyes opened to SML about 20 years ago).
Still with OCaml finally supporting multicore and still getting active interest, I often ponder going back and starting a project in it someday. I really like what I see with MirageOS.
These days I just work in Rust and it's Ok.
Imperative code with functional constructs seems like the most workable approach to me, which rust, go, and other languages like kotlin, crystal etc. all offer.