[HN Gopher] Show HN: How to program in Rust as if it was old sch...
___________________________________________________________________
Show HN: How to program in Rust as if it was old school C++ with
pointers
Basically wrap your data struct in Option<Rc<RefCell<_>>> Better
yet, use your custom type that provides few helper functions that
make using it as nice as old C++ pointers. Obviously there's no
pointer arithmetic, but it works great for dynamically allocated
structures like trees or linked lists. Please comment how it's a
horrible idea that will bring doom to me and my family.
fn main() { struct Data { pub number: i32 }
// struct Data { int number; }; let mut
p:Pointer<Data> = Pointer(None); // Data *p = NULL;
println!("{}", p.is_none()); // printf(p == NULL ?
"true\n" : "false\n"); p =
Pointer::new(Data { number: 5 }); // p = new Data { number: 5
}; println!("{}", p.pointed().number); //
printf("%d\n", p->number); let q =
p.clone(); // auto q = p;
q.pointed().number = 6; // q->number = 6;
println!("{}", p.pointed().number); // printf("%d\n",
p->number); println!("{}", p.is_clone_of(&q));
// printf(p == q ? "true\n" : "false\n"); }
// delete p; Helper Pointer<T> type: use
std::{rc::Rc, cell::{RefCell, RefMut}};
#[derive(Debug)] struct Pointer<T>(Option<Rc<RefCell<T>>>);
impl<T> Clone for Pointer<T> { fn clone(&self) -> Self
{ Pointer(Some(self.0.as_ref().unwrap().clone()))
} } impl<T> Pointer<T> { pub
fn new(d: T) -> Pointer<T> {
Pointer(Some(Rc::new(RefCell::new(d)))) }
pub fn pointed(&self) -> RefMut<T> { let res =
self.0.as_ref().unwrap().as_ref().borrow_mut(); res
} pub fn is_clone_of(&self, other:&Pointer<T>) -> bool
{ Rc::ptr_eq(&self.0.as_ref().unwrap(),
&other.0.as_ref().unwrap()) } pub fn
is_none(&self) -> bool { self.0.is_none()
} } Live version (Rust): https://play.rust-
lang.org/?gist=f43ce73b89537e0a9ae0586169b... Live version (C++):
http://tpcg.io/_LNG59M
Author : scotty79
Score : 14 points
Date : 2022-12-20 16:13 UTC (6 hours ago)
| scotty79 wrote:
| Whats most impressive for me is that making completely safe,
| effortlessly mutable and flexible linked list in Rust (or any
| other similar structure) can be as simple as:
| struct LinkedListNode { data: i32, next:
| Pointer<LinkedListNode> }
|
| You still need to care about memory leaks through structs linking
| to each other though because Rc means "reference counted".
| sph wrote:
| Option<Rc<RefCell<_>>> is not the same thing as a pointer, as the
| semantics are different, and it uses much more memory than an
| actual pointer.
|
| Rust has pointers. If you want to program like old school C++,
| wrap everything in unsafe and use all the pointers you want.
| scotty79 wrote:
| I don't want unsafe. I just want it to be out of my hair.
| RefCell is perfectly safe.
| itishappy wrote:
| C++ compiles down to 90 lines of ASM.
|
| https://godbolt.org/z/YYaK8f9rz
|
| Rust compiles down (up?) to 1428!
|
| https://godbolt.org/z/91YfzT5fb
|
| Thanks, I hate it! Do dynamic typing next!
| worldsavior wrote:
| It's because of the libraries. They get compiled once.
| steveklabnik wrote:
| It's because they don't have the same semantics, you are
| adding overhead with the Rust version in multiple ways.
| scotty79 wrote:
| I wonder how much difference there would be if I used
| shared_ptr in C++ instead of the bare one.
|
| EDIT:
|
| As far as I can tell less than 190 lines of asm but I don't
| know shared_ptr enough to produce exactly the same code.
| steveklabnik wrote:
| Yeah, that gets closer for sure. refcell is still going
| to add a bit of state to the value inside of the
| allocation, but at least the shared_ptr and Rc/Arc bits
| are the same semantic, so it'll be closer!
| scotty79 wrote:
| For that small price you get security against everything except
| memory leaks (which you don't get anyways in this bare C++
| either) not to mention other Rust niceties while keeping
| superficially same convenient semantics.
| [deleted]
| gavinray wrote:
| How is this any different than using a mutable reference or
| pointer to the "T"? struct Pointer<T> { ptr: *mut
| T } struct Pointer<T> { ptr: &mut T }
|
| This is just adding a ton of overhead and memory usage
| scotty79 wrote:
| You can safely pass Rc<RefCell<_>> around your program and
| store inside any structures without pretty much any concern for
| any lifetimes.
___________________________________________________________________
(page generated 2022-12-20 23:02 UTC)