Is Rust Web Yet?(arewewebyet.org) |
Is Rust Web Yet?(arewewebyet.org) |
I think what it comes down to is that I'm just not that into bondage and discipline from a compiler. Yes, I know, it's trying to make my code 'safe', and I'm horribly cavalier and I should feel bad, but:
1. the borrow checker rejects valid programs, has a lot of corner cases it can't catch, and is in active development
2. people routinely write more inefficient code to satisfy it
3. people routinely freak out about 'unsafe', which is a bit much given the first point
Anyway, YMMV. Maybe you're smarter than me, or rust fits your mindset better, or you enjoy asking for help on discord all day, but I am so glad not be using it anymore.
I find that as a C++ programmer, Rust encodes in the compiler a lot of best practices about ownership and memory management. Using Rust is a breath of fresh air in not having to worry about dangling references.
From experience programming C++, I can see what the error messages are trying to prevent and why it is important.
However, if your experience was primarily with managed/garbage collected languages, a lot of the Rust compiler pedantry is stuff that you never had to worry about to being with and you have never experienced the pain it is trying to prevent.
You covered the downsides pretty well, big upsides for C++:
- ability to use C libraries directly - and thus original C API docs. I've got battlescars from NPMs deep dependency trees, and cargo is a similar story.
- I don't need the (very patient and knowledgeable!) people on rust discord to hold my hand every day. There's a stackoverflow for almost every C++ issue.
- that 5% edge case where the codes safe but the borrow checker isn't happy I can just write. No RefCell or nightly compiler.
It sounds like you're making a common misconception here. unsafe code and the borrow checker are not closely related, and unsafe blocks are not a way to play fast and loose with ownership issues. See https://steveklabnik.com/writing/you-can-t-turn-off-the-borr...
If you don't want to deal with the borrow checker, the solution isn't unsafe, it's Arc, Clone, RefCell, etc.
This is a red flag for your complains: Is VERY likely you believe Rust is wrong, when the fact the problem is that your code is not good.
I know this, my first 3 months starting Rust were thinking between "I'm a failure as developer" and "Rust is wrong" or "What? Why can't do this?". For first time after learning more than 12 languages I was truly in shock. And even, for second time in 20 years, picking a book and PAYING attention to it.
THE major problem with Rust is not, not even close, the borrow checker or that is picky. Is that Rust idioms are not OO idioms, not C/C++ idioms, not PHP idioms, no Java idioms.
Is fairly a simple language, actually, and the productivity is very high (today I code in Rust faster than python, that is still my benchmark on productivity).
What is NOT simple, is that it require several things to "click" and align properly to make the journey smooth.
And that it reveals how much other langs hide for your.
P.D: The problem you say, sometimes are true, but only at first, when the people are not fluent on the lang, or later, when doing seriously advanced stuff.
Not think I bashing you. This experience is common for many in the community, and even very strong developer get the weird experience with Rust. But also is true that when Rust "click" is very, very good!
P.D.2: I bet Rust is much harder the more experience a developer is and the more ingrained some ways are. I teach Rust to some newbies, and the experience for them is far smother.
I'm gonna be blunt: This is the worst thing to come out of the Rust community, bar none. Rust is a fine language and I love to write in it, but I loathe the way Rust developers have convinced themselves that Rust is an axiomatically 'better' language and that the things you can't do in Rust, or the things that are painful to do in Rust, are a perfect circle venn-diagram overlap with the things that are just bad to do in general. It's a mindset that shuts down discussion and constantly shifts goalposts. It doesn't help anyone.
Who knows, maybe rust clicking for me was just around the corner. I kept thinking "finally I'm understand this" and then something else would happen.
I'll leave it to the incredibly patient programmers who can spend 3 months just learning it. I'll use all the time I save to write more tests, and probably end up with something much more correct.
The instances of safe code that the borrow checker can't verify as such are not "corner cases" by and large, they're genuinely non-trivial patterns, often with non-obvious drawbacks such as lack of composability/modularity. Rust devs and researchers are working on better abstractions to support those cases, but these are very much the exception, not the rule.
> people routinely write more inefficient code to satisfy it
People should stop freaking out about this. The "more inefficient code" you might get by adding a few .clone() or Rc<RefCell<…>> when the borrow checker complains about something is still way more efficient than anything written in alternative "safe" languages.
The "slow" solutions are a bit noisy but that's a good thing, since it tells you where it might be worthwhile to either refactor for efficiency or document why a refactor isn't feasible.
Unfortunately, the borrow checker can't handle a basic observer without falling back to patterns that violate encapsulation. The observer pattern is one of the best patterns for composability/modularity, and I find that the borrow-checker-compliant solutions are more complex and don't solve anything but rather move problems somewhere else.
It's cases like these that make me appreciate Rust's wisdom of adding Rc<RefCell<T>>.
But you don't have to use a "safe language". C++ can avoid a lot of copies and be just as safe from an absolute point of view. The borrow checker isn't god and Rust isn't perfect. In an absolute sense the C++ code you can write could be more correct and efficient(it just doesn't tend to be).
That's Godel's incompleteness theorem for you. Every static type checker also rejects valid programs, but that doesn't make them any less useful. Just one of those inconvenient facts about our universe.
Yup, this is the tradeoff you have to make to catch the wide variety of bugs. For personal use, probably not worthwhile, but it definitely pays off for the safety it provides in production contexts.
The way I view Rust's philosophy is "it's better to catch bugs at the compile stage than at the execution stage".
In theory yes. In practice, getting to the execution stage was such a slog that it rarely happened.
Would have liked it a lot better if the borrow checker had the option to be -Wall instead of -Werror.
Type checkers provide tools that make it comparatively easier to ignore when they could be wrong or are getting in the way. To do something in a type-safe manner often doesn’t require re-abstracting behavior.
In particular I want to shout out for Axum (https://github.com/tokio-rs/axum), from the folks who brought us Tokio. I've been building with it for the past few weeks and have enjoyed every minute.
I started with Warp, but ended up struggling a bit with middleware. I tried Axum as a web framework wrapper for tower (https://crates.io/crates/tower), and never ended up bothering to reintegrate back into Warp.
What I've gained as a result:
- execution speed (about 3x faster, single-threaded)
- better-documented data structures
Things I've lost:
- ease of iteration
- concise, readable code
- really smart type inference
- a bunch of time thinking about the borrow checker
Quick iteration and concise readable code are much more important in web-land than in system programming land, and those are key reasons why I don't think many will be abandoning interpreted langauges for Rust.
I sometimes wonder whether people adopt Rust/Haskell/ReasonML for front-end work because they want it to feel like more of an effort than it otherwise would.
Going by these benchmarks (click around to find your own use case) Rust is definitely fast, but not (much) faster than many other languages, including Javascript. https://www.techempower.com/benchmarks/#section=data-r20&hw=...
When it comes to JSON serializers, there is a Java framework that is faster than Rust, which is interesting to say the least. When you start comparing actual fully-features frameworks, many Rust libraries even lose their advantage!
There are definite benefits to Rust web frameworks (despite the minimal speed diff, Rocket or similar can have less than half the RAM requirements that other languages run into!) but just because Rust compiles to machine code doesn't mean it'll revolutionize your web application.
> These provide everything you’d expect from a web framework, from routing and middleware, to templating, and JSON/form handling.
One problem I've run into is that I wanted to give Rust a try for a basic CRUD application but the features just weren't built in or available in packages. Some frameworks were missing CSRF, others were missing multipart/form uploads, and so on. Online discussions often end up concluding that "it's easy to write the middleware yourself, see this hacky POC", but this type of code is easy to mess up and easy to break with API upgrades.
Tide and Warp seem to have matured quite well, so I guess I'll have to give them a go at some point, but I'm a little sceptical. The status of this issue (https://github.com/http-rs/tide/issues/852) is a little disheartening...
Why is Rocket considered production ready when it's only just at version 0.5? Similar <1.0 stories can be found on crates for sqlx, rusqlite, and postgres. Am I wrong in assuming the API must be quite stable before it can receive the 'production ready' label?
There's no server process — it's all built in GitHub Actions, hosted in GitHub pages, and runs in the browser. The whole WASM code is 164 lines (o/w half are comments).
[1]: https://github.com/prql/prql [2]: https://lang.prql.builders/editor.html
Many negative rust comments over here. It sure did take me a few months to get comfortable with the language and its idioms, but man do I not want to go back to languages without a borrow checker now. The compiler and clippy is just so good at catching bugs. Give it a few years to mature the async/await (it is a mess currently no gonna lie) and it could displace Golang especially for cases where you care about tail latency.
P.S. It's very hard to work without wasm-bindgen, since you have to wrap browser API manually otherwise.
They're surely not talking about compilation times. Admittedly it's been a few years since I tried to build a web stack in Rust, but I felt like I was back in the 1990s dealing with the long compile times on modern hardware. Diesel was such a nightmare to use. It was poorly documented, and took a long time to compile even trivial example projects.
I agree that there's a lot more work to do before Rust development is pleasant on average hardware. Does anyone know if Cranelift is still going anywhere?
Correct.
Does anybody have more insight into its development status?
It’s still a bit rough around the edges but the Rust benefits more than makes up for it.
And the second realization is that the idea of polyglot programming has utterly failed. A lot is due to what kinds of APIs can be exposed between components, and that seems like an inherent problem of communication between different languages.
But there are other areas where you'd think we'd have wider agreement by now: the semantics of data types, runtimes, ABIs, memory layouts, etc.
I guess there are lots of reasons for differences. But it's kinda sad how much effort is spent re-writing stuff that already exists and works in a different language.
Question- Curious to know what backends / languages would be the fastest for a REST-based PostgreSQL backed API?
Because WASM doesn't have a direct method of calling system API functions, you have quite a lot of control over the runtime. Most JS engines are too powerful to just run arbitrary code (especially if they're not run inside a browser) and other tools (LUA etc.) have libraries that usually assume that the program is not executing code from third parties. With many if not most WASM libraries, there is no unmetered networking, there is no I/O, only methods you explicitly write call wrappers for.
For tools like Cloudflare Workers, WASM can be used as a format that executes relatively quickly, relatively safely. Most software won't be in a position where you'd want to push third party blobs of code and execute it in the backend, but for some programs (SaaS + custom report generation?) it can be a nice plugin platform.
There are, of course, alternatives, but since LLVM and GraalVM compile to WASM, there are tons of languages that can generate a compatible blob.
There is something to be said for code reuse, but the speed of the WASM <-> JS bridge to interact with the DOM makes that use case quite difficult to accomplish efficiently.
[1]: https://github.com/integer32llc/rust-playground/pull/777
Having come from python (day job) I did hit a screeching halt when it came time to meaningfully interact with a database.
It is unfair to compare Rusts current offerings to something as mature as SQLAlchecmy but boy does it slow things down dev wise to be mapping my own types and queries using tokio-postgres.
I've looked at Diesel, sqlx and SeaORM but have not yet committed to learning one yet.
I've also used Warp for some small web server stuff in the past as well. It is an interesting approach but definitely a little different.
Similar to typescript, where years ago I thought “but I just want to write code!”, now I can’t imagine going back. At least not for meaningful projects where I need to care about consistency and stability for more than a few months/for something critical.
The initial slowdown affords you a lot in the longer term.
I’m somewhat wide-eyed at how much simpler and more readable query building is in Django. I have been spoiled.
SQLAlchemy is closer to SQL than I generally want to be for pedestrian web programming. It also lacks conveniences I’ve taken for granted writing Django backend.
Even for writing data migrations in scripting, having ORM queries be incredibly simple to read and modify is extremely valuable, it makes code reviews accessible to more people.
I’m not a rust developer, though I admire what it can do. That said, having looked at the starter queries on each, it would take a lot to make me contemplate use of any of the rust-based ORMs you’ve listed.
As a sibling comment points out, typing and async are valuable and Django has no typing and is still working on delivering async support in its ORM.
That said, for web products reducing time to flipping feature flags seems to be the main goal.
In that way Python / Django and I suppose even SQLAlchemy will probably retain users against Rust.
Also, I'm very curious: how does the KLOC count compare for the PHP and Rust versions?
While I don't think you can beat straight php/js/python for this, there's still a lot of room for improvement over the rust/c++ magnitude of compile times.
For example Go/OCaml/Common Lisp (at least, SBCL is a compiler, there are lisp interpreters), all have reasonably quick compile times. And the latter two have repls, which really does help improve the iteration cycle.
I haven't had to play with crystal, where does it fall on this spectrum?
I don't have exact numbers since it's not a straight port — the original PHP code was written to analyse a slightly different language than the Rust version I'm building.
I'd estimate that Rust requires you to be about 10% more verbose than PHP. Main annoyances vs PHP: no default argument values, and only a single let allowed inside an if conditional.
People just run `composer install --dev vimeo/psalm` and it works. It can also run on any web server that runs PHP, so I have it running on psalm.dev
OfC the Rust equivalent is very easy to package, and also runs reliably in the browser via WASM (currently ~1.5MB compressed).
That's ridiculous. There's a lot of garbage to unpack in that sentence, but for example Rust's borrow checker provides valuable guarantees about your code and eliminates entire classes of bugs. It's not just wasted time. Haskell's purity and lazy semantics allows for equational reasoning and more composable abstractions. ReasonML makes it really hard to accidentally write a bug that crashes the program. Etc.
Just because you don't see why those things are valuable doesn't mean they aren't.
> - concise, readable code
Rust code is significantly more readable. Use the type system to your advantage.
> - - really smart type inference
Rust has really smart type inference too and only rarely ask for an explicit type. I've found that I prefer annotating my types. It adds to documentation and readability.
> - a bunch of time thinking about the borrow checker
You can use Arc/Mutex to overcome some of these and review them in a refactoring.
> - ease of iteration
At the cost of introducing a bug/technical debt.
In PHP, modern typecheckers can verify that the first element always exists on an array after an emptiness check:
if ($some_arr) {
echo reset($arr);
}
Whereas in Rust you have to explicitly unwrap: if !some_vec.empty() {
print!("{}", some_vec.first().unwrap());
// .. more code
}
The Rust version requires you to use your intuition to figure out that `unwrap()` will never panic here.In my Rust port I consistently rely on the PHP typechecker's knowledge of the equivalent code when using `unwrap()`, because it knows which array fetches are safe.
> At the cost of introducing a bug/technical debt.
At the cost of shipping a product!
-------
Edit: user ibraheemdev proposes this Rust equivalent which more closely matches the idealised pseudocode, and type-checks:
if let [first, ..] = &some_vec {
print!("{}", first);
// .. more code
}
It's preferable IMO to if let Some(first) = some_vec.first() {
because the latter relies on a property of a non-empty vec, and checks that property, rather than checking the non-emptiness of the collection.You should put down the Rust kool-aid. Rust is incredibly hard to read due to its sigil and abbreviation heaviness.
Are you calling php's chaotic mess of type juggling "really smart type inference"?
> - ease of iteration
> - concise, readable code
Ouch... then it's a big nope for me.
Apparently async db requests and batching transactions are the key to winning on that benchmark: https://news.ycombinator.com/item?id=24315512
I wish more benchmarks would produce latency vs requests/second curves in microseconds. I bet the latency is massive due to batching.
You read see the source of the tests here: https://github.com/TechEmpower/FrameworkBenchmarks/tree/mast...
The SQL code seems quite optimized (manually compiling database packets instead of using a library). Most code seems quite static and very small, so it's probably very quick. I don't think you can actually use the framework like that in practice, though.
Additionally a lot of these benchmarks focus on things that the JS engines are very good at. It isnt like they are running CPU intensive tasks in JS.
And then someone shows up and hands you a nail gun.
Rust makes me happy because we speak the same language. Stuff gets done and I go home at 4:30 and play with my kids instead of my compiler.
If you can get the hang of it, it’s a safer hammer. You’re still going to be manually managing your memory allocations though. The nailgun people have garbage collection (and yes for the gc folks, I’m aware you can still write allocation free code, or at least take manual control of allocations in a garbage collected language and therefore opt out of garbage collection overhead - but why would you unless there was a performance issue)
C's age is not an issue in itself. The programming languages it replaced were ahead of C in many ways. It was a setback from a language design point of view, even 50 years ago.
People aren’t searching for Rust much:
https://trends.google.com/trends/explore?q=%2Fm%2F0dsbpg6,%2...
Because it’s not a popular language, cobol and prolog are more popular: https://www.tiobe.com/tiobe-index/
And yet hardly a day goes by without a rust story on hn and for the past 5 years it’s scored most loved language on the annual stack overflow developer survey.
That said, Rust has an exit from cult status and a starting path toward mainstream in its sights. If Rust makes it into the kernel then that is the beginning of Rust.
I like Rust, I write a lot of it, but I can't help but feel that Rust isn't "it". I think another language will pave the path Rust trail-blazed, at some point.
Seems like your argument is Python catches some bugs when converting to bytecode, so it cares about catching bugs early. That's not true -- for the most part, Python catches only the most trivial of typos before execution.
After all, you are human, and we humans aren't good at exhaustive covering of all bases. Sometimes when I am reading a rust compiler error message about erroneous borrowing I really wonder that I never could have thought about that corner case.
It's true. Sometimes Rust compiler's pedantry is just not neccessary. Then write Python, TypeScript, Ruby or in Rust box, arc and clone everything.
I understand, I was close to drop it.
In retrospect, I create a lot of self-inflicting problems in my journey (like I learn Rust making a programming language and hit by coincidence some of the hard stuff with Rust!) and knowing what I know now, Is clear the time running in circles was in big part that.
But, of course, is hard to see you are running in circles when you are running in circles :(
I'm not converting, I'm just porting a good chunk of it for a slightly different purpose.
Not sure what's a red flag -- the original PHP utility has 17 million downloads and people are pretty happy with it.
The source of my amusement was -- I really, really don't see the world the same way as you do.
I won't take your negatives point by point, but, for instance, familiarity and readability do really seem to be in the eye of the beholder, because, to my eyes, to call PHP concise and readable, especially as compared to Rust, is a spit take. PHP is emphatically not readable to me. Writing a 100KLOC project in PHP? Ugh. Yeah, you do you, but not this guy.
Pretty much every set of benchmarks out there is ruined by monstrous unrealistic code that squeezes out 5% more performance than actually well written code.
As a side note, one flaw of TechEmpower benchmarks is that to my knowledge they use the original "wrk" tool, which only supports HTTP 1.0 and is sensitive to "coordinated omission" [0]. This means it ends up being biased in favor of web frameworks that implement specific optimizations or have specific behaviors that aren't actually useful in a production context.
Or is it some Goldilocks not-unoptimised not-too-optimised I'll-know-it-when-I-see-it wishful-thinking thing?
It's not heavily IO-bound — it's mostly memory-bound (it's a type-checking tool for very large codebases).
Further (painful) optimisations will likely involve the use of arenas to prevent so many atomic de-allocations.
I don't manually manage my memory anymore in Rust than I do in garbage collected languages (say Python or Go). (I do have to think about object lifetimes and whats pointing where in all three mentioned languages).
As an aside, I really like not having to manually free locks, close files, release connections back to pools, etc. It's one resource management paradigm that applies to everything - not just memory.
This is the (in my opinion) insurmountable difference between low and high-level languages. Even though rust is (arguably) probably the best/most readable low-level language that as you note can sometime even beat managed languages (locking/file close), it will loose to major refactor-speed.
I'm writing a 10,000 LoC library and I call drop() manually only 3 times, in exactly one place, and not for memory reasons. I'm not sure what you mean. If you mean thinking about lifetimes, sure. If you mean thinking about drop(), almost never.
Coming from c++, Rust was pretty familiar. PHP isn't that hard to read either.
Maybe all this is necessary for a system level programming language, fine, but don't tell me this is easy to read.
Most Rust programmers just never, ever have to deal with pointers like this. And most code in the wild looks nothing like this. Yes, it's there if you need it, but in practice you will never read anything like it.
Readability is the most suspect of all the anti-Rust arguments to me, because, as others have noted, it's almost always about familiarity. The most senior parent comment is someone explaining how their 100KLOC PHP command line program(!) was more concise and readable than Rust! PHP as the exemplar of readability. Think about that.
Look -- if I really loved PHP and was forced to write Rust, I might really hate it. But I think the world of people who really love PHP is pretty small compared to the world of people who have lived with PHP because that was what was familiar. Folks let's climb off the bus to crazy town.
This is something Rust is relatively good at, you just may need some unsafe blocks, but assuming you can compile using clang for the C code everything tends to work well. I am saying this as a Rust skeptic.
> Would have liked it a lot better if the borrow checker had the option to be -Wall instead of -Werror.
Wouldn’t this defeat the purpose of the borrow checker and remove the guarantees the language gives you?
The software is a layer over an in-process key value store written in C (LMDB).
That model favours easy-to-google frameworks with wide ecosystems.
That is something I would find hard to believe, if you mean iteration of changes. I have coordinated a few rust rewrites, and at least seeing engineers live programming, it takes far far longer to change and compile Rust code than python.
Could you talk more about your company's process or how you mean?
As an example, type errors in Rust are radically better than mypy, it's no competition. In general rust's type system is just way better, we have to use Any all over the place because mypy can't even handle a Json type (no recursive types at all).
There's nothing that Python really does better in terms of iteration that I can think of. Obviously you don't have to compile code, but `cargo check` is seconds, that is not the bottleneck. We use hypothesis in Python and quickcheck in Rust, cargo is way better than pip, working with loosely typed data is about the same in Rust, maybe a bit better, and working with strictly typed data is wayyyy better.
The tooling for working with crates, having an actual lockfile, higher quality libraries, etc. It just all makes Rust more productive.
We've run into maybe one rust footgun, which is that binding to _ drops the value immediately. We've run into so many Python footguns, like, did you know that in Python if you want to do circular imports you need to put your imports at the bottom of the file? Or use absolute imports everywhere? Neither of which seem to work 100% of the time by the way, something that makes writing graph data structures quite cumbersome. The other day we ran into a stray comma turning a value into a tuple. The papercuts and footguns across the tooling and language just add up really fast and basically don't exist in Rust.
I don't know how people get stuck on the borrow checker, frankly. It's one thing if you're very new to the language, but within weeks it should be very simple to avoid those errors. I maybe hit a "fuck, what" borrow checker issue once a year, in which case I hit up the Discord, they fix it, and I file an issue with rustc so that the error message will get improved.
This is based on about 7 years of Rust and Python experience, with 6 years of professional experience in Python and 3 in Rust.
I've felt this a little bit, but can only theorize why; the borrow checker makes mutability into a viral leaky abstraction, such that a change over here can sometimes cause widespread refactors on other components that would be decoupled in other languages.
Jury's still out on whether that's healthy long-term for a codebase, especially once the original writers have left. Jury's also still out on whether it encourages us into better architectures to begin with. Maybe it evens out, maybe not!
C takes a different approach to how it handles problems that was described well in "The Rise of Worse is Better":
"Two famous people, one from MIT and another from Berkeley (but working on Unix) once met to discuss operating system issues. The person from MIT was knowledgeable about ITS (the MIT AI Lab operating system) and had been reading the Unix sources. He was interested in how Unix solved the PC loser-ing problem. The PC loser-ing problem occurs when a user program invokes a system routine to perform a lengthy operation that might have significant state, such as IO buffers. If an interrupt occurs during the operation, the state of the user program must be saved. Because the invocation of the system routine is usually a single instruction, the PC of the user program does not adequately capture the state of the process. The system routine must either back out or press forward. The right thing is to back out and restore the user program PC to the instruction that invoked the system routine so that resumption of the user program after the interrupt, for example, re-enters the system routine. It is called PC loser-ing because the PC is being coerced into loser mode, where loser is the affectionate name for user at MIT.
The MIT guy did not see any code that handled this case and asked the New Jersey guy how the problem was handled. The New Jersey guy said that the Unix folks were aware of the problem, but the solution was for the system routine to always finish, but sometimes an error code would be returned that signaled that the system routine had failed to complete its action. A correct user program, then, had to check the error code to determine whether to simply try the system routine again. The MIT guy did not like this solution because it was not the right thing.
The New Jersey guy said that the Unix solution was right because the design philosophy of Unix was simplicity and that the right thing was too complex. Besides, programmers could easily insert this extra test and loop. The MIT guy pointed out that the implementation was simple but the interface to the functionality was complex. The New Jersey guy said that the right tradeoff has been selected in Unix -- namely, implementation simplicity was more important than interface simplicity.
The MIT guy then muttered that sometimes it takes a tough man to make a tender chicken, but the New Jersey guy didn’t understand (I’m not sure I do either).
Now I want to argue that worse-is-better is better. C is a programming language designed for writing Unix, and it was designed using the New Jersey approach. C is therefore a language for which it is easy to write a decent compiler, and it requires the programmer to write text that is easy for the compiler to interpret. Some have called C a fancy assembly language. Both early Unix and C compilers had simple structures, are easy to port, require few machine resources to run, and provide about 50%-80% of what you want from an operating system and programming language.
Half the computers that exist at any point are worse than median (smaller or slower). Unix and C work fine on them. The worse-is-better philosophy means that implementation simplicity has highest priority, which means Unix and C are easy to port on such machines. Therefore, one expects that if the 50% functionality Unix and C support is satisfactory, they will start to appear everywhere. And they have, haven’t they?
Unix and C are the ultimate computer viruses."
Has this changed or is the "defined" part still the compiler source code? In that case taking the source code of any C compiler as the _blessed_ one should get rid of any undefined behaviour problems as well.
Indeed the notion of what behaviour is considered undefined changes with compiler versions, and it is not fixed yet. E.g. mem::unused() for example is now basically always undefined and you are supposed to use MaybeUninit. But you get a warning if you try to use the old API.
This is for unsafe Rust however. With safe Rust, even though there is no spec, the guarantee is that, unless you hit one of the soundness holes in the language, or a piece of user code that uses unsafe internally, you are safe.
Here's your problem. No, that is not an accurate summary of the discussion. And the whole point of the dialogue between the kernel maintainers and the Rust developers to figure out what needs to be done to make Rust suitable for inclusion in the kernel - which has already resulted to changes in the Rust toolchain and standard library. So
> Rust will never make it into the kernel as-is
Is about the most negative possible way to frame it while being technically true. Nobody is suggesting that Rust be included in the kernel "as-is", they're suggesting that Rust be included in the kernel, and having a dialogue about what would need to be done on both sides to make that possible.
Potentially the issues we ran into were due to the inexperience of the team, Rust despite being ~12 years old, most of the programmers we were working with had less than 2 years of experience with it. So if you have a more experienced team, your mileage may vary.
Given that, I think it has to do with the typing system, it is a lot faster to change your structs in python and propagate the changes as needed than in Rust. Asking for another field to be displayed on a web dashboard could take ~1 hour for a team we had working in Django, and ~2 days for a team working in Rust. Of course the projects in question were wildly different and a lot of other caveats, but still in general we found that Python was just much much faster to make changes with. I was not directly involved in any of the programming, but did review the changes, so my perspective may not be the correct one.
We, like the commenter have made the decision to start slowly depreciating our Go code base in favor of Rust.
You should not use `unwrap` in a production product. It's there for prototyping and I think it's a mistake they have it (though the language already requires a good upfront time investment as it is). Use `?` and have your error propagate accordingly to the top of the chain. Have your own error types and convert from other error types.
if !some_vec.empty() {
print!("{}", some_vec.first().unwrap());
// .. more code
}
I don't know why you would check the first element of a vector. Use Rust type system to your advantage, and don't "convert" PHP code into Rust. Re-design your program. Also you don't need to check that the Vector is empty if you are using "first". "first" returns an Option with None if your vector is empty. My guess is that you have yet to exhaust the idioms Rust offers and approaching it in a PHP-like manner.> > At the cost of introducing a bug/technical debt.
> At the cost of shipping a product!
Okay!
I can imagine a language where panics don't crash the entire application, but instead blast away the surrounding "region" of memory, leaving the rest of the program intact and able to keep running. Similar to catch_unwind, but if the language is aware of region boundaries, and only allows certain methods of communication between them, it would leave the rest of the memory in much more predictable possible states.
It may sound surprising, but it's actually possible with the right language constructs (Erlang folks know what I'm talking about!) and that way, we could once again have panics for unexpected errors, and Results for expected errors.
Trust me, I am!
For example, I'm rewriting all the (very-efficient) PHP regex code to a much more convoluted version because Regex::new is so costly.
Less sarcastically, I am embracing the Rust Way where necessary. My complaint is that the Rust Way sometimes forces me to depart from the idealised pseudocode version of a given algorithm much more drastically than PHP does.
Are you using lazy_static? See: https://docs.rs/regex/latest/regex/#example-avoid-compiling-...
if let Some(element) = some_vec.first() {
println!("{}", element);
// .. more code
}
and avoid the unwrap and the empty check?Edit: Added a `let` I had forgotten.
Every time you have a Boolean if condition with an unwrap, it means you are not taking advantage of the type system.
You've left behind an explicit "is this collection non-empty" and you're instead relying on a property of a non-empty collection.
The PHP version can also be written as
if (($element = reset($some_arr)) !== null) {
echo $element;
}
But that code is similarly divorced from the imaginary pseudocode equivalent> You've left behind an explicit "is this collection non-empty" and you're instead relying on a property of a non-empty collection.
More abstract for who? I think virtually all Rust programmers would easily understand the `if let` snippet, virtually all PHP programmers would understand the PHP snippet, and virtually all programmers of any language would understand that a non-empty array has a first element. I'm not at all convinced that most programmers would correctly guess that a function called `reset` is used to access the first element in an array though.
if let [first, ..] = &some_vec {
print!("{}", first);
// .. more code
}