Heterogenous persistent list in Rust
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I have implemented a basic, but seemingly working, persistent (as in immutable), heterogenous list type in Rust.
Here's the code:
#[derive(Debug)]
pub enum ConsCell<'a>
Char(char),
Number(u64),
String(&'a str),
pub struct PersistentList<'a, T: 'a>
first: Option<&'a T>,
rest: Option<&'a PersistentList<'a, T>>,
count: u64,
impl<'a, T> PersistentList<'a, T>
pub fn new() -> PersistentList<'a, T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> &T
self.first.unwrap()
pub fn next(&self) -> Option<&PersistentList<T>>
if self.count == 1
return None;
self.rest
pub fn cons(&'a self, x: &'a T) -> PersistentList<'a, T>
PersistentList
first: Some(x),
rest: Some(&self),
count: self.count + 1
pub fn count(&self) -> u64
self.count
This can be used like so:
fn main()
let list = PersistentList::new();
let cell = &ConsCell::Number(42);
let list = list.cons(cell);
let cell = &ConsCell::String(&"foo");
let list = list.cons(cell);
match list.first()
ConsCell::Char(c) => println!("", c),
ConsCell::Number(n) => println!("", n),
ConsCell::String(s) => println!("", s),
The ergonomics of this are not fantastic, however it does seem to work. Is there a more idiomatic way of doing something similar with Rust?
beginner linked-list rust immutability
add a comment |Â
up vote
4
down vote
favorite
I have implemented a basic, but seemingly working, persistent (as in immutable), heterogenous list type in Rust.
Here's the code:
#[derive(Debug)]
pub enum ConsCell<'a>
Char(char),
Number(u64),
String(&'a str),
pub struct PersistentList<'a, T: 'a>
first: Option<&'a T>,
rest: Option<&'a PersistentList<'a, T>>,
count: u64,
impl<'a, T> PersistentList<'a, T>
pub fn new() -> PersistentList<'a, T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> &T
self.first.unwrap()
pub fn next(&self) -> Option<&PersistentList<T>>
if self.count == 1
return None;
self.rest
pub fn cons(&'a self, x: &'a T) -> PersistentList<'a, T>
PersistentList
first: Some(x),
rest: Some(&self),
count: self.count + 1
pub fn count(&self) -> u64
self.count
This can be used like so:
fn main()
let list = PersistentList::new();
let cell = &ConsCell::Number(42);
let list = list.cons(cell);
let cell = &ConsCell::String(&"foo");
let list = list.cons(cell);
match list.first()
ConsCell::Char(c) => println!("", c),
ConsCell::Number(n) => println!("", n),
ConsCell::String(s) => println!("", s),
The ergonomics of this are not fantastic, however it does seem to work. Is there a more idiomatic way of doing something similar with Rust?
beginner linked-list rust immutability
Why doesn't yourPersistentList
own any value?
â Zeta
May 21 at 10:18
@Zeta I was having difficulty with owned values--I'm very new to Rust and I'm sure there is a better way of handling that shortcoming.
â maxcountryman
May 22 at 15:23
Just to be sure: you're also interested in a review that shows how to be able to movePersistentList
s around, without being limited to the lifetime of their surroundings, right? Or rather: did you take inspiration from another programming language/implementation?
â Zeta
May 22 at 18:58
I think that's right. In an ideal implementation you'd be able to add elements of virtually any type and pass the list around as you saw fit. So what I'm after is an immutable, heterogenous linked-list.
â maxcountryman
May 22 at 19:37
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I have implemented a basic, but seemingly working, persistent (as in immutable), heterogenous list type in Rust.
Here's the code:
#[derive(Debug)]
pub enum ConsCell<'a>
Char(char),
Number(u64),
String(&'a str),
pub struct PersistentList<'a, T: 'a>
first: Option<&'a T>,
rest: Option<&'a PersistentList<'a, T>>,
count: u64,
impl<'a, T> PersistentList<'a, T>
pub fn new() -> PersistentList<'a, T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> &T
self.first.unwrap()
pub fn next(&self) -> Option<&PersistentList<T>>
if self.count == 1
return None;
self.rest
pub fn cons(&'a self, x: &'a T) -> PersistentList<'a, T>
PersistentList
first: Some(x),
rest: Some(&self),
count: self.count + 1
pub fn count(&self) -> u64
self.count
This can be used like so:
fn main()
let list = PersistentList::new();
let cell = &ConsCell::Number(42);
let list = list.cons(cell);
let cell = &ConsCell::String(&"foo");
let list = list.cons(cell);
match list.first()
ConsCell::Char(c) => println!("", c),
ConsCell::Number(n) => println!("", n),
ConsCell::String(s) => println!("", s),
The ergonomics of this are not fantastic, however it does seem to work. Is there a more idiomatic way of doing something similar with Rust?
beginner linked-list rust immutability
I have implemented a basic, but seemingly working, persistent (as in immutable), heterogenous list type in Rust.
Here's the code:
#[derive(Debug)]
pub enum ConsCell<'a>
Char(char),
Number(u64),
String(&'a str),
pub struct PersistentList<'a, T: 'a>
first: Option<&'a T>,
rest: Option<&'a PersistentList<'a, T>>,
count: u64,
impl<'a, T> PersistentList<'a, T>
pub fn new() -> PersistentList<'a, T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> &T
self.first.unwrap()
pub fn next(&self) -> Option<&PersistentList<T>>
if self.count == 1
return None;
self.rest
pub fn cons(&'a self, x: &'a T) -> PersistentList<'a, T>
PersistentList
first: Some(x),
rest: Some(&self),
count: self.count + 1
pub fn count(&self) -> u64
self.count
This can be used like so:
fn main()
let list = PersistentList::new();
let cell = &ConsCell::Number(42);
let list = list.cons(cell);
let cell = &ConsCell::String(&"foo");
let list = list.cons(cell);
match list.first()
ConsCell::Char(c) => println!("", c),
ConsCell::Number(n) => println!("", n),
ConsCell::String(s) => println!("", s),
The ergonomics of this are not fantastic, however it does seem to work. Is there a more idiomatic way of doing something similar with Rust?
beginner linked-list rust immutability
edited May 23 at 9:46
t3chb0t
31.9k54195
31.9k54195
asked May 20 at 22:25
maxcountryman
418
418
Why doesn't yourPersistentList
own any value?
â Zeta
May 21 at 10:18
@Zeta I was having difficulty with owned values--I'm very new to Rust and I'm sure there is a better way of handling that shortcoming.
â maxcountryman
May 22 at 15:23
Just to be sure: you're also interested in a review that shows how to be able to movePersistentList
s around, without being limited to the lifetime of their surroundings, right? Or rather: did you take inspiration from another programming language/implementation?
â Zeta
May 22 at 18:58
I think that's right. In an ideal implementation you'd be able to add elements of virtually any type and pass the list around as you saw fit. So what I'm after is an immutable, heterogenous linked-list.
â maxcountryman
May 22 at 19:37
add a comment |Â
Why doesn't yourPersistentList
own any value?
â Zeta
May 21 at 10:18
@Zeta I was having difficulty with owned values--I'm very new to Rust and I'm sure there is a better way of handling that shortcoming.
â maxcountryman
May 22 at 15:23
Just to be sure: you're also interested in a review that shows how to be able to movePersistentList
s around, without being limited to the lifetime of their surroundings, right? Or rather: did you take inspiration from another programming language/implementation?
â Zeta
May 22 at 18:58
I think that's right. In an ideal implementation you'd be able to add elements of virtually any type and pass the list around as you saw fit. So what I'm after is an immutable, heterogenous linked-list.
â maxcountryman
May 22 at 19:37
Why doesn't your
PersistentList
own any value?â Zeta
May 21 at 10:18
Why doesn't your
PersistentList
own any value?â Zeta
May 21 at 10:18
@Zeta I was having difficulty with owned values--I'm very new to Rust and I'm sure there is a better way of handling that shortcoming.
â maxcountryman
May 22 at 15:23
@Zeta I was having difficulty with owned values--I'm very new to Rust and I'm sure there is a better way of handling that shortcoming.
â maxcountryman
May 22 at 15:23
Just to be sure: you're also interested in a review that shows how to be able to move
PersistentList
s around, without being limited to the lifetime of their surroundings, right? Or rather: did you take inspiration from another programming language/implementation?â Zeta
May 22 at 18:58
Just to be sure: you're also interested in a review that shows how to be able to move
PersistentList
s around, without being limited to the lifetime of their surroundings, right? Or rather: did you take inspiration from another programming language/implementation?â Zeta
May 22 at 18:58
I think that's right. In an ideal implementation you'd be able to add elements of virtually any type and pass the list around as you saw fit. So what I'm after is an immutable, heterogenous linked-list.
â maxcountryman
May 22 at 19:37
I think that's right. In an ideal implementation you'd be able to add elements of virtually any type and pass the list around as you saw fit. So what I'm after is an immutable, heterogenous linked-list.
â maxcountryman
May 22 at 19:37
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
I asked about this in the Rust beginner's IRC channel and someone helpfully pointed out that another approach might be to use trait objects and Box.
By way of illustration:
use std::fmt::Display;
pub trait Item: Display
impl Item for String
impl Item for bool
impl Item for char
impl Item for f64
impl Item for u64
pub struct PersistentList<T = Box<Item>>
first: Option<T>,
rest: Option<Box<PersistentList<T>>>,
count: usize,
impl<T> PersistentList<T>
pub fn new() -> PersistentList<T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> Option<&T>
self.first.as_ref()
pub fn next(self) -> Option<Box<PersistentList<T>>>
self.rest
pub fn cons(self, item: T) -> PersistentList<T>
let count = &self.count + 1;
PersistentList
first: Some(item),
rest: Some(Box::new(self)),
count,
pub fn count(&self) -> usize
self.count
The advantage here is that we can simply implement Item
for any given type and our collection will be capable of handling it. Here's a Playground link.
Now I think it's only fair to leave this question open for a while: I'm new to Rust and still learning and I'm unsure of the best practices and idioms--that said, this seems to be a pretty decent approach.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I asked about this in the Rust beginner's IRC channel and someone helpfully pointed out that another approach might be to use trait objects and Box.
By way of illustration:
use std::fmt::Display;
pub trait Item: Display
impl Item for String
impl Item for bool
impl Item for char
impl Item for f64
impl Item for u64
pub struct PersistentList<T = Box<Item>>
first: Option<T>,
rest: Option<Box<PersistentList<T>>>,
count: usize,
impl<T> PersistentList<T>
pub fn new() -> PersistentList<T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> Option<&T>
self.first.as_ref()
pub fn next(self) -> Option<Box<PersistentList<T>>>
self.rest
pub fn cons(self, item: T) -> PersistentList<T>
let count = &self.count + 1;
PersistentList
first: Some(item),
rest: Some(Box::new(self)),
count,
pub fn count(&self) -> usize
self.count
The advantage here is that we can simply implement Item
for any given type and our collection will be capable of handling it. Here's a Playground link.
Now I think it's only fair to leave this question open for a while: I'm new to Rust and still learning and I'm unsure of the best practices and idioms--that said, this seems to be a pretty decent approach.
add a comment |Â
up vote
2
down vote
accepted
I asked about this in the Rust beginner's IRC channel and someone helpfully pointed out that another approach might be to use trait objects and Box.
By way of illustration:
use std::fmt::Display;
pub trait Item: Display
impl Item for String
impl Item for bool
impl Item for char
impl Item for f64
impl Item for u64
pub struct PersistentList<T = Box<Item>>
first: Option<T>,
rest: Option<Box<PersistentList<T>>>,
count: usize,
impl<T> PersistentList<T>
pub fn new() -> PersistentList<T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> Option<&T>
self.first.as_ref()
pub fn next(self) -> Option<Box<PersistentList<T>>>
self.rest
pub fn cons(self, item: T) -> PersistentList<T>
let count = &self.count + 1;
PersistentList
first: Some(item),
rest: Some(Box::new(self)),
count,
pub fn count(&self) -> usize
self.count
The advantage here is that we can simply implement Item
for any given type and our collection will be capable of handling it. Here's a Playground link.
Now I think it's only fair to leave this question open for a while: I'm new to Rust and still learning and I'm unsure of the best practices and idioms--that said, this seems to be a pretty decent approach.
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I asked about this in the Rust beginner's IRC channel and someone helpfully pointed out that another approach might be to use trait objects and Box.
By way of illustration:
use std::fmt::Display;
pub trait Item: Display
impl Item for String
impl Item for bool
impl Item for char
impl Item for f64
impl Item for u64
pub struct PersistentList<T = Box<Item>>
first: Option<T>,
rest: Option<Box<PersistentList<T>>>,
count: usize,
impl<T> PersistentList<T>
pub fn new() -> PersistentList<T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> Option<&T>
self.first.as_ref()
pub fn next(self) -> Option<Box<PersistentList<T>>>
self.rest
pub fn cons(self, item: T) -> PersistentList<T>
let count = &self.count + 1;
PersistentList
first: Some(item),
rest: Some(Box::new(self)),
count,
pub fn count(&self) -> usize
self.count
The advantage here is that we can simply implement Item
for any given type and our collection will be capable of handling it. Here's a Playground link.
Now I think it's only fair to leave this question open for a while: I'm new to Rust and still learning and I'm unsure of the best practices and idioms--that said, this seems to be a pretty decent approach.
I asked about this in the Rust beginner's IRC channel and someone helpfully pointed out that another approach might be to use trait objects and Box.
By way of illustration:
use std::fmt::Display;
pub trait Item: Display
impl Item for String
impl Item for bool
impl Item for char
impl Item for f64
impl Item for u64
pub struct PersistentList<T = Box<Item>>
first: Option<T>,
rest: Option<Box<PersistentList<T>>>,
count: usize,
impl<T> PersistentList<T>
pub fn new() -> PersistentList<T>
PersistentList
first: None,
rest: None,
count: 0,
pub fn first(&self) -> Option<&T>
self.first.as_ref()
pub fn next(self) -> Option<Box<PersistentList<T>>>
self.rest
pub fn cons(self, item: T) -> PersistentList<T>
let count = &self.count + 1;
PersistentList
first: Some(item),
rest: Some(Box::new(self)),
count,
pub fn count(&self) -> usize
self.count
The advantage here is that we can simply implement Item
for any given type and our collection will be capable of handling it. Here's a Playground link.
Now I think it's only fair to leave this question open for a while: I'm new to Rust and still learning and I'm unsure of the best practices and idioms--that said, this seems to be a pretty decent approach.
edited May 28 at 17:43
answered May 24 at 3:17
maxcountryman
418
418
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194834%2fheterogenous-persistent-list-in-rust%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Why doesn't your
PersistentList
own any value?â Zeta
May 21 at 10:18
@Zeta I was having difficulty with owned values--I'm very new to Rust and I'm sure there is a better way of handling that shortcoming.
â maxcountryman
May 22 at 15:23
Just to be sure: you're also interested in a review that shows how to be able to move
PersistentList
s around, without being limited to the lifetime of their surroundings, right? Or rather: did you take inspiration from another programming language/implementation?â Zeta
May 22 at 18:58
I think that's right. In an ideal implementation you'd be able to add elements of virtually any type and pass the list around as you saw fit. So what I'm after is an immutable, heterogenous linked-list.
â maxcountryman
May 22 at 19:37