How to optimize brainf*ck instructions - algorithm

I'm trying to write an optimisation feature for my brainf*ck interpreter.
It basically combines same instructions into 1 instruction.
I wrote this function but It doesn't work properly:
pub fn optimize_multiple(instructions: &Vec<Instruction>) -> Vec<OptimizedInstruction> {
let mut opt: Vec<OptimizedInstruction> = Vec::new();
let mut last_instruction = instructions.get(0).unwrap();
let mut last_count = 0;
for instruction in instructions.iter() {
if instruction == last_instruction {
last_count += 1;
}
else if let Instruction::Loop(i) = instruction {
opt.push(OptimizedInstruction::Loop(optimize_multiple(i)));
last_count = 1;
}
else {
opt.push(OptimizedInstruction::new(last_instruction.clone(), last_count));
last_instruction = instruction;
last_count = 1;
}
}
opt
}
Here's the OptimizedInstruction enum and the "new" method:
(The Instruction::Loop hand is just a place holder, I didn't used it)
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OptimizedInstruction {
IncrementPointer(usize),
DecrementPointer(usize),
Increment(usize),
Decrement(usize),
Write,
Read,
Loop(Vec<OptimizedInstruction>),
}
impl OptimizedInstruction {
pub fn new(instruction: Instruction, count: usize) -> OptimizedInstruction {
match instruction {
Instruction::IncrementPointer => OptimizedInstruction::IncrementPointer(count),
Instruction::DecrementPointer => OptimizedInstruction::DecrementPointer(count),
Instruction::Increment => OptimizedInstruction::Increment(count),
Instruction::Decrement => OptimizedInstruction::Decrement(count),
Instruction::Write => OptimizedInstruction::Write,
Instruction::Read => OptimizedInstruction::Read,
Instruction::Loop(_i) => OptimizedInstruction::Loop(Vec::new()),
}
}
}
I ran it with this input:
++-[+-++]
But it gave me this output:
[Increment(2), Loop([Increment(1), Decrement(1)])]
Insted of this:
[Increment(2), Decrement(1), Loop([Increment(1), Decrement(1), Increment(2)])]
I've been trying to solve it for 2 days and still, I don't have any idea about why it doesn't work.
~ Derin

First off, just to rain a little on your parade I just want to point out that Wilfred already made a brainf*ck compiler in Rust that can compile to a native binary through LLVM (bfc). If you are getting stuck, you may want to check his implementation to see how he does it. If you ignore the LLVM part, it isn't too difficult to read through and he has a good approach.
When broken down into its core components, this problem revolves around merging two elements together. The most elegant way I have come across to solve this is use an iterator with a merge function. I wrote an example of what I imagine that would look like below. I shortened some of the variable names since they were a bit long but the general idea is the same. The merge function has a very simple job. When given two elements, attempt to merge them into a single new element. The iterator then handles putting them through that function and returning items once they can no longer be merged. A sort of optional fold if you will.
pub struct MergeIter<I: Iterator, F> {
iter: I,
func: Box<F>,
held: Option<<I as Iterator>::Item>,
}
impl<I, F> Iterator for MergeIter<I, F>
where
I: Iterator,
F: FnMut(&<I as Iterator>::Item, &<I as Iterator>::Item) -> Option<<I as Iterator>::Item>,
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
let mut first = match self.held.take() {
Some(v) => v,
None => self.iter.next()?,
};
loop {
let second = match self.iter.next() {
Some(v) => v,
None => return Some(first),
};
match (self.func)(&first, &second) {
// If merge succeeds, attempt to merge again
Some(v) => first = v,
// If merge fails, store second value for next iteration and return result
None => {
self.held = Some(second);
return Some(first);
}
}
}
}
}
pub trait ToMergeIter: Iterator {
fn merge<F>(self, func: F) -> MergeIter<Self, F>
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Self::Item>;
}
impl<I: Sized + Iterator> ToMergeIter for I {
fn merge<F>(self, func: F) -> MergeIter<Self, F>
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Self::Item>,
{
MergeIter {
iter: self,
func: Box::new(func),
held: None,
}
}
}
Then we can apply this process recursively to get our result. Here is a brief example of what that would look like. It isn't quite as memory efficient since it makes a new Vec each time, but it makes the process of specifying what instructions to merge way easier for you and helps make your work easier to read/debug.
pub fn optimize(instructions: Vec<Instruction>) -> Vec<Instruction> {
instructions
.into_iter()
// Recursively call function on loops
.map(|instruction| match instruction {
Instruction::Loop(x) => Instruction::Loop(optimize(x)),
x => x,
})
// Merge elements using the merge iter
.merge(|a, b| {
// State if any two given elements should be merged together or not.
match (a, b) {
(Instruction::IncPtr(x), Instruction::IncPtr(y)) => {
Some(Instruction::IncPtr(x + y))
}
(Instruction::DecPtr(x), Instruction::DecPtr(y)) => {
Some(Instruction::DecPtr(x + y))
}
(Instruction::Increment(x), Instruction::Increment(y)) => {
Some(Instruction::Increment(x + y))
}
(Instruction::Decrement(x), Instruction::Decrement(y)) => {
Some(Instruction::Decrement(x + y))
}
// Etc...
_ => None,
}
})
// Collect results to return
.collect()
}
playground link

