rcchars
This commit is contained in:
parent
28f28b8298
commit
3b5bbb50d5
@ -5,6 +5,9 @@ multilingual = false
|
||||
src = "src"
|
||||
title = "Exercises"
|
||||
|
||||
[rust]
|
||||
edition = "2021"
|
||||
|
||||
[build]
|
||||
build-dir = "book"
|
||||
create-missing = false
|
||||
|
@ -7,3 +7,6 @@
|
||||
- [test1.rs (refbind)](./exercises/refbind.md)
|
||||
- [A/A1/A2](./exercises/multiple_blanket.md)
|
||||
- [BoolStream](./exercises/bool_stream.md)
|
||||
- [RcChars](./exercises/rcchars.md)
|
||||
- [Chapter 2](./chapter_2.md)
|
||||
- [AnyStr](./exercises/anystr.md)
|
||||
|
1
src/chapter_2.md
Normal file
1
src/chapter_2.md
Normal file
@ -0,0 +1 @@
|
||||
# Chapter 2
|
3
src/exercises/anystr.md
Normal file
3
src/exercises/anystr.md
Normal file
@ -0,0 +1,3 @@
|
||||
Create something similar to [Python's `typing.AnyStr`].
|
||||
|
||||
[Python's `typing.AnyStr`]: https://docs.python.org/3/library/typing.html#typing.AnyStr
|
@ -1,6 +1,29 @@
|
||||
Make `test_covariance` compile by making `BoolStream<'a>` covariant `'a`. Restrictions:
|
||||
- Can only change implementation details of `BoolStream` and its methods and add extra items outside of what's given, i.e. no signature/test change.
|
||||
- Changed version must behave the same way.
|
||||
|
||||
Consider the following code:
|
||||
```rust,compile_fail
|
||||
pub struct BoolStream<'a>(
|
||||
Box<dyn 'a + FnOnce() -> (bool, BoolStream<'a>)>,
|
||||
);
|
||||
|
||||
impl<'a> BoolStream<'a> {
|
||||
pub fn new(f: impl 'a + FnOnce() -> (bool, Self)) -> Self {
|
||||
Self(Box::new(f))
|
||||
}
|
||||
|
||||
pub fn next(self) -> (bool, Self) {
|
||||
self.0()
|
||||
}
|
||||
}
|
||||
|
||||
fn test_covariance<'a: 'b, 'b>(e: BoolStream<'a>) -> BoolStream<'b> {
|
||||
e
|
||||
}
|
||||
```
|
||||
Why does it fail to compile?
|
||||
|
||||
```rust
|
||||
pub struct BoolStream<'a>(
|
||||
// change this
|
||||
|
50
src/exercises/rcchars.md
Normal file
50
src/exercises/rcchars.md
Normal file
@ -0,0 +1,50 @@
|
||||
[`Chars`] but keeping a strong reference ([`Rc`]) to the string.
|
||||
|
||||
[`Chars`]: https://doc.rust-lang.org/std/str/struct.Chars.html
|
||||
[`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||
|
||||
```rust
|
||||
# mod rcchars {
|
||||
# pub struct RcChars { _rc: std::rc::Rc<String>, chars: std::mem::MaybeUninit<std::str::Chars<'static>> }
|
||||
# impl Iterator for RcChars {
|
||||
# type Item = char;
|
||||
# fn next(&mut self) -> Option<Self::Item> { unsafe { self.chars.assume_init_mut() }.next() }
|
||||
# }
|
||||
# impl RcChars {
|
||||
# pub fn from_rc(rc: std::rc::Rc<String>) -> Self {
|
||||
# let mut new = Self { _rc: rc, chars: std::mem::MaybeUninit::uninit() };
|
||||
# new.chars .write(unsafe { &*std::rc::Rc::as_ptr(&new._rc) }.chars());
|
||||
# new
|
||||
# }
|
||||
# }
|
||||
# impl From<std::rc::Rc<String>> for RcChars {
|
||||
# fn from(value: std::rc::Rc<String>) -> Self { Self::from_rc(value) }
|
||||
# }
|
||||
# impl Drop for RcChars {
|
||||
# fn drop(&mut self) { unsafe { self.chars.assume_init_drop() } }
|
||||
# }
|
||||
# }
|
||||
# use std::rc::Rc;
|
||||
# use rcchars::RcChars;
|
||||
{
|
||||
let rc = Rc::new("abc".to_string());
|
||||
let rcc = RcChars::from(rc.clone());
|
||||
drop(rc);
|
||||
assert_eq!(rcc.collect::<Vec<_>>(), ['a', 'b', 'c']);
|
||||
}
|
||||
{
|
||||
let rc = Rc::new("abc".to_string());
|
||||
let rcc = RcChars::from(rc);
|
||||
let rcc = Box::new(rcc);
|
||||
assert_eq!(rcc.collect::<Vec<_>>(), ['a', 'b', 'c']);
|
||||
}
|
||||
```
|
||||
|
||||
## Solutions
|
||||
- [Solution] used in rattlescript.
|
||||
- [Same solution] but with some extra comments.
|
||||
- [Another solution].
|
||||
|
||||
[Solution]: https://github.com/HavenSelph/rattlescript/blob/f8bafb8b063b9bf056efb1ea14188db0624d981c/src/interpreter/value.rs#L21-L50
|
||||
[Same solution]: https://gist.github.com/timotheyca/7e46c9734653b2fcbe826ea4d13b9aa0
|
||||
[Another solution]: https://gist.github.com/timotheyca/bc419e0997d6f7ea5722fd2823a78c62
|
@ -7,7 +7,7 @@ fn refbind<T, F: Fn(&T) -> Option<&T>>(f: F, fa: Option<&T>) -> Option<&T> {
|
||||
}
|
||||
}
|
||||
# }
|
||||
# fn refbind<'a,'b,T:'a+?Sized>(f:impl'a+Fn(&'a T)->Option<&'b T>,fa:Option<&'a T>)->Option<&'b T>{fa.and_then(f)}
|
||||
# fn refbind<'a,'b,T:'a+?Sized>(f:impl 'a+Fn(&'a T)->Option<&'b T>,fa:Option<&'a T>)->Option<&'b T>{fa.and_then(f)}
|
||||
|
||||
// don't change anything below
|
||||
|
||||
|
@ -2,9 +2,11 @@
|
||||
|
||||
Random Rust exercises.
|
||||
|
||||
**Warning: this is a live-edited website, errors and accidental spoilers are to be expected.**
|
||||
|
||||
# Solutions
|
||||
|
||||
Currently solutions are only provided in a non-human-readable form in the page source.
|
||||
Currently solutions are mostly provided in a non-human-readable form in the page source.
|
||||
Those are mostly intended for testing that the exercise is even possible to solve.
|
||||
```rust
|
||||
# /*
|
||||
|
Loading…
Reference in New Issue
Block a user