13 ms·
Hmmm...I disagree with a number of statements in the post but I think the following two hypotheses will make for more interesting discussion than some nitpicks:
by noelwelsh 2y ago
Hmmm...I disagree with a number of statements in the post but I think the following two hypotheses will make for more interesting discussion than some nitpicks:
1. A large part of why many people love Rust is that it's the first time they've used an ML family language. One of the innovations of Rust was to create a community that felt like home to Unix hackers who weren't programming language nerds.
2. Rust is the first language to bring non-GC automatic memory management to the mainstream. It won't be the last and it might well be the worst. Other languages in this space include Swift (as in OP's post), OCaml[1], and Scala[2]. These alternatives take the approach that tracking ownership is not the default, which is fine for the majority of programs and far more ergonomic.
There's also a corollary
3. The age of Smalltalk is over. It's now the age of ML. (Amusingly, going backwards in time, from 1983 to 1975). The languages that dominated the 2000s (Ruby, Python, Javscript, PHP) were all more or less derived from Smalltalk (everything is an object! dynamic types! runtime metaprogramming!) The new languages (Rust, Scala, Swift, Kotlin, etc.) are ML family languages. Similarly, back in the day you could learn, say, Ruby, and still be reasonably proficient in Python or JS. Now you can learn, say, Scala, and pick up Rust or Swift reasonably easily.
[1]: https://blog.janestreet.com/oxidizing-ocaml-locality/ https://blog.janestreet.com/oxidizing-ocaml-locality/
[2]: https://dl.acm.org/doi/full/10.1145/3618003 https://dl.acm.org/doi/full/10.1145/3618003
- the_duke 2y agoAd 3) Scala is quite a bit older than the others, I'd put it in a previous generation. I always saw Kotlin as a more convenient Java, without Scalas heavy tilt towards FP. Java also added the equivalent of sum types with sealed interfaces and exhaustive pattern matching, does that make Java an ML language? Many older languages by now have incorporated valuable parts of FP/ML (including Javascript, Java, C++, ...) Borrowing some concepts from ML doesn't put these languages in the ML family.
- SSLy 2y ago> does that make Java an ML language? not really, the type-system-sublanguage is still modelled like classy OOP, not more like MLy modules.
- nextaccountic 2y agoBut Kotlin is like this too.
- SSLy 2y agoIndeed, and Scala (at least the version I've tried 10 years ago) tries to do both, somewhat poorly. shrug
- valenterry 2y agoPersonally I found Scala's module/import system to be really really good. There are some annoying things with it, but they mostly come from JVM/Java compatibility.
- SSLy 2y agoYeah, it's the compat that I vaguely recall being kludgy.
- valenterry 2y agoOCaml is older than Scala though. > Java also added the equivalent of sum types with sealed interfaces and exhaustive pattern matching, does that make Java an ML language? I don't think so. Java heavily relies on mutation and you can see this throughout the whole ecosystem and even the JVM whereas OCaml doesn't. Kotlin also relies on mutation (it relies on Java's stdlib after all) whereas Scala has its own stdlib with both mutable and immutable classes but defaulting to immutability almost everywhere. So if anything, Scala can be called an ML language imho.
- arghwhat 2y ago> Rust is the first language to bring non-GC automatic memory management to the mainstream To nitpick, the first language to bring non-GC automatic memory management to the mainstream would be either Forth or C through stack memory. For heaps, we have reference counting, often handled automatically through the stack (e.g., C++ smart pointers). The thing Rust brought to mainstream is not automatic memory management - they're a dime a dozen with and without GC. It's an ownership model that is strict about whether you have read or write access within the type system. At the same time, this is also where most developer friction stems from, as it's quite unique, and you're often faced with a trade-off between explaining exactly what you want at compile-time at higher design cost, or bailing out more to runtime checks with e.g. RefCell while getting fewer guarantees about code correctness from the compiler.
- pjmlp 2y agoNot at all, considering the decade of high level systems programming languages that predated the very thought of C coming into life. All with stack allocation.
- arghwhat 2y agoKeyword is mainstream, so it’s not when the idea was invented - I think Forth popularized it? I can’t really comment on what counted as mainstream before C though. Not old enough for that.
- pjmlp 2y agoMainstream is whatever people could use between 1958 and 1969, as high level programming language, in whatever computers, universities and companies could afford. Goggle, Bing, DuckDuckGo, ChatGPT,... will gladly provide a list.
- arghwhat 2y agoWhat people could use is not at all what mainstream is. You can use D, OCaml, F# and brainfuck, but they are not mainstream. To define what was mainstream we'd need to talk to people coding at the time and ask them about popularity, adoption, tooling availability, etc. and what languages people were likely to use rather than what was available. And no, I have no need for researching that as I have no use of the information - the point is to say that automatic memory management in mainstream languages predate rust by decades and is present in most languages, not "this specific language should get credit".
- est31 2y ago> Rust is the first language to bring non-GC automatic memory management to the mainstream. It won't be the last and it might well be the worst. Other languages in this space include Swift Rust's memory management is not automatic, you have to explicitly manage memory. It's just made extremely easy for you by the language thanks to stuff like RAII, and there is checks that prevent memory safety violations like double free. But those checks won't prevent leaks, although the many lints do make it harder to forget about a value. Also, Swift's refcounting can be seen as a form of gc.
- kaba0 2y agoYeah, the correct statement would be ‘Rust is the first mainstream language without GC, that guarantees memory safety’ (with obviously the caveat of unsafe blocks, but than you can also sun.misc.unsafe yourself into segfault in java).
- lolinder 2y ago> Rust's memory management is not automatic, you have to explicitly manage memory. It's just made extremely easy for you by the language thanks to stuff like RAII, and there is checks that prevent memory safety violations like double free. But those checks won't prevent leaks, although the many lints do make it harder to forget about a value. By this logic no language on earth has automatic memory management. I've spent time troubleshooting a memory leak in JavaScript in the past month, caused by someone keeping a pointer around longer than necessary. Rust's memory management is automatic in that you can write entire Rust programs without once calling `free` manually. I'm not sure what definition of automatic you're working off of, but if it excludes JavaScript it doesn't seem especially useful.
- bryancoxwell 2y agoPointers in JavaScript? I’m far from a JS expert, but didn’t think the language had pointers. Could you explain what you mean here?
- lolinder 2y ago
- dgellow 2y agoSwift does have garbage collection via reference counting
- zerr 2y agoYes, usually GC vs non-GC discussion is actually about deterministic vs non-deterministic memory management. Swift's ref-counting is deterministic.
- benreesman 2y agoI think if Linear/Affine typing was a default anyone wanted, Haskell hackers (who are usually pretty concerned with performance) would regard it as more than a research oddity. When people bitch about the borrow checker, what they usually mean is “std::move is a great wristwatch but god damn does it chafe as a chastity belt”.
- mananaysiempre 2y agoGHC Haskell is a fairly large language with a considerable legacy already, so integrating linear or affine types into it may well be a very different question from making a language centered around them. That language exists in the form of Clean[1,2]. Admittedly it’s not really well-known. [1] https://clean.cs.ru.nl/ https://clean.cs.ru.nl/ [2] https://clean-lang.org/ https://clean-lang.org/
- benreesman 2y agoThank you for making me aware of Clean, on quick glance it looks cool. I like a lot of things about Rust: it’s got compiler checked exhaustive pattern match and a good initialization syntax and Either baked in and fucking correct package management and a ton of other things. I’ll look at Clean to see if linear-only memory management can be done gracefully. Rust is a lot of cool things but not the language that demonstrated that.
- MarcusE1W 2y agoThere is also Austral, which has linear types as a main capability: https://austral-lang.org/ https://austral-lang.org/
- zozbot234 2y agoThe whole point of Haskell as a programming language is to have lazy evaluation be the default. This comes with boxing data objects everywhere, which is the opposite of a focus on low-level performance. Haskell does support using strict, unboxed data but it's clunky and not the default. (Also, recent versions of Rust have now added support for "plug-in" laziness via the type constructors LazyCell<> and LazyLock<>.)
- timeon 2y ago> These alternatives take the approach that tracking ownership is not the default, which is fine for the majority of programs and far more ergonomic. If you want non-default safety you do not need to leave C++. That is why unlike all these new languages, Rust makes difference.
- zozbot234 2y agoSwift 6 is expected to be memory safe, including for concurrent programs. That's a lot more than you can say about C/C++. (This is achieved by tracking ownership at runtime when required. Rust allows for this via library types such as Rc<> and RefCell<>, which is more principled but obviously adds some boilerplate compared to Swift.)
- tgv 2y agoRust is not really an ML language, is it? &mut is a very noticeable difference. Calling Rust, Scala, Swift and Kotlin ML seems to be taking it too far. Scala and Kotlin even have all the traditional OOP features. You might just as well put C++ in the ML list.
- foldr 2y agoML has mutable references: https://saityi.github.io/sml-tour/tour/02-09-mutable-refs.html https://saityi.github.io/sml-tour/tour/02-09-mutable-refs.ht... (OCaml has something similar too.)
- lolinder 2y agoIf &mut makes Rust not in the ML family then none of the languages they list are in the Smalltalk family either—there's no concept of an image, everything is in files! It's pretty clear that we're talking about very broad families, which is okay—Rust has more in common with ML than it does with Smalltalk or ALGOL (though the ALGOL heritage is definitely present).
- tialaramex 2y agoIt's not the Standard ML of New Jersey of course, like I was taught last century, but it looks like an ML to me. Rust has a sound type system, whereas a language like C++ inherits C's YOLO approach to typing. In Rust Vec<Option<Infallible>> is just a counter. Really, that's not theory that'll just happen by default because of how type arithmetic works. In C++ you can't even write down an equivalent type, let alone say how it would be represented, the type system blows up long before we get there.
- koverstreet 2y agoCould you elaborate? I would think Vec<Option<Infallible>> would have to be a bit vector.
- zozbot234 2y agoInfallible is a clunky name for the Never type in Rust, i.e. a type that has no values and cannot be instantiated. Thus, Option<Infallible> only has a single value, viz. None. Then Vec<Option<Infallible>> is isomorphic to Vec<()> which reduces to a length field - there's no other data associated with it.
- alex_smart 2y ago> The languages that dominated the 2000s (Ruby, Python, Javscript, PHP) were all more or less derived from Smalltalk One of these is not like the others. Javascript derives from Lisp (first-class functions, lambdas, closures), not Smalltalk.
- panzi 2y agoPython has those too, although with less convenient syntax (multiline functions (closures) can only be at statement locations).
- alex_smart 2y agoSure, but use of those patterns is not idiomatic in Python.
- robertkrahn01 2y agoBrendan Eich used both Scheme and Self as inspirations. Self is a dialect of Smalltalk. https://en.wikipedia.org/wiki/Brendan_Eich https://en.wikipedia.org/wiki/Brendan_Eich
- pessimizer 2y agoDid you link his biography? The claim is that he used Self as an inspiration, not that there was once a man named Brendan Eich.
- astrobe_ 2y agoMore than features, JS derives from Lisp because its author was a Scheme implementor. Otherwise function pointers are trivially done even in assembly language, and Smalltalk does have closures. Or maybe you think of the fact that JS uses prototype-based OOP, which makes it closer to what one would do with Scheme (something inspired from CLOS I guess) than Smalltalk ?
- pjmlp 2y agoPrototype-based OOP came first in SELF, a Smalltalk dialect. CLOS is an evolution from Flavors and similar Lisp packages, and outside Lisp, Julia would be the closest to it, in modern times, not counting Dylan.
- bad_user 2y ago> first language to bring non-GC automatic memory management to the mainstream ... Other languages in this space include Swift Ugh, “Arc”, aka (automatic) reference counting, is an implementation of GC as well. It may have certain characteristics, like having worse throughput, corner cases, and better predictability/latency characteristics, but it's GC nonetheless. That's not manual memory management. Swift is not a non-GC language. And that's the big issue that people are missing — Rust tackles some hard problems regarding memory management, and a friendlier alternative exists: garbage collection.
- rcruzeiro 2y agoBoth ARC and garbage collection are memory management techniques. ARC does not equal garbage collection though. Garbage collection runs at intervals and is triggered by certain signals (memory pressure, etc), pauses all threads and scans for objects that can be deallocated. It is a very different concept than ARC.
- twoodfin 2y agohttps://courses.cs.washington.edu/courses/cse590p/05au/p50-bacon.pdf https://courses.cs.washington.edu/courses/cse590p/05au/p50-b... This paper makes a strong argument that “pure” tracing garbage collection and “rote” reference counting are effectively duals at the opposite ends of a spectrum of implementation choices. For example, GC’s often optimize differently for young vs. old objects. How do they distinguish these? By “counting” (one bit) their references across one or more traces in a series of sweeps.
- 01HNNWZ0MV43FF 2y agoAnd a hot wheels car is a car, but I would be perplexed to see one offered to me at a car dealership
- Tuna-Fish 2y agoARC is a method of implementing garbage collection, and is discussed as such in academic literature. What you are equating with "garbage collection" is Mark-Sweep, which is an another way to implement GC, with a very different set of tradeoffs. (Broadly, better throughput at the expense of higher latency.)
- Loic 2y agoIn this context, ML is Meta Language: https://en.wikipedia.org/wiki/ML_(programming_language) https://en.wikipedia.org/wiki/ML_(programming_language)
- kingofthehill98 2y agoThank you! The whole time I was like "what in the absolute hell is a ML language".
- high_priest 2y agoI've heard so much about Machine Learning in recent years, that I couldn't fathom ML be used in any other context & be understood.
- noobr 2y agothanks, i'm bad at abbreviations and don't like when people just throw them like this without first using the whole term at least once
- plorkyeran 2y agoExpanding this abbreviation conveys zero information. It’s a programming language named ML, and if you haven’t heard of it then giving the etymology of the name isn’t going to help.
- duckmysick 2y agoIt clarifies it's not something else I've heard of (markup language, machine learning). The ML abbreviation shares the space with other terms so it can be confusing. Compare it to HTML which is 1) more popular and 2) unique in the context of programming.
- jamwil 2y agoHuh? If I search ‘Meta Language’ I get the exact information I need. If I search ‘ML’ I get less than nothing.
- IsTom 2y ago> (Ruby, Python, Javscript, PHP) were all more or less derived from Smalltalk I'd argue that Erlang (with gen_servers being "objects") has more in common with Smalltalk than these.
- lucideer 2y ago> The age of Smalltalk is over. It's now the age of ML [...] The languages that dominated the 2000s (Ruby, Python, Javscript, PHP) were all more or less derived from Smalltalk [...] The new languages (Rust, Scala, Swift, Kotlin, etc.) are ML family languages. What drew people to a lot of your examples (Javascript, PHP especially) was the runtimes rather than the language features. Your example sets aren't just demarcated by Smalltalk-ishness/ML-ness but more by runtime type (Scala & Kotlin are odd examples given the VM but for the most part your latter examples have build-time compilation while the former have plaintext interpreters). We're definitely in a tools-heavy era of programming where, unless you're writing bash scripts, even very basic applications in interpreted languages are layered with a slew of transpilation/compilation/etc., but generally speaking I still don't see the majority of people moving wholesale away from plaintext runtime interpreters. Where are the ML-ish competitors in that space?
- noelwelsh 2y agoGood point. The nitpicky take: a lot of these languages come with a repl / console. E.g. the most recent version of Scala builds Scala CLI[1] into the language. You can run `scala repl` and just type code into it, or run `scala SomeFile.scala` and it will compile and run `SomeFile.scala`. There is special syntax for writing dependencies so that a single file can pull in the libraries it needs. The 5head thought leader take: the traditional model for typed languages has two phases: compile time and run time. Types exist at compile time. This is inadequate for many applications, particularly interactive ones. E.g. a data scientist doesn't know the shape (type) of the data until it is loaded. It should be possible to infer the type from the data once it is loaded and make that type available to the rest of the program. We know how to do this (it's called staging) but it's just not available in the vast majority of languages. Staging, and metaprogramming in general, is perhaps the next great innovation in programming languages (which will take us from ML to Lisp). In general, the challenge for these new languages is to reach "down" into the simpler scriptier applications, instead of the "serious" programming they are usually built for. [1]: https://scala-cli.virtuslab.org/ https://scala-cli.virtuslab.org/
- hyperbrainer 2y agoAbout the time travel to past aspect, I wonder if we will have an age of lisp now? I know Lisp is very popular in some niches(zB Emacs), but I really want to see innovations in syntax from the current standard of too many brackets. (M-expressions?)
- hollerith 2y agoYou seem to assert that OCaml doesn't use a run-time garbage collector: >Rust is the first language to bring non-GC automatic memory management to the mainstream. . . . Other languages in this space include . . . OCaml[1] But your own link[1] says, >The OCaml compiler does not statically track lifetimes. Instead, it relies on a garbage collector to figure out a suitable lifespan for each value at runtime. Values are collected only after they become unreferenced, so OCaml programs are memory-safe. To a first approximation, this model requires allocating all values on the heap. Fortunately, OCaml’s generational GC can efficiently handle . . . Scala does run-time garbage collecting, too (or rather the JVM does, which Scala depends on at run-time) unless I'm very much mistaken.