Most active commenters
  • jonathanstrange(8)
  • junon(7)
  • j-krieger(5)
  • tracker1(4)
  • thesuperbigfrog(4)
  • ArtixFox(4)
  • baq(3)
  • GoblinSlayer(3)
  • (3)

←back to thread

364 points Klasiaster | 82 comments | | HN request time: 3.507s | source | bottom
1. akira2501 ◴[] No.41851912[source]
I personally dislike rust, but I love kernels, and so I'll always check these projects out.

This is one of the nicer ones.

It looks pretty conservative in it's use of Rust's advanced features. The code looks pretty easy to read and follow. There's actually a decent amount of comments (for rust code).

Not bad!

replies(2): >>41852794 #>>41855386 #
2. IshKebab ◴[] No.41852794[source]
Rust code is usually well commented in my experience.
replies(2): >>41853577 #>>41854248 #
3. cies ◴[] No.41853577[source]
Instead of asking "what other languages and project (open/closed, big/small, web/mobile/desktop, game/consumerapp/bizapp) have you experience with as to come to this conclusion?" people down vote you.

So lemme ask: what other languages and project (open/closed, big/small, web/mobile/desktop, game/consumerapp/bizapp) have you experience with as to come to this conclusion?

replies(2): >>41853586 #>>41854119 #
4. ramon156 ◴[] No.41854119{3}[source]
I expect the downvotes to be there because it's talking positively about rust, which is blasphemy! /j
replies(1): >>41858473 #
5. iknowstuff ◴[] No.41854248[source]
for the downvoters: it’s true, and it’s because of rustdoc and doctests. comments become publicly browsable documentation, and any code contained within is run as a part of the test suite.
replies(2): >>41854277 #>>41862206 #
6. 1oooqooq ◴[] No.41854277{3}[source]
think the downvotes are because of relevance. point was not using advanced rust features, not being documented
replies(1): >>41854310 #
7. forks ◴[] No.41854310{4}[source]
I don't see how the relevance is in question. GGGP said "There's actually a decent amount of comments (for rust code)." GGP seems to be responding to that parenthetical.
8. wg0 ◴[] No.41855386[source]
Otherwise is a decent language but what makes it difficult is the borrow semantics and lifetimes. Lifetimes are more complicated to get your head around.

But then there's this Arc, Ref, Pinning and what not - how deep is that rabbit hole?

replies(5): >>41855987 #>>41855995 #>>41856204 #>>41856306 #>>41856588 #
9. oneshtein ◴[] No.41855987[source]
Rust lifetime is just a label for a region of memory with various data, which is discarded at the end of its life time. When compiler enters a function, it creates a memory block to hold data of all variables in the function, and then discards this block at the exit from the function, so these variables are valid for life time of the function call only.
10. KingOfCoders ◴[] No.41855995[source]
I always feel Arc is the admission that the borrow checker with different/overlapping lifetimes is too difficult, despite what many Rust developers - who liberally use Arc - claim.
replies(5): >>41856058 #>>41857157 #>>41857254 #>>41857856 #>>41859332 #
11. Galanwe ◴[] No.41856058{3}[source]
It's not that the borrow checker is too difficult, it's that it's too limiting.

The _static_ borrow checker can only check what is _statically_ verifiable, which is but a subset of valid programs. There are few things more frustrating than doing something you know is correct, but that you cannot express in your language.

replies(2): >>41857630 #>>41860547 #
12. baq ◴[] No.41856204[source]
If you’re writing C and don’t track ownership of values, you’re in a world of hurt. Rust makes you do from day one what you could do in C but unless you have years of experience you think it isn’t necessary.
replies(2): >>41856314 #>>41856786 #
13. oersted ◴[] No.41856306[source]
I don’t entirely agree, you can get used to the borrow checker relatively quickly and you mostly stop thinking about it.

What tends to make Rust complex is advanced use of traits, generics, iterators, closures, wrapper types, async, error types… You start getting these massive semi-autogenerated nested types, the syntax sugar starts generating complex logic for you in the background that you cannot see but have to keep in mind.

It’s tempting to use the advanced type system to encode and enforce complex API semantics, using Rust almost like a formal verifier / theorem prover. But things can easily become overwhelming down that rabbit hole.

replies(1): >>41859789 #
14. metalloid ◴[] No.41856314{3}[source]
It was true until LLMs arrive. Feature compilers + IDEs can be integrated with LLMs to help programmers.

Rust was a great idea, before LLMs, but I don't see the motivation for Rust when LLMs can be the solution initial for C/C++ 'problems'.