Related

Rust proc_macro_derive (with syn crate) generating enum variant for matching

I'm a rust newbie, I started one week ago but this language is already very exciting. I'm rewritting a nodejs project in rust to get better performance and for the moment it's just crazy how faster it is.
I'm actually writting a proc_derive_macro (using the "syn" crate) to generate method on some specific struct. I'm almost done but i don't find how to generate enum variant. I will try to explain myself.
That's my code generation (using quote!)
quote! {
// The generated impl.
impl #name /*#ty_generics #where_clause*/ {
pub fn from_config(config: &IndicatorConfig) -> Result<Self, Error> {
let mut #name_lower = #name::default()?;
for (k, v) in config.opts.iter() {
println!("{:?} {:?}", k, v);
match (k.as_str(), v) {
("label", Values::String(val)) => {
#name_lower.label = val.clone();
}
("agg_time", Values::String(val)) => {
#name_lower.agg_time = Some(val.clone());
}
#(
(#fields_name_str, Values::Unteger(val)) => {
#name_lower.#fields_name = val.clone();
}
)*
(&_, _) => {}
}
}
#name_lower.init()?;
Ok(#name_lower)
}
}
};
As we can see I'm generating much of my code here
(#fields_name_str, Values::Unteger(val)) => {
#name_lower.#fields_name = val.clone();
}
But I didn't find a way to generate an "enum variant for the matching" (I don't know how we call that, i hope you will understand):
Values::String(val)
OR
Values::Unteger(val)
...
I'm writting a function which will create the variant matching according to parameter type found inside the struct:
fn create_variant_match(ty: &str) -> PatTupleStruct {
let variant = match ty {
"u32" => Ident::new("Unteger", Span::call_site()),
...
_ => unimplemented!(),
};
}
Actually I'm creating an Ident but I want to create the "enum variant match" -> Values::Unteger(val).
I watched the doc of the syn crate, spend hours trying to find a way, but it's a bit complex for my actual level, so I hope someone will explain me how to do that.
I found a simple way of doing that. Just need to parse a string (which i can format before) using the syn parser.
Didn't think about it before was trying to construct the Expr by hand (a bit stupid ^^)
syn::parse_str::<Expr>("Values::Unteger(val)")
which will generate the Expr needed

Rust - adding event listeners to a webassembly game

