4 ms·
Come on, the author is comparing Rust to Typescript, Zig and Python, and then concludes that Rust becomes more productive in larger codebases compared to 'some
by misja111 1y ago
Come on, the author is comparing Rust to Typescript, Zig and Python, and then concludes that Rust becomes more productive in larger codebases compared to 'some other language'?
Could it be that those 3 languages were not really designed with large (backend) codebases in mind?
To do a fair analysis the author should have compared with a language like Java, Scala or C#.
About the article itself: the part of wrapping a structure in a mutex because it is accessed concurrently is a bit of a red flag. If you are really working in large codebases, you'd like to avoid having to do that: you'd much rather encapsulate that structure in a service and make sure all access to the structure is queued. Much simpler and less chance for nasty deadlocks.
- Ygg2 1y ago> To do a fair analysis the author should have compared with a language like Java, Scala or C#. Wouldn't that be unfair to them? They still use null or Nullable. They don't have ADTs, their thread-safe invariant is maintained by docs, etc.
- misja111 1y agoMaybe. But at least these languages were meant for large applications so the outcome of the comparison would be more meaningful. Apart from that, Scala uses the Option type instead of null, and it has ADT's; And I dont know about C# but in Java and Scala using low level mutexes is considered a code smell, the standard libraries provide higher level concurrent data structures. On top of that, Scala provides several widely used IO frameworks that make dealing with concurrency and side effect much more simple and less error-prone, it would win the comparison with Rust here.
- Ygg2 1y ago> On top of that, Scala provides several widely used ... With Scala is less what you miss, and more what you have. - Custom operators. Those are great for DSLs and rendering your code to look like utter gibberish, and confuse IDEs. - SBT. Shudder. - Scala 2 codebases.
- misja111 1y agoYour first 2 are good points. Your last point is of course not relevant when you're considering which language to pick for your new enterprise application. Anyways, IMO it would have been much more interesting and useful to compare Rust with Scala/Java/C#, whatever the outcome of the comparison would be.
- Ygg2 1y ago> Your last point is of course not relevant when you're considering which language to pick for your new enterprise application. Sure I might be writing a new app, but what if some dependency is Scala 2.12-? As for your latter point. I still think Rust would be more productive than all listed. I would expect Scala might give Rust the biggest run for its money. C# could probably be closest to Rust perf wise. Or not. Depends on the workload.
- pjmlp 1y agoJava and Scala certainly have ADTs, while Scala and C# have nullable types support.
- Ygg2 1y agoOk, I should have been more specific. By ADT I meant sum types, or, to be even more exact, discriminated union. Everyone and their mother has product types. Java doesn't have a discriminated union for sure (and C# as of 8.0). It does have a `|` operator that can cast two objects to the nearest common ancestor. Having nullable support is the issue. I've played around with it in C#. Nullables are horrible. And I say this as someone who was formerly in Option<T> is horrible. You can easily cause type confusion, and if the number of times a non-nullable has been nullable (or at least has appeared as that in the debugger) was greater than zero. To be fair there was reflection and code generation involved.
- pjmlp 1y agoI advise you to update your language knowledge to Java 24, C# 13, Scala 3. From another comment of mine, type Exp = UnMinus of Exp | Plus of Exp * Exp | Minus of Exp * Exp | Times of Exp * Exp | Divides of Exp * Exp | Power of Exp * Exp | Real of float | Var of string | FunCall of string * Exp | Fix of string * Exp ;; Into the Java ADTs that you say Java doesn't have for sure, public sealed interface Exp permits UnMinus, Plus, Minus, Times, Divides, Power, Real, Var, FunCall, Fix {} public record UnMinus(Exp exp) implements Exp {} public record Plus(Exp left, Exp right) implements Exp {} public record Minus(Exp left, Exp right) implements Exp {} public record Times(Exp left, Exp right) implements Exp {} public record Divides(Exp left, Exp right) implements Exp {} public record Power(Exp base, Exp exponent) implements Exp {} public record Real(double value) implements Exp {} public record Var(String name) implements Exp {} public record FunCall(String functionName, Exp argument) implements Exp {} public record Fix(String name, Exp argument) implements Exp {} And a typical ML style evaluator, just for the kicks, public class Evaluator { public double eval(Exp exp) { return switch (exp) { case UnMinus u -> -eval(u.exp()); case Plus p -> eval(p.left()) + eval(p.right()); case Minus m -> eval(m.left()) - eval(m.right()); case Times t -> eval(t.left()) * eval(t.right()); case Divides d -> eval(d.left()) / eval(d.right()); case Power p -> Math.pow(eval(p.base()), eval(p.exponent())); case Real r -> r.value(); case Var v -> context.valueOf(v.name); case FunCall f -> eval(funcTable.get(f.functionName), f.argument); case Fix fx -> eval(context.valueOf(v.name), f.argument); }; } }