replies(3): >>41856391 #>>41856419 #>>41858422 #
15. baq ◴[] No.41856391{4}[source]
On the contrary LLMs make using safe but constraining languages easier - you can just ask it how to do what you want in Rust, perhaps even by asking it to translate C-ish pseudocode.
16. smolder ◴[] No.41856419{4}[source]
Relying on LLMs to code for you in no way solves the safety problem of C/C++ and probably worsens it.
replies(1): >>41863848 #
17. junon ◴[] No.41856588[source]
Context: I'm writing a novel kernel in Rust.

Lifetimes aren't bad, the learning curve is admittedly a bit high. Post-v1 rust significantly reduced the number of places you need them and a recent update allows you to elide them even more if memory serves.

Arc isn't any different than other languages, not sure what you're referring to by ref but a reference is just a pointer with added semantic guarantees, and Pin isn't necessary unless you're doing async (not a single Pin shows up in the kernel thus far and I can't imagine why I'd have one going forward).

replies(1): >>41858618 #
18. wg0 ◴[] No.41856786{3}[source]
Okay, I think it is is more like Typescript. You hate it but one day you just write small JS program and convert it to Typescript to discover that static analysis alone had so many code paths revealed that would have resulted in uncaught errors and then you always feel very uncomfortable writing plain Javascript.

But what about tools like valgrind in context of C?

replies(5): >>41857436 #>>41857484 #>>41858152 #>>41858386 #>>41864741 #
19. jeroenhd ◴[] No.41857157{3}[source]
Lifetime tracking and ownership are very difficult. That's why languages like C and C++ don't do it. It's also why those languages needs tons of extra validation steps and analysis tools to prevent bugs.

Arc is nothing more than reference counting. C++ can do that too, and I'm sure there are C libraries for it. That's not an admission of anything, it's actually solving the problem rather than ignoring it and hoping it doesn't crash your program in fun and unexpected ways.

Using Arc also comes with a performance hit because validation needs to be done at runtime. You can go back to the faster C/C++ style data exchange by wrapping your code in unsafe {} blocks, though, but the risks of memory corruption, concurrent access, and using deallocated memory are on you if you do it, and those are generally the whole reason people pick Rust over C++ in the first place.