I'm attempting to create a game in web assembly. I chose to prepare it in rust and compile it using cargo-web. I managed to get a working game loop, but I have a problem with adding MouseDownEvent listener due to rust borrowing mechanisms. I would very much prefer to write "safe" code (without using "unsafe" keyword)
At this moment the game simply moves a red box from (0,0) to (700,500) with speed depending on the distance. I would like to have the next step to use user click update the destination.
This is the simplified and working code of the game.
static/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>The Game!</title>
</head>
<body>
<canvas id="canvas" width="600" height="600">
<script src="game.js"></script>
</body>
</html>
src/main.rs
mod game;
use game::Game;
use stdweb::console;
use stdweb::traits::*;
use stdweb::unstable::TryInto;
use stdweb::web::document;
use stdweb::web::CanvasRenderingContext2d;
use stdweb::web::html_element::CanvasElement;
use stdweb::web::event::MouseDownEvent;
fn main()
{
let canvas: CanvasElement = document()
.query_selector("#canvas")
.unwrap()
.unwrap()
.try_into()
.unwrap();
canvas.set_width(800u32);
canvas.set_height(600u32);
let context = canvas.get_context().unwrap();
let game: Game = Game::new();
// canvas.add_event_listener(|event: MouseDownEvent|
// {
// game.destination.x = (event.client_x() as f64);
// game.destination.y = (event.client_y() as f64);
// });
game_loop(game, context, 0f64);
}
fn game_loop(mut game : Game, context : CanvasRenderingContext2d, timestamp : f64)
{
game.cycle(timestamp);
draw(&game,&context);
stdweb::web::window().request_animation_frame( |time : f64| { game_loop(game, context, time); } );
}
fn draw(game : &Game, context: &CanvasRenderingContext2d)
{
context.clear_rect(0f64,0f64,800f64,800f64);
context.set_fill_style_color("red");
context.fill_rect(game.location.x, game.location.y, 5f64, 5f64);
}
src/game.rs
pub struct Point
{
pub x: f64,
pub y: f64,
}
pub struct Game
{
pub time: f64,
pub location: Point,
pub destination: Point,
}
impl Game
{
pub fn new() -> Game
{
let game = Game
{
time: 0f64,
location: Point{x: 0f64, y: 0f64},
destination: Point{x: 700f64, y: 500f64},
};
return game;
}
pub fn cycle(&mut self, timestamp : f64)
{
if timestamp - self.time > 10f64
{
self.location.x += (self.destination.x - self.location.x) / 10f64;
self.location.y += (self.destination.y - self.location.y) / 10f64;
self.time = timestamp;
}
}
}
The commented out part of main.rs is my attempt of adding a MouseDownEvent listener. Unfortunately it generates a compilation error:
error[E0505]: cannot move out of `game` because it is borrowed
--> src\main.rs:37:15
|
31 | canvas.add_event_listener(|event: MouseDownEvent|
| - ----------------------- borrow of `game` occurs here
| _____|
| |
32 | | {
33 | | game.destination.x = (event.client_x() as f64);
| | ---- borrow occurs due to use in closure
34 | | game.destination.y = (event.client_y() as f64);
35 | | });
| |______- argument requires that `game` is borrowed for `'static`
36 |
37 | game_loop(game, context, 0f64);
| ^^^^ move out of `game` occurs here
I would very much like to know how to properly implement a way of reading user input into a game. It doesn't need to be asynchronous.
I think that the compiler error message is pretty clear in this case. You're trying to borrow the game in the closure for the 'static lifetime and then you're also trying to move the game. It isn't allowed. I'd recommend to read The Rust Programming Language book again. Focus on chapter 4 - Understanding Ownership.
To make it shorter, your question boils down to something like - how to share a state, which can be mutated. There're plenty of ways how to achieve this goal, but it really depends on your needs (single or multi thread, etc.). I'm going to use Rc & RefCell for this problem.
Rc (std::rc):
The type Rc<T> provides shared ownership of a value of type T, allocated in the heap. Invoking clone on Rc produces a new pointer to the same value in the heap. When the last Rc pointer to a given value is destroyed, the pointed-to value is also destroyed.
RefCell (std::cell):
Values of the Cell<T> and RefCell<T> types may be mutated through shared references (i.e. the common &T type), whereas most Rust types can only be mutated through unique (&mut T) references. We say that Cell<T> and RefCell<T> provide 'interior mutability', in contrast with typical Rust types that exhibit 'inherited mutability'.
Here's what I did to your structures:
struct Inner {
time: f64,
location: Point,
destination: Point,
}
#[derive(Clone)]
pub struct Game {
inner: Rc<RefCell<Inner>>,
}
What does this mean? Inner holds the game state (same fields as the old Game). New Game has just one field inner, which contains the shared state.
Rc<T> (T is RefCell<Inner> in this case) - allows me to clone inner multiple times, but it won't clone the T
RefCell<T> (T is Inner in this case) - allows me to borrow T immutably or mutably, checking is done in the runtime
I can clone the Game structure multiple times now and it won't clone the RefCell<Inner>, just the Game & Rc. Which is what the enclose! macro is doing in the updated main.rs:
let game: Game = Game::default();
canvas.add_event_listener(enclose!( (game) move |event: MouseDownEvent| {
game.set_destination(event);
}));
game_loop(game, context, 0.);
Without the enclose! macro:
let game: Game = Game::default();
// game_for_mouse_down_event_closure holds the reference to the
// same `RefCell<Inner>` as the initial `game`
let game_for_mouse_down_event_closure = game.clone();
canvas.add_event_listener(move |event: MouseDownEvent| {
game_for_mouse_down_event_closure.set_destination(event);
});
game_loop(game, context, 0.);
Updated game.rs:
use std::{cell::RefCell, rc::Rc};
use stdweb::traits::IMouseEvent;
use stdweb::web::event::MouseDownEvent;
#[derive(Clone, Copy)]
pub struct Point {
pub x: f64,
pub y: f64,
}
impl From<MouseDownEvent> for Point {
fn from(e: MouseDownEvent) -> Self {
Self {
x: e.client_x() as f64,
y: e.client_y() as f64,
}
}
}
struct Inner {
time: f64,
location: Point,
destination: Point,
}
impl Default for Inner {
fn default() -> Self {
Inner {
time: 0.,
location: Point { x: 0., y: 0. },
destination: Point { x: 700., y: 500. },
}
}
}
#[derive(Clone)]
pub struct Game {
inner: Rc<RefCell<Inner>>,
}
impl Default for Game {
fn default() -> Self {
Game {
inner: Rc::new(RefCell::new(Inner::default())),
}
}
}
impl Game {
pub fn update(&self, timestamp: f64) {
let mut inner = self.inner.borrow_mut();
if timestamp - inner.time > 10f64 {
inner.location.x += (inner.destination.x - inner.location.x) / 10f64;
inner.location.y += (inner.destination.y - inner.location.y) / 10f64;
inner.time = timestamp;
}
}
pub fn set_destination<T: Into<Point>>(&self, location: T) {
let mut inner = self.inner.borrow_mut();
inner.destination = location.into();
}
pub fn location(&self) -> Point {
self.inner.borrow().location
}
}
Updated main.rs:
use stdweb::traits::*;
use stdweb::unstable::TryInto;
use stdweb::web::document;
use stdweb::web::event::MouseDownEvent;
use stdweb::web::html_element::CanvasElement;
use stdweb::web::CanvasRenderingContext2d;
use game::Game;
mod game;
// https://github.com/koute/stdweb/blob/master/examples/todomvc/src/main.rs#L31-L39
macro_rules! enclose {
( ($( $x:ident ),*) $y:expr ) => {
{
$(let $x = $x.clone();)*
$y
}
};
}
fn game_loop(game: Game, context: CanvasRenderingContext2d, timestamp: f64) {
game.update(timestamp);
draw(&game, &context);
stdweb::web::window().request_animation_frame(|time: f64| {
game_loop(game, context, time);
});
}
fn draw(game: &Game, context: &CanvasRenderingContext2d) {
context.clear_rect(0., 0., 800., 800.);
context.set_fill_style_color("red");
let location = game.location();
context.fill_rect(location.x, location.y, 5., 5.);
}
fn main() {
let canvas: CanvasElement = document()
.query_selector("#canvas")
.unwrap()
.unwrap()
.try_into()
.unwrap();
canvas.set_width(800);
canvas.set_height(600);
let context = canvas.get_context().unwrap();
let game: Game = Game::default();
canvas.add_event_listener(enclose!( (game) move |event: MouseDownEvent| {
game.set_destination(event);
}));
game_loop(game, context, 0.);
}
P.S. Please, before sharing any code in the future, install and use the rustfmt.
In your example game_loop owns game, as it is moved into the loop. So anything that should change game needs to happen inside game_loop. To fit event handling into this, you have multiple options:
Option 1
Let the game_loop poll for events.
You create a queue of events and your game_loop will have some logic to get the first event and handle it.
You will have to deal with synchronization here, so I suggest that you read up on Mutex and Concurrency in general. But it should be a fairly easy task once you get the hang of it. Your loop gets one reference and each event handler gets one, all try to unlock the mutex and then access the queue (vector probably).
This will make your game_loop the monolithic one truth of them all, which is a popular engine design because it is easy to reason about and start with.
But maybe you want to be less centralized.
Option 2
Let events happen outside the loop
This idea would be a bigger refactor. You would put your Game in a lazy_static with a Mutex around it.
Every invocation of the game_loop it will try to get the lock on said Mutex and then perform game calculations.
When an input event happens, that event also tries to get the Mutex on the Game. This means while the game_loop is processing, no input events are handled, but they will try to get in between ticks.
A challenge here would be to preserve input order and to make sure that inputs are processed quick enough. This might be a bigger challenge to get completely right. But the design will give you some possibilities.
A fleshed out version of this idea is Amethyst, which is massively parallel and makes for a clean design. But they employ a quite more complex design behind their engine.

