15 ms·
I tried to pick up Rust a few years ago, but there were too many sharp edges. I thought it was a nice language, but was too early for actual use. I played with
by thejosh 4y ago
I tried to pick up Rust a few years ago, but there were too many sharp edges. I thought it was a nice language, but was too early for actual use. I played with some libraries (Apache Arrow, etc) and it was nice.
About 2 months ago I wanted to use Arrow within Elixir, which required me to start using Rust again (Elixir uses Rustler to safely convert from Rust <> Elixir without theoretically crashing the beam). I am amazed how far it's come, and I've actually been using it a lot over the last few months and haven't ran into any major issues. There is a fair amount of information out there, and the documentation as the OP pointed out is really fantastic.
The libraries are really good now, and I've had no issues using it on Linux or on my Macbook M1. Incredibly impressive speed results. SIMD is a game changer.
Major shoutouts to arrow2 and Polars, I love using it for data analysis :).
- atoav 4y agoI mean it depends. Many of aspects of Rust that are perceived as sharp edges are in fact the programmer bringing in their preferences and paradigms from other languages and trying to program that way in Rust. I was one of those and tried to do OOP in Rust. It was a pain. At some point I gave up and was like: "Okay Rust, I do it your way, I just want this to work". And it worked flawlessly and easy. I literally had to overcome my ideas of beauty in code to realize how Rust is meant to be programmed in (more data oriented, less object oriented). This was a really good lesson for me, as I had to question similar aesthetically motivated decisions I made in other languages in the past.
- zozbot234 4y agoRust actually supports most OOP features, with the main exception of implementation inheritance. And implementation inheritance is a nasty footgun in large-scale software systems (search around for: "fragile base class problem"), in a way that just doesn't apply to simple composition and pure interfaces (traits). So it's hard to fault Rust for including the latter and not the former.
- hyperman1 4y agoFor me it was the web-of-pointers strategy I had to unlearn. A child object keeping a pointer to its parent is misery in Rust. It forces you to either make the child completely independent or really prove the parent will be around until the child disappears. 90% of the time this is dumb overhead, but 10% of the time it found a bug in some edge case, so I learned to appreciate it as a tough teacher, and my designs got better for it.
- deleted 4y ago[deleted]
- FpUser 4y ago>"90% of the time this is dumb overhead, but 10% of the time it found a bug in some edge case, so I learned to appreciate it as a tough teacher, and my designs got better for it." Sounds kind of like Stockholm syndrome
- atoav 4y agoAnd you sound like you are part of the reason why we still have exploitable null-pointer bugs in 2022. Imagine a structural engineer that would say "all that static and dynamic analysis is dumb overhead 90% of the time, so I am going to skip it". Imagine an electrical engineer who would go like "all these wire gauge calculations are exhausting, 90% of the time my installations don't catch fire" Seriously, I sometimes wonder what is wrong with the whole field of software development.
- FpUser 4y agoNothing is wrong. Same shit as in any other area. It is a usual trade-off between what you pay and what you get in return, some of it highly politicized.
- philosopher1234 4y ago> designs got better for it. What is better about them?
- hurril 4y agoThis sounds to me like the journey into functional programming. I've experienced the same thing myself.
- AndrewDucker 4y agoI've encountered this pretty-much every time that I've learned a new language or framework. I start out trying to use it the way I've used things before, and then I slowly learn how the people who wrote it expect me to work, and then things get a lot easier.
- hurril 4y agoThat too and I don't think I'm even done with that, myself :) What I meant is the step away from the notion that things are objects, stuff gets done with methods, methods are available via mixins/ inheritance/ magic, etc. I've seen the notion of using values and pure functions as data oriented programming recently but never understood what that moniker adds.
- AndrewDucker 4y agoI think that going with pure functions/functional programming simplifies things, because it makes it much easier to test that things work as you'd expect when you don't have side-effects/state to think about.
- dotancohen 4y agoAs someone who even structures their Python in OOP, I'd appreciate elaboration on how you organize your Rust code. I've been glancing at Rust for far too long, never finding a weekend to dive in. Save me some headaches, how should I approach e.g. Customer - Product - Order relations without OOP? What is the canonical "Rust Way"?
- nicoburns 4y agoYour customer, product and order are still going to be objects, but they won’t reference each other directly with references/pointers. Instead they’ll either store an id, or you’ll have a central registry of relationships using some kind of id (could be a key into a hashmap or an index into a vector) and then fetch data from the central store (or have the caller pass it in) at the last minute when running code that does something.
- dralley 4y agoThe nice thing about doing it this way is that it makes it much easier to serialize and/or save to a database.
- gary17the 4y ago> they won’t reference each other directly with references/pointers I'm not sure if I understood your reply correctly, but there seems to be nothing in Rust stopping one dynamic trait (interface-based) object directly referencing another dynamic trait (interface-based) object. The main difference between C++ O-O and Rust trait-oriented programming is C++ inheritance of implementation vs. Rust inheritance of interfaces. You can also downcast in Rust, if you try hard enough. https://gist.github.com/rust-play/fbe471b12a0fabe4ab7b653835251073 https://gist.github.com/rust-play/fbe471b12a0fabe4ab7b653835...
- nicoburns 4y agoYou can do references in Rust. But you can only have one mutable reference to an object at once unless you work around this with locks (Mutex, RefCell, etc). So for anything other than trivial child object references, you can quickly paint yourself into a corner of compilation errors by using webs of references. And this seems to be the basis of a lot of people's frustrations with Rust. It's true that you also can't do inheritance. But I've found this tends to be less of a problem as most OOP languages encourage composition over inheritance anyway, and composition works the same in Rust as in other languages.
- greenmana 4y agoHaving studied mostly OOP/Java at the uni, and been using mostly C# at work, I realized I might actually start to find programming fun again through Go. I've studied it a bit recently and this idea of interfaces with composition over inheritance etc. made somehow a lot more sense to me, and gave me this boost to try and learn it more because it felt so enjoyable. Not even with some practical problem at hand to solve, but just on an abstract level, not having to deal with OOP classes and inheritance and all the things. Now I just need to find a Go job and get my feet a little more wet. ;P I'm talking about Go because it gives me similar feelings as Rust, but Rust I have a lot less experience with. I hope there's a similar fun and excitement to be found in Rust as well, after unlearning some old habits.
- linuxftw 4y agoGo is fun at first, and then it becomes soul sucking. It's all boiler plate. Many large scale projects have a lack of adequate unit testing, so large code bases are particularly painful to maintain. I attribute this lack of tests due to how the code needs to be structured, you have to needlessly add 'interfaces' throughout your code to accomplish things. Go has it's strengths, but IMO fun isn't one of them. It turns into soul-suck quickly.
- metaltyphoon 4y agoI'm in the same position as OP and was wondering the same thing; finding a job using Go. Is the bloat that you see the most related to error checking? If not what else is it?
- ushakov 4y agofor me it's lack of map/reduce
- linuxftw 4y agoThe bloat is mostly related to mocking and making a fake client for everything for unit tests, and the practices you have to follow to make that actually work. In Python or Java, you can do something like: class: f1(): self.some_api_call() <process api call here> test_class extends class some_api_call(): <mock definition> In go, you cannot do this. Fair enough, but everyone writes object-style code because it's easier and there's less boiler plate. If you do this, you can't write tests. Instead, you have to do something like: class: apiMethod = nil f1(): self.apiMethod() <process api call> And assign apiMethod when you create the instance of the object; there are no constructors because they're not traditional objects, you need to create a factor method (boiler plate) or build the struct by hand (boiler plate). None of this is terribly challenging in and of itself, but if you work on large code bases, nobody did this because it's extra work, and now you have to refactor it because you want to make a change to the critical business logic and prove you're not introducing a regression (a constraint the l33t coders before you didn't have because they get to go fast and break things). And finally, often times the thing you need to mock is in someone else's package, and it doesn't implement an interface, or the thing you need to mutate is private, etc, etc. You end up need to mock half of a package sometimes. None of this is insurmountable, but when you do it day in and day out for years like I did, it's a real slog, and it sucks your soul out of your body. It wasn't uncommon for me to spend literally 20x as long refactoring and implementing tests as it was to ship features. If you look at some unit tests from large go projects, you'll see stuff like struct{struct{struct{struct{...}}},struct{struct{struct{...}}}} because so much stuff needs to be mocked up. And since interfaces are disjointed from classes, you won't know with certainty which methods you need to needlessly mock for your mock class until you try to compile, because the interface is defined somewhere else and not attached to a base class, it's just a definition floating out there in the source somewhere.
- augustk 4y agoHowever, if I'm not mistaken, the language still has no formal specification.
- speed_spread 4y agoA second implementation based on GCC is underway and will help press this very issue.
- munificent 4y agoThis is a somewhat heretical opinion but I don't think having a formal specification is particularly important for programming languages today. It was very valuable, say, twenty years ago, when there were most programs were written or compiled using multiple closed source implementations of languages coming from competing companies. There were real economic incentives for the implementations to diverge from each other in ways that harmed the larger ecosystem. A formal spec was a forcing function to make those implementations compatible. Today, programmers simply won't use a language whose implementation isn't open source with a very permissive license. This makes it very hard for an organization to deliberately make the implementation incompatible with others because other organizations and users are able to either avoid the incompatibility by forking the implementation if they don't like it, or making it compatible by using the implementation if they do. I still think it's very valuable to have a committee with members of all implementations that helps drive consensus for where the language should go. But the document itself I see as secondary to that human process.
- augustk 4y agoThe value of a formal specification is the ability to reason about a program without having to compile and run it (using a specific implementation).
- vistro 4y agoGood luck reasoning about C++ code. After all static analysis, sanitizers and whatever dynamic analysis, you still cannot be really sure that your code will blow up with undefined behavior.
- arwhatever 4y agoIndeed, I’m rereading The Rust Book , after struggling and finding slight success about around 2018, and am surprised at how much better the presentation is, as though they maintainers have closely studied where people got hung up, and then targeted those areas to add clarity. I strongly suspect that it will stick this time.
- sfteus 4y agoI had a very similar experience; thought it was an interesting language but I got discouraged around the time the small stuff I was working on required lifetimes, or had weird reference errors (or at least, what I thought was weird at the time). When I tried again recently I started with the Too Many Linked Lists, which I felt did a better job of explaining both lifetimes and how the compiler views <type>, &<type>, and &ref <type> as completely different types, and that helped a ton. Combine that with spending more time understanding how Rust handles object composition (compared to "traditional" OOP), the massive compiler improvements W/R/T lifetime elision and auto-derefing within the past several years, and realizing just how damn helpful the compiler and documentation is compared to other languages (again, thanks to TMLL for explicitly showing this), and it's been a downright pleasure to use this time around.
- chakkepolja 4y agoThe person who wrote this blog is really good at C++ and compilers (along with many other things), so I think this would be relatively easier for him.