replies(1): >>41857894 #
20. GolDDranks ◴[] No.41857254{3}[source]
It's not just difficult, sometimes it's impossible to statically know a lifetime of a value, so you must dynamically track it. Arc is one of such tools.
21. badmintonbaseba ◴[] No.41857436{4}[source]
Valgrind is great, especially if you write extensive tests and you actually run them through it regularly. And even then, it does not prove the absence of any kind of bugs. Safe rust has strong guarantees.
22. baq ◴[] No.41857484{4}[source]
You probably should run your rust programs through valgrind regardless. Rust is safer than C, but any unsafe code drops you to approximately C level of safety and any C FFI calls are obviously outside of rust's control or responsibility.
23. netbsdusers ◴[] No.41857630{4}[source]
For kernels (and I suspect database engines might be added to the list, since they seem to have similar requirements to be both scalable and deal with massive amounts of shared state, but I'm not overly familiar with them) is where it gets particularly difficult.

Several kernels for example use type-stable memory, memory that is guaranteed to only hold objects of a particular type, though perhaps only providing that guarantee for as long as you hold an RCU read-lock (this is the case in Linux with SLAB_TYPESAFE_BY_RCU). It is possible in some cases to be able to safely deal with references to objects where the "lifetime" of the referent has ended, but where by dint of it being guaranteed to be the same type of object, you can still do what you want to do.

This comes in handy when you have a problem that commonly appears in kernels where you need to invert a typical lock ordering (a classic case is that the page fault codepath might want to lock, say, VM object then page queue, but the page-replacement codepath will want to lock page-queue then VM object.)

Unfortunately it's hard to think of how the preconditions for these tricks could be formally expressed.

replies(1): >>41859480 #
24. lmm ◴[] No.41857856{3}[source]
If tracking lifetimes is simple 90% of the time and complex 10% of the time, maybe a tool that lets you have them automatically managed (with some runtime overhead) that 10% of the time is the right way forward.
replies(1): >>41858439 #
25. GoblinSlayer ◴[] No.41857894{4}[source]
Looking at the code, it consists of long chains of get().unwrap().to_mut().unwrap().get() noise. Looks like coping with library design than ownership tacking. Also why Result<Option<T>>? Isn't Result already Option by itself? I guess that's why you need get().unwrap().to_mut() to get a value from Result<Option<T>> from an average function call?
replies(2): >>41858336 #>>41858604 #
26. rcxdude ◴[] No.41858152{4}[source]
Valgrind can only tell you about issues that your testcases exercise. It doesn't provide the same guarantees as static checking of memory safety invariants. But, if you're really concerned (especially about unsafe code), belt-and-bracers is a good strategy, and valgrind will work with rust binaries as well. Rust also has a tool called MIRI which can similarly flag up issues in testcases (it's effectively an interpreter for the intermediate representation in the compiler, and it can detect undefined behaviour even if the compiled assembly would happen to look OK. Still has the same limitation of needing extensive testcases though)
27. LinXitoW ◴[] No.41858336{5}[source]
If I ask my repository (backed by an sql db) to get a user, there might be 3 different scenarios I'm interested in:

- Technical problem (like connection problems) means I don't know what's in the db

- No technical problem, but no user entry

- No technical problem, and a user entry

You need the Result for the technical problems, and the Option for whether there's a user entry or not.

replies(1): >>41859945 #
28. tracker1 ◴[] No.41858386{4}[source]
A few years ago I was worrying on a Byzantine mess of a JS project. I converted everything to TS for the sole reason of somewhat safely refactoring the project as a whole.

There was so little trust in the fragility of the original, it took a few months to convince everyone the refactored TS branch was safe.

After that, feature development was a lot faster in terms of productivity again.

29. ulbu ◴[] No.41858422{4}[source]
Rust compiler checks things for you. People trust the Rust compiler because it enforces rules they want, so people don’t have to be in its place. Your suggestion is to be that checker to LLM-generated code. Back to square one.
30. tracker1 ◴[] No.41858439{4}[source]
Then you can use a language and runtime like C# or Java. Or you can use patterns like Go promotes.

There are lots of options if you want.

replies(1): >>41865586 #
31. tracker1 ◴[] No.41858473{4}[source]
I'm guessing a lot of any perception of a lack of comments or documentation in a rust codebase comes down to how new or green a developer is to rust.

If you're just starting out or doing something relatively simple, your goal is to get something working. This is so true regardless of the language.

replies(1): >>41864802 #
32. thesuperbigfrog ◴[] No.41858604{5}[source]
>> Also why Result<Option<T>>? Isn't Result already Option by itself?

No. I've written code that returns Result<Option<T>>. It was a wrapper for a server's query web API.

The Result part determines whether the request succeeded and the response is valid.

The Option part is because the parameter being queried might not exist. For example, if I ask the API for the current state of the user session with a given Session ID, but that Session ID does not exist, then the Rust wrapper could return OK(None) meaning that the request succeeded, but that no such session was found.

replies(2): >>41859652 #>>41859658 #
33. mcherm ◴[] No.41858618{3}[source]
Would you not want to use Pin when sharing memory with a driver or extension written in a different language (eg: C)?
replies(2): >>41861219 #>>41868083 #
34. surajrmal ◴[] No.41859332{3}[source]
Arc usually means you've not structured your code to have clear lifetimes where one object clearly outlives another. Typically I see c++ applications avoid it but actually suffer from bugs due to the same structural deficiencies. They said, I think it's almost always possible to to avoid it if you try hard enough. With async you need to use structured concurrency.
35. andrewflnr ◴[] No.41859480{5}[source]
Wouldn't you want the relevant Rust lifetime to be that of the type-stable memory block, not the individual "object" inside? I'm not that familiar with kernel programming, but that sounds a lot like an arena, and (IIRC) that's the approach with an arena.
36. GoblinSlayer ◴[] No.41859652{6}[source]
Presumably missing session is an alternative scenario and thus should be reported as an error, then you match and handle this error. Your design complicates the common scenario: in case of valid session you need double unwrap, cf File::open that could return Result<Option<File>> if file is not found.
replies(1): >>41860445 #
37. oniony ◴[] No.41859658{6}[source]
Result is whether an operation returned an error or not. Option is whether you have a value or no value.
replies(1): >>41860266 #
38. jonathanstrange ◴[] No.41859789{3}[source]
It's just overengineered. Many Rust folks don't realize it because they come from C++ and suffer from Stockholm Syndrome.
replies(1): >>41869044 #
39. GoblinSlayer ◴[] No.41859945{6}[source]
Surely Result is supposed to hold both system errors and business errors.
40. thesuperbigfrog ◴[] No.41860266{7}[source]
Exactly.

That is why a query that successfully returns no items can be represented as Ok(None).

A successful query with items returned would instead be Ok(Vec<Item>).

An error in the completing the query (for example, problem with the database), would be Err(DatabaseError) or Err(SomeOtherError).

41. thesuperbigfrog ◴[] No.41860445{7}[source]
>> Presumably missing session is an alternative scenario and thus should be reported as an error

But in this case, a query using an invalid session ID is not an error. It is asking for details about something that does not exist.

>> cf File::open that could return Result<Option<File>> if file is not found.

This type of query is not like File::open which gets a handle to a resource. Trying to get a handle to a resource that does not exist is an error.

This type of query is read-only and does not allocate any resources or prepare to do anything with the session.

It simplifies the control flow because it distinguishes between errors in completing a query versus the presence or absence of items returned from the query.

replies(1): >>41864904 #
42. acomar ◴[] No.41860547{4}[source]
I've found the opposite. every time I attempt to subvert the borrow checker, I eventually discover that I'm attempting to write a bug.
43. bombela ◴[] No.41861219{4}[source]
Pin is a pure compile time abstraction for a single problem: memory safety of self referential struct.

Pin leverages the type system to expose to the programmer receiving a pointer to a Pin'ned object, that this object has some pointer on itself (a self referencial struct). You better be mindful not to move this object to a different memory location unless you know for sure that it is safe to do so. The Pin abstraction makes it harder to forget; and easier to notice during code review; by forcing you to use the keyword unsafe for any operations on the pinned object that could move it around.

In C, there is no such way to warn the programmer besides documentation. It is up to the programmer to be very careful.

44. cgh ◴[] No.41862206{3}[source]
Javadoc pioneered this 25+ years ago and despite that, there's plenty of poorly-documented Java code out there. Orders of magnitude more of it than all of the Rust code in existence, in fact.

Intuition tells me that Rust is young enough to attract a certain type of early adopter, the kind of programmer who is more likely to document their code well from the outset.

45. BrainInAJar ◴[] No.41863848{5}[source]
probably?

even if the LLM is trained on flawless C code (which it isn't) it still has no way of reasoning about a complex system, it's just "what token is statistically most likely to come next"

replies(1): >>41866874 #
46. jimbomins ◴[] No.41864741{4}[source]
frama-c
replies(1): >>41869041 #
47. jimbomins ◴[] No.41864802{5}[source]
I've never looked at any Rust. But this mini thread leaves me expecting the Rust world to be like Perl. The experienced Rust/Perl user uses every feature and short cut for magnificently dense expressive (alt. incomprehensible gibberish to anyone else) and doesn't comment it because the code is self evident. When actually they just want to code wank showing how clever they are and how lazy anyone else is if they haven't take the time to understand the details and thus understand.

But like I said, I've not looked at any Rust despite its marketing success.

replies(1): >>41882284 #
48. lenkite ◴[] No.41864904{8}[source]
How does the caller know whether the response was empty because of an invalid session id ? You have conflated empty response with an erroneous situation. The simplest solution is just Result<T, E>.
replies(1): >>41865871 #
49. lmm ◴[] No.41865586{5}[source]
> Then you can use a language and runtime like C# or Java. Or you can use patterns like Go promotes.

But in that case you're stuck paying the overhead 100% of the time, even though 90% of the lifetimes are simple. (Perhaps a little less so with escape analysis etc., but doing it at compile time in a way that's understandable in the source feels a lot more reliable)

replies(1): >>41866076 #
50. thesuperbigfrog ◴[] No.41865871{9}[source]
>> How does the caller know whether the response was empty because of an invalid session id ?

Documentation and how SQL database queries work.

The documentation states that a valid session id will return a SessionInfo struct (since it is an Option the type is Some(SessionInfo) ), and that an invalid session id will return None.

If the SQL query is something like "SELECT * FROM USER_SESSIONS WHERE USER_SESSION_ID = $1" then if an invalid session id is provided the database returns zero rows. The query was successful, but there were no matching sessions with that session id.

>> You have conflated empty response with an erroneous situation. The simplest solution is just Result<T, E>.

Again, an empty response is not an error in this situation. If your database query returns zero rows, is it an error? The database query succeeded. There are no sessions with the provided session id. What error occurred?

51. neonsunset ◴[] No.41866076{6}[source]
Java and C# are languages of different class. C# is perfectly capable of systems programming and manual memory management that is at least more convenient than C (but not C++ with move semantics and operator overloading abuse, otoh C#'s type system and build process are saner which at least partially pays for this).
52. smolder ◴[] No.41866874{6}[source]
I said that because it's very possible for someone to write a more flawed program without an LLMs help. The exact probabilities weren't central to my point.
53. junon ◴[] No.41868083{4}[source]
Nah not really. Pin is for self-refefential data typically. It's compile time only so that information would get lost in C anyway, and there's no way to distinguish that data at runtime.

The kernel is doing so much anyway with memory maps and flipping in / out pages for scheduling and context switching that Pin doesn't add any value in such cases anyway.

It was also specifically built for async rust. I've never personally seen it in the wild in any other context.

54. junon ◴[] No.41869041{5}[source]
Which is terrible for kernel development, and is generally very hard to work with, unfortunately.
55. junon ◴[] No.41869044{4}[source]
How is it overengineered?
replies(1): >>41877577 #
56. jonathanstrange ◴[] No.41877577{5}[source]
That's my personal opinion after I've learned it and read Klabnik's book. I'm aware that other people's mileage differs. I'm listing a few reasons below.

- Overall too complex

- Wrong philosophy: demanding the user to solve problems instead of solving problems for the user

- Trying to provide infinite backwards compatibility with crates, which leads to hidden bitrot

- Slow compilation times

- Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.

- Adding features to fix misfeatures (e.g. all that lifetime cruft; arc pointers) instead of fixing the underlying problem

- Hiding implementations with leaky abstractions (traits)

- Going at great length to avoid existing solutions so users re-invent it (e.g. OOP with inheritance; GC), or worse, invent more complex paradigms to work around the lack (e.g. some Rust GUI efforts; all those smart pointer types to work around the lack of GC)

- A horrendous convoluted syntax that encourages bad programming style: lot's of unwrap, and_then, etc. that makes programs hard to read and audit.

- Rust's safe code is not safe: "Rust’s safety guarantees do not include a guarantee that destructors will always run. [...] Thus, allowing mem::forget from safe code does not fundamentally change Rust’s safety guarantees."

It already has similar complexity and cognitive demands as C++ and it's going to get worse. IMHO, that's also why it's popular. Programmers love shitty languages that allow them to show off. Boring is good.

replies(2): >>41883465 #>>41904646 #
57. tracker1 ◴[] No.41882284{6}[source]
I've read a lot more Rust than I've written at this point... A lot of what I've seen has been really easy to reason with and follow. There are a few features that are a bit harder to grok, especially with complex access lifetimes. Generally those complexities have been more from the inexperienced as a lot of what I've seen from more experienced devs simplifies those complex points of interaction making the entirety more easy to reason with.

I find a lot of the complexities tend to come from devs with more experience in communities that tend to add complexity by nature (C# and Java devs in particular). YMMV of course, that's just been my take so far. I've written a few simple web (micro)services in Rust and a couple of playground Tauri apps. I will say the simpler tasks have been incredibly easy to work through.

Though I may not have always taken the absolutely most performant, least memory path of work, it's been smaller/faster than other platforms and languages I have more experience with. And that's without even getting into build/compile time optimization options.

58. junon ◴[] No.41883465{6}[source]
> Overall too complex

Completely subjective. I've learned all there is to learn about Rust's syntax and most of its standard libraries, I think, and it's really not all that, in my personal opinion. There are certainly much more complex languages out there, even dynamic languages. I'd argue Typescript is more complex than Rust as a language.

> Wrong philosophy: demanding the user to solve problems instead of solving problems for the user

I have no idea what you mean by this. Do you mean you want more magic?

> Trying to provide infinite backwards compatibility with crates, which leads to hidden bitrot

Backwards compatibility reduces bitrot. Bitrot is when the ecosystem has moved on to a point of not supporting features used by stale code, thus making the code partially or completely unusable in newer environments as time progresses and the code doesn't update.

The Rust editions explicitly and definitively solve the bitrot problem, so I'm not sure what you're on about here.

> Slow compilation times

Sure, of course. That's really the biggest complaint most people have, though I've had C++ programs take just as long. Really depends on how the code is structured.

> Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.

Unsafe isn't a license to kill. It also doesn't allow "arbitrary" code. I suggest reading the rustnomicon, the book about Rust undefined behavior. All `unsafe` code must adhere to the postcondition that no undefined behavior is present. It also doesn't remove borrow checking and the like. Without `unsafe` you couldn't do really anything that a systems language would need to do in certain cases - e.g. writing a kernel requires doing inherently unsafe things (e.g. switching out CR3) where no compiler on earth currently written will understand those semantics.

People seem to parrot this same "unsafe nullifies rust's safety" without really understanding it. I suppose they could have renamed the `unsafe` keyword `code_the_does_stuff_unverifiable_by_the_compiler_so_must_still_adhere_to_well_formed_postrequisites_at_risk_of_invoking_undefined_behavior` but alas I think it'd be pretty annoying to write that so often.

It's pretty typical to abstract away `unsafe` code into a safe API, as most crates do.

> Adding features to fix misfeatures (e.g. all that lifetime cruft; arc pointers) instead of fixing the underlying problem

Lifetimes aren't "cruft", not sure what you mean. They've also been elided in a ton of cases.

An "arc pointer" isn't a thing; there's ARC (which is present in every unmanaged language, including C++, Objective-C, Swift, etc). I'm not sure what the "underlying problem" is you're referring to. Rust takes the position that the standard library shouldn't automatically make e.g. Mutexes an atomically reference counted abstraction, but instead allow the user to determine if reference counting if even necessary (Rc<Mutex>) and if it should be atomic so as to be shareable across cores (Arc<Mutex>). This type composure is exactly why Rust's type system is so easy to work with, refactor and optimize.

> Hiding implementations with leaky abstractions (traits)

Sorry for being blunt but this is a word salad. Traits aren't leaky abstractions. In my personal experience they compose so, so much better and have better optimization strategies than more rigid OOP class hierarchies. So I'm not sure what you mean here.

> Going at great length to avoid existing solutions so users re-invent it (e.g. OOP with inheritance; GC), or worse, invent more complex paradigms to work around the lack (e.g. some Rust GUI efforts; all those smart pointer types to work around the lack of GC)

Trait theory has been around for ages. GC is not a silver bullet and I wish people would stop pretending it was. There are endless drawbacks to GC. "All those smart pointer types" -- which ones? You just seem to want GC. I'm not sure why you want GC. GC solves few problems and creates many more. It can't be used in a ton of environments, either.

> A horrendous convoluted syntax that encourages bad programming style: lot's of unwrap, and_then, etc. that makes programs hard to read and audit.

This is completely subjective. And no, there's not a lot of `and_then`, I don't think you've read much Rust. Sorry if I'm sounding rude, but it's clear to me by this point in my response that you've played with the language only at a very surface level and have come to some pretty strong (and wrong) conclusions about it.

If you don't like it, fine, but don't try to assert it as being a bad language and imply something about the people that use it or work on it.

> Rust's safe code is not safe: "Rust’s safety guarantees do not include a guarantee that destructors will always run. [...] Thus, allowing mem::forget from safe code does not fundamentally change Rust’s safety guarantees."

You misunderstand what it's saying there but I'm honestly tired of rehashing stuff that's very easily researched that you seem to not be willing to do.

replies(1): >>41888346 #
59. jonathanstrange ◴[] No.41888346{7}[source]
That's a lengthy and passionate reply. The phrases "in my opinion" and "other people's mileage may differ" should have given away that my take was mostly subjective opinion. Rust is definitely not a language for me and would be a bad choice for the projects I'm working on. I continue to think it's totally overengineered. But, as noted before, other people's mileage may differ.

As long as the Rust fans stick to their favorite language, everybody can be happy.

60. j-krieger ◴[] No.41904646{6}[source]
> Claims to be "safe" but allows arbitrary unsafe code, and it's everywhere.

Sigh. This is not true. Not the first part, and especially not the last part. `Unsafe` doesn't allow arbitrary, unsafe code. It resets the compiler to a level where most manually managed languages are all the time. You still have to uphold all guarantees the compiler provides, just manually. That's why Miri exists.

replies(2): >>41908829 #>>41908855 #
61. ◴[] No.41908829{7}[source]
62. jonathanstrange ◴[] No.41908855{7}[source]
Either it's safe or it's unsafe. If you use the keyword "unsafe" it should definitely not mean "safe" (and it doesn't, but you seem to suggest it).
replies(3): >>41915086 #>>41915710 #>>42008676 #
63. junon ◴[] No.41915086{8}[source]
I think you're intentionally misreading everything people are saying to you.
replies(1): >>41916017 #
64. j-krieger ◴[] No.41915710{8}[source]
You're being obtuse. Terms have contexts. It is unsafe in the sense that C++ is unsafe, in that you may cause undefined behavior which can't be entirely checked by the compiler. You're back to what Valgrind/C++ -wall/UBSan provide.

"Unchecked" or "Unconfirmed" would've perhaps been better choices, but Rust considers all other manual memory and reference management unsafe, so the word stuck.

replies(1): >>41915977 #
65. jonathanstrange ◴[] No.41915977{9}[source]
I'm not being obtuse at all, I'm using the term exactly in the same way as you use it. By the way, the fact that Rust allows unsafe code by itself is not a problem. Although there are fully memory safe languages, many good languages allow unsafe code. Ada also allows unsafe constructions via pragmas. The problem is that, much unlike Ada programmers, Rust programmers use unsafe code extensively. That's the whole point. It's everywhere.
replies(2): >>41921857 #>>42008681 #
66. jonathanstrange ◴[] No.41916017{9}[source]
It's really just you and another Rust fan, there's no need to further discuss this among the three of us. I think I've made it extensively clear - based on the above reasons - that I believe it's a horrible programming language and people using it now will regret it in 10 years or so.
replies(3): >>41917931 #>>41921899 #>>42008790 #
67. junon ◴[] No.41917931{10}[source]
You're welcome to read the rustnomicon to learn about the topic you're discussing. Having written C and C++ for almost 15 years and doing extensive embedded work with it, I'm very secure in my decision to use Rust. But I'm capable of doing research to learn about it and to be somewhat involved in the development, mostly as an observer, to see both the direction it's moving and the overall process and meticulousness with which it's developed, to make an informed decision.

It doesn't seem you're making an informed statement at all anywhere in this thread, choosing instead to be hung up on semantics rather than the facts plainly laid out for you.

If that makes me an "enthusiast" then so be it.

replies(1): >>42008455 #
68. j-krieger ◴[] No.41921857{10}[source]
Alright, we’ve arrived at a point where I‘m going to ask you for a source. You‘re being willfully ignorant. I explained that „unsafe“ is not used in the Rust community like you think it is, and that the compiler provides verification of safe Rust types in unsafe blocks.

The only times I‘ve used unsafe code is for FFI and very rarely on bare metal machines.

A common Rust programmer will never use unsafe. They will use safe abstractions by the standard library. There is no need for direct use of unsafe in application code, and only very rarely in library code.

In fact, [1] reports that most unsafe calls in libraries are FFI calls into existing C/C++ code or system calls.

[1]: https://foundation.rust-lang.org/news/unsafe-rust-in-the-wil...

replies(1): >>42008434 #
69. j-krieger ◴[] No.41921899{10}[source]
I don‘t think so. The language is not perfect, and if you actually took the time to understand it’s benefits instead of spouting falsehoods, you‘d be able to see its advantages. My employer certainly sees its benefits, as do a lot of Fortune 500 companies right now.

I love C and I have used it for more than a decade, but I wouldn‘t choose it again. The most important thing I save with Rust is time and also my sanity. The very fact that I can trust my code if it compiles and that I don’t have to spend hours in GDB anymore makes it worth my while.

70. jonathanstrange ◴[] No.42008434{11}[source]
It's funny because you provide the source yourself: "[...] 34.35% make a direct function call into another crate that uses the unsafe keyword. [...] Nearly 20% of all crates have at least one instance of the unsafe keyword, a non-trivial number."

That's a lot of unsafe code for an allegedly safe language. Of course, most of it calls into system libraries. I never claimed or insinuated anything to the contrary (except perhaps in your imagination). But if you compare that to typical Ada code, the latter is much safer. Ada programmers try to do more things in Ada, probably because many of them need to write high integrity software.

Anyway, Rust offers nothing of value for me. It's overengineered and the languages I use are already entirely memory safe. Languages are mere tools, if it suits you well, continue using your Rust. No problem for me. By the way, I welcome when people re-write C++ code in Rust. Rust is certainly better than that, but that's a low-hanging fruit!

replies(2): >>42008778 #>>42009667 #
71. jonathanstrange ◴[] No.42008455{11}[source]
Well, if you come from C++ then Rust might look nice to you. But I come from languages like CommonLisp and Ada, and so Rust just looks like a horrible abomination to me because that's what it is. It's also not surprising. A good programming language simply cannot be designed that fast.
replies(1): >>42008583 #
72. ArtixFox ◴[] No.42008583{12}[source]
Common Lisp is an amalgamation of every lisp they could find, they slammed it all in. Calling it well designed is funny because every single CL developer openly accepts that its a fucking weird language with hell lot of warts that cannot be polished away.

Ada is fine, just verbose, kinda fun, no comments about it except that its kinda sad how weak their formal verification is. I prefer Frama-C over it. You can compare Ada and rust but ada is horrible, sincerely horrible at working with ownership. Frama-C can run laps around it as you can verify EVEN arbitrary pointer arithmetic.

Calling rust a horrible abomination is weird. As someone who dabbled in CL for an year, I love the fact that it has proc macros and even tho its harder to use it, i can make my own DSLs and make buildtime compilers!!

That opens up a world of possibilities.We can actually have safer and stricter math libraries! Maybe put us back in era of non-electron applications?

The horrible part might be syntax but eh, its a stupid thing to care about.

replies(3): >>42009058 #>>42009697 #>>42019160 #
73. ArtixFox ◴[] No.42008676{8}[source]
you said you use Ada, if you use it, you should know that Ada is fundamentally unsafe language with a safe subset called spark.

It could not verify dynamic allocations thats why it has such a huge toolset for working with static allocations.

Frama-C allows you to program in a safe subset of the unsafe language called C.

And these languages are the backbone of everything where lives are at risk. YOu can have a language that allows both unsafe and safe.

Safety is not binary and our trains run C/C++ [BOTH UNSAFE LANGUAGES]

74. ◴[] No.42008681{10}[source]
75. ArtixFox ◴[] No.42008778{12}[source]
Wait just 20% thats a low number damn. You said a lot and i was expecting...idk, 50%?

If Ada was used in domains where rust is used, like desktop applications, servers, high perf stuff, it would also do unsafe stuff you could never verify using spark.

But instead it is used in microcontrollers with runtimes provided by adacore and other vendors. Can you fully know if those pieces of code are 100% verified and safe? the free ones are not. atleast the free x86 one.

How ridiculous. The language you use is not memory safe btw. unchecked_deallocation can be easily used without any pragmas iirc. You need to enable spark_mode which will restrict you to an even smaller subset! You cannot even safely write a doubly linked list in it![you can with great pain in rust] [with less pain in Frama-C] [never tried ats]

76. ArtixFox ◴[] No.42008790{10}[source]
hey, if you just wanna hate a language and feel superior, you are free to. But the things you are saying are stupid.
77. lispm ◴[] No.42009058{13}[source]
> Common Lisp is an amalgamation of every lisp they could find, they slammed it all in.

Not really. It's mostly a modernized version of Zetalisp. In many cases simpler as that, with some added new stuff (like type declarations).

replies(1): >>42013545 #
78. j-krieger ◴[] No.42009667{12}[source]
> But if you compare that to typical Ada code, the latter is much safer. Ada programmers try to do more things in Ada, probably because many of them need to write high integrity software.

Well, since Rust is explicitly a system programming language, you would expect it to call into underlying systems more often, hence the use of unsafe.

The difference is this: Like all programming languages, Rust lives close to the metal. The „unsafe“ keyword is merely a marker that a system call might happen here, which might be inherently unsafe (think of C‘s localization methods which are not thread safe).

That‘s it. You can call ADA more safer but it still has to adhere to the underlying complexity of the system it runs on, and upon interaction with it via FFI calls it will be just as unsafe, just without a marker.

The low hanging fruit is exactly what Rust is made for. It‘s explicitly overengineered for that one use case, where GC languages can not be used for whatever reasons. It lives in the twilight zone between a GC and calling alloc/free yourself.

I disagree with people rewriting everything in Rust that could be simpler and better done with Python/Csharp/Go/etc. But if you need to work with manual memory management or concurrency with shared references, Rust is certainly your best bet.

79. f1shy ◴[] No.42009697{13}[source]
> Common Lisp is an amalgamation of every lisp they could find, they slammed it all in.

Absolutely NO. Take a look to the book by Guy Steel, and you will see is not like that.

80. ◴[] No.42013545{14}[source]
81. kazinator ◴[] No.42019160{13}[source]
CK standardization was before my Lisp time, but from the historical accounts that I read about, many people in the Lisp world were unhappy because Common Lisp didn't have this or that from whatever they were working on, and because CL was standard they would have to use it.

CL is fairly carefully designed with regards to compiling. This is why math functions are not generic for instance. Redefining standard functions is undefined behavior, as a self-modifying code. It omits features that don't integrate well with conventional run time and machine models like continuations. It doesn't even require implementations to optimize tail calls.

I have no idea why ANSI CL has such a large page count. In my mind it's such a small language. I think it could have benefited from an editorial pass to get it down to 600-something pages. But that would have delayed it even longer.

Once the horse escapes the barn it's risky. When you rewrite technical text you can very easily change the meaning of something, or take a particular interpretation where multiple are possible and such.

replies(1): >>42021922 #
82. lispm ◴[] No.42021922{14}[source]
> many people in the Lisp world were unhappy because Common Lisp didn't have this or that from whatever they were working on, and because CL was standard they would have to use it.

There were many unhappy, but from very different camps. Some were unhappy (for example people in the small Standard Lisp camp) because Common Lisp was not dynamic enough (it has features of static compilation, no fexprs, ...). Others were unhappy because it was too dynamic and difficult to compile to efficient code on small machines with stock CPUs. Some complained that it was too large and hard to fit onto some of the tiny machines of that time. Others complained that it was too small and lacked critical features from larger Lisp implementations (like stack groups, threads, a fully integrated object system, the first version had no useful error handling, gui functionality, extensible streams, ...).

Many more users/implementors from other Lisp dialects were unhappy, because it was clear that their favorite Lisp dialect would slowly fade away - funding was going away, new users would avoid it, existing users would port their code away, ...

> This is why math functions are not generic for instance

The math functions are generic (they work for several types). But there was no machinery behind that specified. They were not generic in the sense of CLOS generic functions (or similar). Also because with CLtL1 there was no such machinery in the language, but there are (non-extensible) generic numeric functions. CLOS later added a machinery for generic functions, but there was no experience to create optimized&fast code for it. The way of a CLtL1 Lisp implementation for fast numeric functions was to specify types and let a compiler generate type specific (non-generic) code. ANSI CL left the language in that state: the generic numeric functions were not implemented by CLOS, similar to so much in the language specification avoids further integration of CLOS and leaves it to implementations to decide how to implement them: I/O, condition handling, ...

> I have no idea why ANSI CL has such a large page count.

It was supposed to be a language specification for industrial users with detailed infos. There were standard templates how to specify a function, macro, ...

The Scheme reports OTOH were made to have the smallest page count possible with 2 columns of text, leaving out much of the detail of a real language spec. Why? Because it was material for a teaching language and thus was supposed to be read by students learning the language in a semester course at the university. Thus R5RS specified a teaching language, just barely, not as a full application programming language (for example it has zero error handling and basic things were just barely specified in its behavior and implementation).