Safely return multiple references to internal nodes, while still allowing mutation of other nodes

Suppose, for example, I have a linked list which does not allow removal of nodes.
Would it be possible to return shared references to values which have already been inserted, while still allowing the relative order of the nodes to be changed, or new nodes inserted?
Even mutation through one of the nodes should be safe "on paper" as long as only one node is used to mutate the list at a time. Is it possible to represent this in rust's ownership system?
I'm specifically interested in doing so without runtime overhead (potentially using unsafe in the implementation, but not in the interface).
EDIT: As requested, here is an example that gives the outline of what I am thinking of.
let list = MyLinkedList::<i32>::new()
let handle1 = list.insert(1); // Returns a handle to the inserted element.
let handle2 = list.insert(2);
let value1 : &i32 = handle1.get();
let value2 : &i32 = handle2.prev().get(); // Ok to have two immutable references to the same element.
list.insert(3); // Also ok to insert and swap nodes, while the references are held.
list.swap(handle1,handl2);
foo(value1,value2);
let exclusive_value: &mut i32 = handle1.get_mut(); // While this reference is held, no other handles can be used, but insertion and permutation are ok
handle5 = list.insert(4);
list.swap(handle1, handle2);
In other words, the data contained inside the nodes of the list is treated as one resource that can be borrowed shared/mutably, and the links between the nodes are another resource that can be borrowed shared/mutably.
In other words, the data contained inside the nodes of the list is treated as one resource that can be borrowed shared/mutably, and the links between the nodes are another resource that can be borrowed shared/mutably.
The idea to deal with such spatial partitioning is to introduce a different "key" for each partition; it's easy since they are static. This has been dubbed the PassKey pattern.
In the absence of brands, it will still require a run-time check: verifying that the elements-key is tied to this specific list instance is mandatory for safety. This is, however, a read-only comparison that will always be true, so the performance is about as good as it gets as far as run-time checks go.
The idea, in a nutshell:
let (handles, elements) = list.keys();
let h0 = handles.create(4);
handles.swap(h0, h1);
let e = elements.get(h0);
In your usecase:
It is always possible to change the links, so we will use internal mutability for this.
The borrow-check on elements inside handles will be carried out by borrowing elements.
The full implementation can be found here. It heavily uses unsafe, and I make no promise that it is fully safe, however it is hopefully sufficient for a demonstration.
In this implementation, I have opted for dumb handles and implemented the operations on the key types themselves. This limited the number of types who needed to borrow from the main list, and simplified borrowing.
The core idea, then:
struct LinkedList<T> {
head: *mut Node<T>,
tail: *mut Node<T>
}
struct Handles<'a, T> {
list: ptr::NonNull<LinkedList<T>>,
_marker: PhantomData<&'a mut LinkedList<T>>,
}
struct Elements<'a, T> {
list: ptr::NonNull<LinkedList<T>>,
_marker: PhantomData<&'a mut LinkedList<T>>,
}
LinkedList<T> will act as the storage, however will implement only 3 operations:
construction,
destruction,
handing out the keys.
The two keys Handles and Elements will both borrow the list mutably, guaranteeing that a single of (each of them) can exist simultaneously. Borrow-checking will prevent a new Handles or Elements from being created if any instance of them still lives for this list:
list: grants access to the list storage; Elements will only use it for checking (necessary) run-time invariants and never dereference it.
_marker: is the key to the borrow-checking actually guaranteeing exclusitivity.
Sounds cool so far? For completion, the last two structures then:
struct Handle<'a, T> {
node: ptr::NonNull<Node<T>>,
list: ptr::NonNull<LinkedList<T>>,
_marker: PhantomData<&'a LinkedList<T>>,
}
struct Node<T> {
data: T,
prev: *mut Node<T>,
next: *mut Node<T>,
}
Node is the most obvious representation of a doubly-linked list ever, so we're doing something right. The list in Handle<T> is there for the exact same purpose as the one in Elements: verifying that both Handle and Handles/Elements are talking about the same instance of list. It's critical for get_mut to be safe, and otherwise helps avoiding bugs.
There's a subtle reason for Handle<'a, T> having a lifetime tying to the LinkedList. I was tempted to remove it, however this would allow creating a handle from a list, destroying the list, then recreating a list at the same address... and handle.node would now be dangling!
And with, we only need to implement the methods we need on Handles and Elements. A few samples:
impl<'a, T> Handles<'a, T> {
pub fn push_front(&self, data: T) -> Handle<'a, T> {
let list = unsafe { &mut *self.list.as_ptr() };
let node = Box::into_raw(Box::new(Node { data, prev: ptr::null_mut(), next: list.head }));
unsafe { &mut *node }.set_neighbours();
list.head = node;
if list.tail.is_null() {
list.tail = node;
}
Handle {
node: unsafe { ptr::NonNull::new_unchecked(node) },
list: self.list, _marker: PhantomData,
}
}
pub fn prev(&self, handle: Handle<'a, T>) -> Option<Handle<'a, T>> {
unsafe { handle.node.as_ref() }.prev().map(|node| Handle {
node,
list: self.list,
_marker: PhantomData
})
}
}
And:
impl<'a, T> Elements<'a, T> {
pub fn get<'b>(&'b self, handle: Handle<'a, T>) -> &'b T {
assert_eq!(self.list, handle.list);
let node = unsafe { &*handle.node.as_ptr() };
&node.data
}
pub fn get_mut<'b>(&'b mut self, handle: Handle<'a, T>) -> &'b mut T {
assert_eq!(self.list, handle.list);
let node = unsafe { &mut *handle.node.as_ptr() };
&mut node.data
}
}
And this should be safe because:
Handles, after creating a new handle, only ever accesses its links.
Elements only ever returns references to data, and the links cannot be modified while it accesses them.
Example of usage:
fn main() {
let mut linked_list = LinkedList::default();
{
let (handles, mut elements) = linked_list.access();
let h0 = handles.push_front("Hello".to_string());
assert!(handles.prev(h0).is_none());
assert!(handles.next(h0).is_none());
println!("{}", elements.get(h0));
let h1 = {
let first = elements.get_mut(h0);
first.replace_range(.., "Hallo");
let h1 = handles.push_front("World".to_string());
assert!(handles.prev(h0).is_some());
first.replace_range(.., "Goodbye");
h1
};
println!("{} {}", elements.get(h0), elements.get(h1));
handles.swap(h0, h1);
println!("{} {}", elements.get(h0), elements.get(h1));
}
{
let (handles, elements) = linked_list.access();
let h0 = handles.front().unwrap();
let h1 = handles.back().unwrap();
let h2 = handles.push_back("And thanks for the fish!".to_string());
println!("{} {}! {}", elements.get(h0), elements.get(h1), elements.get(h2));
}
}

