6 ms·
I can see moving from C/C++ to Rust for buffer-copying style codes, but for most code general-use programs the cognitive load required to deal with resource man
by thelazydogsback 7y ago
I can see moving from C/C++ to Rust for buffer-copying style codes, but for most code general-use programs the cognitive load required to deal with resource management seems way to high to move from from Java/C#/Node to Rust. (I just got called about a shop moving their Node code to Rust, and I can't imagine why any code that would make good Rust code was written in JS in the first place.) Go seems like a non-starter to me -- sure features can be abused (as implementation inheritance has been for years) but to omit generics at this point just seems silly.
As for moving from C# to Rust, you can learn to program with the Span<> APIs and get the non-GC perf. of Rust for the most part and still keep GC and other C# niceties (like the whole toolchain and ecosystem...) in much less time than a wholesale move to Rust. As as for message-passing/agent/channel programming, you can certainly do that in C# if you like, and though there is certainly a lot a foot-shooting that can be done with async and thread contexts, in general the Task<> system is a joy to use compare to almost anything else out there, not only for async code, but for concurrent code.
Don't get me wrong, I always thought that C++ was a "worst of all worlds" language and appreciate moving to Rust from there, but for most user-facing applications that tend to have complex object lifetimes, I just can't see why you'd want to deal with RIAA when modern GC's are so darn good.
- munk-a 7y agoAh the Generics, the fact that empty interfaces have been accepted as the way to get things done is absolutely terrifying to me. I understand that C++'s approach to generic type usage has slowly evolved into the most absurd collection of left angle brackets out there but Go seriously needs to shape up about generics, when people are regularly hacking your logic rules and advising others to do the same thing then... maybe there was an error in your rules. Go is interesting and I really wonder how it'd be doing if someone went all in on the multi-return syntax sugar (pretty awesome stuff), the prohibition (mostly) on exceptions, channels and trivial threading and a bunch of other nicely packaged features while giving some ground on Generics. All languages have their warts, but I think this one is particularly easy to address - though it may take a major version bump and introduce some BC breaks I feel like those could be minimized, the biggest cost would be library incompatibility.
- erik_seaberg 7y agoMultiple return values are a lot less general and harder to use than tuple values; you can't store them in maps or pass them over channels or compose functions (while f(g()) works, f(g(), h()) is not allowed).
- masklinn 7y agoYou could implement an entire corner of the language to work with special-cased / non-reified MRV, that's what Common Lisp does. Go doesn't do that though. There is some magic for builtins (e.g. variable-arity MRV) but as usual mere mortals need not apply.
- otabdeveloper2 7y ago> C++'s approach to generic type usage has slowly evolved into the most absurd collection of left angle brackets out there C++ templates are a purely-functional Lisplike language. There's nothing strange or absurd about it; it's a very vanilla way to approach string rewriting systems. (It's ugly to read, yes, but then all Lisplikes are too.)
- dochtman 7y agoHave you actually used Rust? I spend very little time (or code) on resource management when writing Rust code. And when I do, it's usually the compiler helping me understand an aspect of my design that doesn't work as I expected. Sure, other languages might allow me to gloss over that, but that will likely come down to finding the edge case in production.
- thelazydogsback 7y agoI have a bit -- but I don't have a project that makes sense to do in Rust at the moment. I'm mostly doing long-running symbolic AI code where I don't want to mess around with object lifetime because imposing the concept of "ownership" would be difficult. (F#/C# is the best fit at the moment.)
- marmaduke 7y ago> long-running symbolic AI code That sounds cool. An obvious question is, why not a lisp? But generally do you find f# works well on dotnet mixed with c#?
- thelazydogsback 7y agoI love Lisp and Prolog the languages and I went there first -- the issue always turns out to be either (a) they make hard stuff really easy, but stuff that should be easy really hard, and (b) IMHO nothing even comes close to the .Net ecosystem when it comes to debugging tools, libs, etc. Clojure+Cursive comes closest, but the JVM world is a bit of a turn-off for me -- maybe I've been away from it too long, but it just seems a bit clunky. (And of course, reified generics, value types, etc., aren't available in the JVM.) The meta-programming story isn't as good as in Lisp/Prolog of course. JS (as others have said) an acceptable Lisp and has some advantages for the type of work I'm doing -- my problem with JS (and Typescript) isn't the language, but the run-time environment of Node, which makes things like true parallel programming a PITA and incurs serialization overhead between workers.
- 7y ago
- otabdeveloper2 7y ago> the cognitive load required There's no cognitive load required to code in C++. You just don't know the language. There's no easy tutorials or learning materials for it, but it's not hard.
- arcticbull 7y agoIm not sure if this is sarcasm, honestly. C++ is one of the hardest languages to use, full of edge cases, it blows my mind every time I pick it up. > You just don't know the language. Nobody knows the language haha. If anyone tells you they know C++, they're absolutely wrong. This has been, IME, the easiest way to know if a candidate is over-stating their resume -- if they say they "know" C++.
- otabdeveloper2 7y ago> C++ is one of the hardest languages to use, No. > full of edge cases, Definitely no. > it blows my mind every time I pick it up. I'm tempted to say "programming is not for you", but I'll be charitable and just point out that you've never learned the actual language to make statements like that. > If anyone tells you they know C++, they're absolutely wrong. That's a load of crapola. It's impossible to "know C++" in the sense of knowing the ISO standard for C++; but that is also true of any other language with a real standard. Languages without standards, of course, are worse in every way.
- code_sloth 7y ago>> C++ is one of the hardest languages to use > No. Most defenses I've seen of C++ boils down to something along the lines of "you're using it wrong (tm)". I've seen enough C++ to take the side of "the design is probably wonky if it's that easy to do the wrong thing."
- otabdeveloper2 7y ago> Most defenses I've seen of C++ boils down to something along the lines of "you're using it wrong (tm)". Maybe, but that wasn't what I said. The problem is that lots of people know C, but very, very few people know C++. A big part of the problem is that both languages share one compiler, and people come from C thinking that C++ is just an upgrade with some features bolted on. It's not. It's a completely different language, and if you approach it as "I'll learn a bit of C and then throw in some C++ features" you're setting yourself up for a world of hurt. The hurt goes away if you forget C, start with a clean slate and learn C++ as a new language.
- qaq 7y agoThere is obviously a learning curve but it's hard to argue that: #[get("/hello/<name>/<age>")] fn hello(name: String, age: u8) -> String { format!("Hello, {} year old named {}!", age, name) } is more complex than express + Node. With added bonus that you get validation for free
- tinco 7y agoI'm a firm believer in that Rust is the greatest imperative programming language ever designed. But your example is a pathologically simple problem with a horrendously complex solution in Rust. In responding to a simple get request you have to lean on both function annotations and a macro. That code would be so much nicer in Ruby.
- qaq 7y agoWould you post an equivalent code in Ruby ? (that like above does validation of inputs)
- johnlinvc 7y agoNot exactly the same, since there's no UInt8 in Ruby. require 'sinatra' get %r{/hello/([^/]+)/(\d+)} do |name, age| "Hello, #{age} year old named #{name}!" end
- tinco 7y agoIf you need input validation like that, which you normally wouldn't in Ruby because your models should do it for you, I'd probably use grape or something similar: require 'grape' params do requires :age, type: Integer requires :name, type: String end get "/hello/:name/:age" do "Hello, #{params[:age]} year old named #{params[:name]}!" end In any case, my beef is more with the macro than with the function annotation, which is rather spiffy. The macro hides the fact that string manipulation in Rust definitely requires a little bit of manual reading. And I feel that as soon as your app becomes more complex Rust will just start getting more in the way. And to an experienced Rust dev that might not be a big deal, because an experienced dev knows how to work with strings or which memory management strategy so it won't bog them down. But if you're just working on something and you quickly want to whip out a service that tells people what age they are, I'd definitely go for a quick Ruby or Go service.
- nwallin 7y ago> but for most user-facing applications that tend to have complex object lifetimes, I just can't see why you'd want to deal with RIAA when modern GC's are so darn good. My day job is ~half c++ and ~half c#, and I couldn't possibly disagree more. The first problem is IDisposable and event handlers. Because c# doesn't have anything like weak pointers, event handlers require that you manually dispose of half your objects. In c, there's a simple rule: you always dispose of your objects. In c++, there's a simple rule: the destructor of your data structure/smart pointer always disposes of your objects. In c#, the rule isn't simple. Half the time, you have nontrivial destructor doing nontrivial things, the other half the time you can leave it up to the GC. But it isn't necessarily immediately clear which is which. The second is `using`. Again, you must necessarily mix the semantics of non-deterministic GC cleanup and deterministic RAII cleanup. Which is worse than having a simple rule that always works.
- Const-me 7y ago> c# doesn't have anything like weak pointers https://docs.microsoft.com/en-us/dotnet/api/system.weakreference https://docs.microsoft.com/en-us/dotnet/api/system.weakrefer... https://docs.microsoft.com/en-us/dotnet/api/system.weakreference-1 https://docs.microsoft.com/en-us/dotnet/api/system.weakrefer... https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2 https://docs.microsoft.com/en-us/dotnet/api/system.runtime.c... > event handlers require that you manually dispose of half your objects. You probably have software design issue on your day job. C# events can be great, but they're not a silver bullet. For loosely coupled application wide events, event aggregator pattern works better, see IEventAggregator from Caliburn.Micro for an example. If the two sides of the event handlers need strong coupling for a good reason, an interface or abstract class for the consumer works better, see ExpressionVisitor from System.Linq.Expressions for an example.
- pjmlp 7y agoYou forgot to add safe handles as well. https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netframework-4.8 https://docs.microsoft.com/en-us/dotnet/api/system.runtime.i... This and the the thread of the other day regarding having to use C for what C# is capable of, apparently many don't look on their toolboxes.