Is it possible to have one line assignments in structs as an example:
pub struct Pipe {
texture: Texture2D,
x: f32,
y: f32,
}
Instead have something like
pub struct Pipe {
texture: Texture2D,
(x, y): (f32, f32)
}
Also an approach like this is not what I want, because I want to access the variable like Pipe.pos.x or Pipe.x instead of pipe.pos.0:
pub struct Pipe {
texture: Texture2D,
pos: (f32, f32)
}
Is it possible to have one line assignments in structs as an example:
No.
Also an approach like this is not what I want, because I want to access the variable like Pipe.pos.x or Pipe.x instead of pipe.pos.0:
Define a struct. And possibly a ctor function for convenience.
That's called tuple
pub struct Pipe {
texture: Texture2D,
pos: (f32, f32),
}
let pipe = Pipe {
texture: new_texture,
pos: (10.5, 24.0),
};
println!("x position is {}", pipe.pos.0);
println!("y position is {}", pipe.pos.1);
// to access using x and y you can create a trait
trait XYAccessor {
fn x(&self) -> f32
fn y(&self) -> f32
}
// implement trait for the tuple
impl XYAccessor for (f32,f32) {
fn x(&self) -> f32 {
self.0
}
fn y(&self) -> f32 {
self.1
}
}
// then you can use .x() and .y()
println!("x position is {}", pipe.pos.x());
println!("y position is {}", pipe.pos.y());
Related
I'm making a maze algorithm using rust and wasm and I have two structs. A maze, and maze has an Vec of a Block struct.
Like this:
pub struct Maze {
pub cols: usize,
pub rows: usize,
pub blocks: Vec<Block>,
pub stack: Vec<usize>,
}
impl Maze {
pub fn new(cols: usize, rows: usize) -> Maze {
let mut maze = Maze {
cols,
rows,
blocks: vec![],
};
for y in 0..rows {
for x in 0..cols {
maze.blocks.push(Block::new(x, y))
}
}
maze
}
And the struct Block has an attribute called visited.
I want in a struct function of Maze change this value
// in Maze struct impl
pub fn run(&mut self) {
let current_index = self.get_current_index();
let mut current_block = &mut &self.blocks[current_index];
// .....
*current_block.visited = true;
In the last line occur an error:
error[E0614]: type `bool` cannot be dereferenced
--> src/maze.rs:119:17
|
119 | *current_block.visited = true;
| ^^^^^^^^^^^^^^^^^^^^^^
How can I do to change this value?
This is my implementation of Block
pub struct Block {
pub x: usize,
pub y: usize,
pub visited: bool,
}
impl Block {
pub fn new(x: usize, y: usize) -> Block {
Block {
x,
y,
visited: false,
}
}
How can I do to change the visited value from Maze.run?
There are two problems, one which is the error you see and one which you will encounter next. The problem with
*current_block.visited = true;
is that the precedence of * is lower than ., so you've written code equivalent to)
*(current_block.visited) = true;
which does not compile because the type of the visited field is bool, which indeed cannot be dereferenced. You could write
(*current_block).visited = true;
and that would work, but it's also unnecessary, because in Rust the . operator looks through references, so you only need
current_block.visited = true;
to assign to the visited field of an &mut Block.
The second problem is that you have an extra & here:
let mut current_block = &mut &self.blocks[current_index];
This means current_block is of type &mut &Block. You can never mutate through an & reference, so you need to remove the &, and it is not needed anyway:
let mut current_block = &mut self.blocks[current_index];
I have a struct:
pub struct Test {
pub x: i32,
pub y: i32,
}
I'd like to have a function that mutates this — easy:
pub fn mutateit(&mut self) {
self.x += 1;
}
This makes the entire struct mutable for the duration of the function call of mutateit, correct? I only want to mutate x, and I don't want to mutate y. Is there any way to just mutably borrow x?
Citing The Book:
Rust does not support field mutability at the language level, so you cannot write something like this:
struct Point {
mut x: i32, // This causes an error.
y: i32,
}
You need interior mutability, which is nicely described in the standard docs:
use std::cell::Cell;
pub struct Test {
pub x: Cell<i32>,
pub y: i32
}
fn main() {
// note lack of mut:
let test = Test {
x: Cell::new(1), // interior mutability using Cell
y: 0
};
test.x.set(2);
assert_eq!(test.x.get(), 2);
}
And, if you wanted to incorporate it in a function:
impl Test {
pub fn mutateit(&self) { // note: no mut again
self.x.set(self.x.get() + 1);
}
}
fn main() {
let test = Test {
x: Cell::new(1),
y: 0
};
test.mutateit();
assert_eq!(test.x.get(), 2);
}
I have a struct which looks something like this:
pub struct MyStruct<F>
where
F: Fn(usize) -> f64,
{
field: usize,
mapper: F,
// fields omitted
}
How do I implement Clone for this struct?
One way I found to copy the function body is:
let mapper = |x| (mystruct.mapper)(x);
But this results in mapper having a different type than that of mystruct.mapper.
playground
As of Rust 1.26.0, closures implement both Copy and Clone if all of the captured variables do:
#[derive(Clone)]
pub struct MyStruct<F>
where
F: Fn(usize) -> f64,
{
field: usize,
mapper: F,
}
fn main() {
let f = MyStruct {
field: 34,
mapper: |x| x as f64,
};
let g = f.clone();
println!("{}", (g.mapper)(3));
}
You can't Clone closures. The only one in a position to implement Clone for a closure is the compiler... and it doesn't. So, you're kinda stuck.
There is one way around this, though: if you have a closure with no captured variables, you can force a copy via unsafe code. That said, a simpler approach at that point is to accept a fn(usize) -> f64 instead, since they don't have a captured environment (any zero-sized closure can be rewritten as a function), and are Copy.
You can use Rc (or Arc!) to get multiple handles of the same unclonable value. Works well with Fn (callable through shared references) closures.
pub struct MyStruct<F> where F: Fn(usize) -> f64 {
field: usize,
mapper: Rc<F>,
// fields omitted
}
impl<F> Clone for MyStruct<F>
where F: Fn(usize) -> f64,
{
fn clone(&self) -> Self {
MyStruct {
field: self.field,
mapper: self.mapper.clone(),
...
}
}
}
Remember that #[derive(Clone)] is a very useful recipe for Clone, but its recipe doesn't always do the right thing for the situation; this is one such case.
You can use trait objects to be able to implement Сlone for your struct:
use std::rc::Rc;
#[derive(Clone)]
pub struct MyStructRef<'f> {
field: usize,
mapper: &'f Fn(usize) -> f64,
}
#[derive(Clone)]
pub struct MyStructRc {
field: usize,
mapper: Rc<Fn(usize) -> f64>,
}
fn main() {
//ref
let closure = |x| x as f64;
let f = MyStructRef { field: 34, mapper: &closure };
let g = f.clone();
println!("{}", (f.mapper)(3));
println!("{}", (g.mapper)(3));
//Rc
let rcf = MyStructRc { field: 34, mapper: Rc::new(|x| x as f64 * 2.0) };
let rcg = rcf.clone();
println!("{}", (rcf.mapper)(3));
println!("{}", (rcg.mapper)(3));
}
I need to convert a usize to a &str to pass to a fn foo(&str). I found the following two ways, but don't know if there is a difference between using as_str() or Deref. Maybe the work done by self in as_str links with Deref somehow? I do not know if it may be better to use one or the other or if they actually are the same.
Using temp.to_string().as_str():
#[inline]
#[stable(feature = "string_as_str", since = "1.7.0")]
pub fn as_str(&self) -> &str {
self
}
Using &*temp.to_string() or &temp.to_string(). This works via Deref:
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for String {
type Target = str;
#[inline]
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.vec) }
}
}
The question may depend on what you want to do in foo: does the passed
&str need to outlive foo or not ?
foo(&str) is a minimal example for s: &str in this code:
extern crate termbox_sys as termbox;
pub fn print(&self, x: usize, y: usize, sty: Style, fg: Color, bg: Color, s: &str) {
let fg = Style::from_color(fg) | (sty & style::TB_ATTRIB);
let bg = Style::from_color(bg);
for (i, ch) in s.chars().enumerate() {
unsafe {
self.change_cell(x + i, y, ch as u32, fg.bits(), bg.bits());
}
}
}
pub unsafe fn change_cell(&self, x: usize, y: usize, ch: u32, fg: u16, bg: u16) {
termbox::tb_change_cell(x as c_int, y as c_int, ch, fg, bg)
}
termbox_sys
As you noticed, as_str doesn't appear to do anything. In fact it returns self, a &String, where a &str is expected. This causes the compiler to insert a call to Deref. So your two ways are exactly the same.
I have the following wrapper type (similar to std::io::Cursor) to allow limiting the number of bytes read:
use std::{cmp, io};
pub struct Limited<T> {
inner: T,
pos: u64,
limit: u64,
}
impl<T> Limited<T> {
pub fn new(inner: T, limit: u64) -> Limited<T> {
Limited {
inner: inner,
pos: 0,
limit: limit,
}
}
pub fn pos(&self) -> u64 { self.pos }
pub fn limit(&self) -> u64 { self.limit }
pub fn into_inner(self) -> T { self.inner }
pub fn get_ref(&self) -> &T { &self.inner }
pub fn get_mut(&mut self) -> &mut T { &mut self.inner }
}
impl<T: io::Read> io::Read for Limited<T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let can_read = cmp::min(buf.len() as u64, self.limit - self.pos);
if can_read != 0 {
match self.inner.read(&mut buf[..(can_read as usize)]) {
Ok(read) => {
self.pos += read as u64;
Ok(read)
},
e # _ => e
}
} else {
Ok(0)
}
}
}
Then I can use it like this:
let mut l = Limited::new(io::Cursor::new(vec![1, 2, 3]), 1);
assert_eq!(l.read(&mut [0; 10]).unwrap(), 1);
Next I need to have Limited<RefMut<Read>> (so it owns the RefMut). Adding impl<'a, T: 'a + io::Read> io::Read for Limited<RefMut<'a, T>> makes the compiler complain about conflicting implementations.
Is there a way to have a generic implementation of Limited that would work for Read, RefMut<Read>, Rc<Read>, DerefMut<Target=Read>?
Is there a way to have a generic implementation of Limited that would work for Read, RefMut<Read>, Rc<Read>, Deref<Target=Read>?
Not really.
Read and DerefMut 1 are both traits. What should the expected behavior be if you passed in a type that implemented both traits? There's a RFC for specialization that might allow this in some form or the other. As the name says, it's usually about a more specific implementation, so I don't know how two distinct traits would fit in.
RefMut already implements DerefMut, so presumably that would be covered. I don't know how Rc would come into play as it's only for immutable data.
1: I assume you mean DerefMut instead of Deref as Read needs a mutable receiver.