Rust: explicit type definition syntax in for loop [duplicate]

C++ example:
for (long i = 0; i < 101; i++) {
//...
}
In Rust I tried:
for i: i64 in 1..100 {
// ...
}
I could easily just declare a let i: i64 = var before the for loop
but I'd rather learn the correct way to doing this, but this resulted in
error: expected one of `#` or `in`, found `:`
--> src/main.rs:2:10
|
2 | for i: i64 in 1..100 {
| ^ expected one of `#` or `in` here
You can use an integer suffix on one of the literals you've used in the range. Type inference will do the rest:
for i in 1i64..101 {
println!("{}", i);
}
No, it is not possible to declare the type of the variable in a for loop.
Instead, a more general approach (e.g. applicable also to enumerate()) is to introduce a let binding by destructuring the item inside the body of the loop.
Example:
for e in bytes.iter().enumerate() {
let (i, &item): (usize, &u8) = e; // here
if item == b' ' {
return i;
}
}
If your loop variable happens to be the result of a function call that returns a generic type:
let input = ["1", "two", "3"];
for v in input.iter().map(|x| x.parse()) {
println!("{:?}", v);
}
error[E0284]: type annotations required: cannot resolve `<_ as std::str::FromStr>::Err == _`
--> src/main.rs:3:37
|
3 | for v in input.iter().map(|x| x.parse()) {
| ^^^^^
You can use a turbofish to specify the types:
for v in input.iter().map(|x| x.parse::<i32>()) {
// ^^^^^^^
println!("{:?}", v);
}
Or you can use the fully-qualified syntax:
for v in input.iter().map(|x| <i32 as std::str::FromStr>::from_str(x)) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
println!("{:?}", v);
}
See also:
How do I imply the type of the value when there are no type parameters or ascriptions?
There used to be a discussion where this was requested, which was followed up by an actual RFC.
It seems like the discussion was postponed, though, because not enough people really cared about the topic.
Currently, if you absolutely want to annotate, it seems like the best option you have is:
fn main() {
let my_vec: Vec<i32> = vec![-1, 22, -333];
for i in my_vec.iter() {
let _: &i32 = i;
println!("{}", i);
}
}
As you can see, this fails if the type doesn't match:
fn main() {
let my_vec: Vec<i32> = vec![-1, 22, -333];
for i in my_vec.iter() {
let _: &i16 = i;
println!("{}", i);
}
}
--> src/main.rs:4:23
|
4 | let _: &i16 = i;
| ---- ^ expected `i16`, found `i32`
| |
| expected due to this
|
= note: expected reference `&i16`
found reference `&i32`
Of course due to automatic dereferencing this method cannot differentiate between &i32 and &&i32, which might be a problem in some cases:
fn main() {
let my_vec: Vec<i32> = vec![-1, 22, -333];
for i in my_vec.iter() {
let _: &i32 = &i; // Compiles, but the right side is &&i32
println!("{}", i);
}
}
But in general this should bring enough confidence to potential reviewers, in my opinion.
Try casting with as:
for i in 1..100 as i64 {
// ...
}

Tree traversal in Rust vs Borrow Checker

I'm attempting to implement a tree structure in Rust, traverse it, and modify it, and I'm running into trouble with the borrow checker. My setup is more or less the following:
#![feature(slicing_syntax)]
use std::collections::HashMap;
#[deriving(PartialEq, Eq, Hash)]
struct Id {
id: int, // let’s pretend it’s that
}
struct Node {
children: HashMap<Id, Box<Node>>,
decoration: String,
// other fields
}
struct Tree {
root: Box<Node>
}
impl Tree {
/// Traverse the nodes along the specified path.
/// Return the node at which traversal stops either because the path is exhausted
/// or because there are no more nodes matching the path.
/// Also return any remaining steps in the path that did not have matching nodes.
fn traverse_path<'p>(&mut self, mut path: &'p [Id]) -> (&mut Box<Node>, &'p [Id]) {
let mut node = &mut self.root;
loop {
match node.children.get_mut(&path[0]) {
Some(child_node) => {
path = path[1..];
node = child_node;
},
None => {
break;
}
}
}
(node, path)
}
}
I have mutable references here because I want to be able to mutate the node returned by the method. For example, an add method would call traverse_path and then add nodes for the remainder of the path that did not have matching nodes.
This produces these errors:
s.rs:28:19: 28:32 error: cannot borrow `node.children` as mutable more than once at a time
s.rs:28 match node.children.get_mut(&path[0]) {
^~~~~~~~~~~~~
s.rs:28:19: 28:32 note: previous borrow of `node.children` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `node.children` until the borrow ends
s.rs:28 match node.children.get_mut(&path[0]) {
^~~~~~~~~~~~~
s.rs:39:6: 39:6 note: previous borrow ends here
s.rs:25 fn traverse_path<'p>(&mut self, mut path: &'p [Id]) -> (&mut Box<Node>, &'p [Id]) {
...
s.rs:39 }
^
s.rs:31:21: 31:38 error: cannot assign to `node` because it is borrowed
s.rs:31 node = child_node;
^~~~~~~~~~~~~~~~~
s.rs:28:19: 28:32 note: borrow of `node` occurs here
s.rs:28 match node.children.get_mut(&path[0]) {
^~~~~~~~~~~~~
s.rs:38:10: 38:14 error: cannot borrow `*node` as mutable more than once at a time
s.rs:38 (node, path)
^~~~
s.rs:28:19: 28:32 note: previous borrow of `node.children` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `node.children` until the borrow ends
s.rs:28 match node.children.get_mut(&path[0]) {
^~~~~~~~~~~~~
s.rs:39:6: 39:6 note: previous borrow ends here
s.rs:25 fn traverse_path<'p>(&mut self, mut path: &'p [Id]) -> (&mut Box<Node>, &'p [Id]) {
...
s.rs:39 }
^
error: aborting due to 3 previous errors
I understand why the borrow checker doesn't like this code, but I don't know how to make this work.
I also attempted an alternate implementation using an iterator using code like the following:
struct PathIter<'a> {
path: &'a [Id],
node: &'a mut Box<Node>
}
impl<'a> Iterator<Box<Node>> for PathIter<'a> {
fn next(&mut self) -> Option<Box<Node>> {
let child = self.node.get_child(&self.path[0]);
if child.is_some() {
self.path = self.path[1..];
self.node = child.unwrap();
}
child
}
}
The errors here ended up being lifetime-related:
src/http_prefix_tree.rs:147:27: 147:53 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
src/http_prefix_tree.rs:147 let child = self.node.get_child(&self.path[0]);
^~~~~~~~~~~~~~~~~~~~~~~~~~
src/http_prefix_tree.rs:146:3: 153:4 help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<Box<Node>>
src/http_prefix_tree.rs:146 fn next(&mut self) -> Option<Box<Node>> {
src/http_prefix_tree.rs:147 let child = self.node.get_child(&self.path[0]);
src/http_prefix_tree.rs:148 if child.is_some() {
src/http_prefix_tree.rs:149 self.path = self.path[1..];
src/http_prefix_tree.rs:150 self.node = child.unwrap();
src/http_prefix_tree.rs:151 }
Another thing I'm interested in is to collect the values of the decoration field for matching nodes and display these values if the path was fully exhausted. My very first thought was to have backlinks from the nodes to their parents, but the only example of this I found was Rawlink in DList, which scared me off. My next hope is that the iterator implementation (if I can get it to work) would lend itself naturally to something like that. Is that the right track to pursue?
Here's a variant of your first approach, using recursion to avoid borrowing conflicts. The iterative equivalent fails to compile because Rust is too strict when dealing with mutable borrowed pointers to mutable values.
impl Node {
fn traverse_path<'p>(&mut self, mut path: &'p [Id]) -> (&mut Node, &'p [Id]) { // '
if self.children.contains_key(&path[0]) {
self.children[path[0]].traverse_path(path[1..])
} else {
(self, path)
}
}
}
impl Tree {
/// Traverse the nodes along the specified path.
/// Return the node at which traversal stops either because the path is exhausted
/// or because there are no more nodes matching the path.
/// Also return any remaining steps in the path that did not have matching nodes.
fn traverse_path<'p>(&mut self, mut path: &'p [Id]) -> (&mut Node, &'p [Id]) { // '
self.root.traverse_path(path)
}
}
Note that I've changed the return type from &mut Box<Node> to &mut Node; you don't need to reveal to your users that you're using a Box in your implementation. Also, see how Node::traverse_path first checks if there's a value in the map using contains_key(), then retrieving the value using indexing. This means that the value is looked up twice, but that's the only way I've found to make this work without requiring unsafe code.
P.S.: You can change the root in Tree to be a Node, rather than a Box<Node>.

Resources