Why would you do
#[derive(Debug)]
struct Inner<V> {
value: V,
}
struct MyStructA<V>
where
Inner<V>: Debug,
V: Debug,
{
value: V,
}
instead of just
struct MyStructB<V>
where
V: Debug,
{
value: V,
}
I'm specifically interested in what value where Inner<V>: Debug adds instead of where V: Debug. Would there ever be a reason that the complier cares more about this or is it just for human documentation? Unless I am mistaken, it does not appear that the where Inner<V>: Debug adds any extra bounds.
fn main() {
let my_struct_a = MyStructA {
value: Inner { value: 23 },
};
let my_struct_a_with_inner = MyStructA { value: 49 };
let my_struct_b = MyStructB { value: 64 };
let my_struct_b_with_inner = MyStructB {
value: Inner { value: 23 },
};
}
Playground with the code.
No, it does not add any bounds. It says that Inner<V> implements Debug - which happens when V implements Debug, so it is the same as the second bound. It is probably done for documentation.
Related
I encountered the following (reduced) example:
enum Thing {
A { value: f32 },
B { value: f32 },
}
fn main() {
let mut thing = Thing::A { value: 0. };
let thing_mut_ref = &mut thing;
if let Thing::A {value} = thing_mut_ref {
*thing_mut_ref = Thing::B { value: value * 2.0};
}
}
The following does not compile because value is captured as a &mut f32, and thus does not support multiplying by 2.0.
What surprised me was that adding ref to the matched pattern suddenly makes it compile, i.e. captures by value (dereferences value):
enum Thing {
A { value: f32 },
B { value: f32 },
}
fn main() {
let mut thing = Thing::A { value: 0. };
let thing_mut_ref = &mut thing;
if let Thing::A {ref value} = thing_mut_ref {
*thing_mut_ref = Thing::B { value: value * 2.0};
}
}
I know ref for usually doing the opposite - stating that we do not want to capture by value. How does this explain what is going on here?
It does not in fact dereference but convert the mutable reference into a shared one.
And as you can see from the documentation of Mul it is implemented for &f32 and f32 but not for &mut f32
I wish that enums in Rust can be used like Haskell's productive type. I want to
access a field's value directly
assign a field's value directly or make a clone with the changing value.
Directly means that not using too long pattern matching code, but just could access like let a_size = a.size.
In Haskell:
data TypeAB = A {size::Int, name::String} | B {size::Int, switch::Bool} deriving Show
main = do
let a = A 1 "abc"
let b = B 1 True
print (size a) -- could access a field's value directly
print (name a) -- could access a field's value directly
print (switch b) -- could access a field's value directly
let aa = a{size=2} -- could make a clone directly with the changing value
print aa
I tried two styles of Rust enum definition like
Style A:
#[derive(Debug)]
enum EntryType {
A(TypeA),
B(TypeB),
}
#[derive(Debug)]
struct TypeA {
size: u32,
name: String,
}
#[derive(Debug)]
struct TypeB {
size: u32,
switch: bool,
}
fn main() {
let mut ta = TypeA {
size: 3,
name: "TAB".to_string(),
};
println!("{:?}", &ta);
ta.size = 2;
ta.name = "TCD".to_string();
println!("{:?}", &ta);
let mut ea = EntryType::A(TypeA {
size: 1,
name: "abc".to_string(),
});
let mut eb = EntryType::B(TypeB {
size: 1,
switch: true,
});
let vec_ab = vec![&ea, &eb];
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
// Want to do like `ta.size = 2` for ea
// Want to do like `ta.name = "bcd".to_string()` for ea
// Want to do like `tb.switch = false` for eb
// ????
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
}
Style B:
#[derive(Debug)]
enum TypeCD {
TypeC { size: u32, name: String },
TypeD { size: u32, switch: bool },
}
fn main() {
// NOTE: Rust requires representative struct name before each constructor
// TODO: Check constructor name can be duplicated
let mut c = TypeCD::TypeC {
size: 1,
name: "abc".to_string(),
};
let mut d = TypeCD::TypeD {
size: 1,
switch: true,
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
// Can't access a field's value like
// let c_size = c.size
let c_size = c.size; // [ERROR]: No field `size` on `TypeCD`
let c_name = c.name; // [ERROR]: No field `name` on `TypeCD`
let d_switch = d.switch; // [ERROR]: No field `switch` on `TypeCD`
// Can't change a field's value like
// c.size = 2;
// c.name = "cde".to_string();
// d.switch = false;
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
}
I couldn't access/assign values directly in any style. Do I have to implement functions or a trait just to access a field's value? Is there some way of deriving things to help this situation?
What about style C:
#[derive(Debug)]
enum Color {
Green { name: String },
Blue { switch: bool },
}
#[derive(Debug)]
struct Something {
size: u32,
color: Color,
}
fn main() {
let c = Something {
size: 1,
color: Color::Green {
name: "green".to_string(),
},
};
let d = Something {
size: 2,
color: Color::Blue { switch: true },
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
let _ = c.size;
}
If all variant have something in common, why separate them?
Of course, I need to access not common field too.
This would imply that Rust should define what to do when the actual type at runtime doesn't contain the field you required. So, I don't think Rust would add this one day.
You could do it yourself. It will require some lines of code, but that matches the behavior of your Haskell code. However, I don't think this is the best thing to do. Haskell is Haskell, I think you should code in Rust and not try to code Haskell by using Rust. That a general rule, some feature of Rust come directly from Haskell, but what you want here is very odd in my opinion for Rust code.
#[derive(Debug)]
enum Something {
A { size: u32, name: String },
B { size: u32, switch: bool },
}
impl Something {
fn size(&self) -> u32 {
match self {
Something::A { size, .. } => *size,
Something::B { size, .. } => *size,
}
}
fn name(&self) -> &String {
match self {
Something::A { name, .. } => name,
Something::B { .. } => panic!("Something::B doesn't have name field"),
}
}
fn switch(&self) -> bool {
match self {
Something::A { .. } => panic!("Something::A doesn't have switch field"),
Something::B { switch, .. } => *switch,
}
}
fn new_size(&self, size: u32) -> Something {
match self {
Something::A { name, .. } => Something::A {
size,
name: name.clone(),
},
Something::B { switch, .. } => Something::B {
size,
switch: *switch,
},
}
}
// etc...
}
fn main() {
let a = Something::A {
size: 1,
name: "Rust is not haskell".to_string(),
};
println!("{:?}", a.size());
println!("{:?}", a.name());
let b = Something::B {
size: 1,
switch: true,
};
println!("{:?}", b.switch());
let aa = a.new_size(2);
println!("{:?}", aa);
}
I think there is currently no built-in way of accessing size directly on the enum type. Until then, enum_dispatch or a macro-based solution may help you.
I've been trying to implement a Strategy pattern in rust, but I'm having trouble understanding how to make it work.
So let's imagine we have a trait Adder and Element:
pub trait Element {
fn to_string(&self) -> String;
}
pub trait Adder {
type E: Element;
fn add (&self, a: &Self::E, b: &Self::E) -> Self::E;
}
And we have two implementations StringAdder with StringElements and UsizeAdder with UsizeElements:
// usize
pub struct UsizeElement {
pub value: usize
}
impl Element for UsizeElement {
fn to_string(&self) -> String {
self.value.to_string()
}
}
pub struct UsizeAdder {
}
impl Adder for UsizeAdder{
type E = UsizeElement;
fn add(&self, a: &UsizeElement, b: &UsizeElement) -> UsizeElement{
UsizeElement { value: a.value + b.value }
}
}
// String
pub struct StringElement {
pub value: String
}
impl Element for StringElement {
fn to_string(&self) -> String {
self.value.to_string()
}
}
pub struct StringAdder {
}
impl Adder for StringAdder {
type E = StringElement;
fn add(&self, a: &StringElement, b: &StringElement) -> StringElement {
let a: usize = a.value.parse().unwrap();
let b: usize = b.value.parse().unwrap();
StringElement {
value: (a + b).to_string()
}
}
}
And I want to write a code that uses trait methods from Adder trait and it's corresponding elements without knowing at compile time which strategy is going to be used.
fn main() {
let policy = "usize";
let element = "1";
let adder = get_adder(&policy);
let element_a = get_element(&policy, element);
let result = adder.add(element_a, element_a);
}
To simplify I'm going to assign a string to policy and element but normally that would be read from a file.
Is the only way to implement get_adder and get_element using dynamic dispatch? And by extension should I define Adder and Element traits to use trait objects and or the Any trait?
Edit: Here is what I managed to figure out so far.
An example of possible implementation is using match to help define concrete types for the compiler.
fn main() {
let policy = "string";
let element = "1";
let secret_key = "5";
let result = cesar(policy, element, secret_key);
dbg!(result.to_string());
}
fn cesar(policy: &str, element: &str, secret_key: &str) -> Box<dyn Element>{
match policy {
"usize" => {
let adder = UsizeAdder{};
let element = UsizeElement{ value: element.parse().unwrap() };
let secret_key = UsizeElement{ value: secret_key.parse().unwrap() };
Box::new(cesar_impl(&adder, &element, &secret_key))
}
"string" => {
let adder = StringAdder{};
let element = StringElement{ value: element.to_string() };
let secret_key = StringElement{ value: secret_key.to_string() };
Box::new(cesar_impl(&adder, &element, &secret_key))
}
_ => {
panic!("Policy not supported!")
}
}
}
fn cesar_impl<A>(adder: &A, element: &A::E, secret_key: &A::E) -> A::E where A: Adder, A::E : Element {
adder.add(&element, &secret_key)
}
However the issue is that I have to wrap every function I want to implement using a match function to determine the concrete type, and also case for every policy available.
It does not seem like the proper way of implementing it as it will bloat the code, make it more error prone and less maintainable unless I end up using macros.
Edit 2: Here you can find an example using dynamic dispatch. However I'm not convinced it's the proper way to implement the solution.
Example using dynamic dispatch
Thank you for your help :)
I am debugging the Parity Ethereum client with LLDB in VSCode and I am trying to access a value through several references.
Here is the code with relevant parts only (full code here)
pub struct SignedTransaction {
transaction: UnverifiedTransaction,
sender: Address,
public: Option<Public>,
}
impl Deref for SignedTransaction {
type Target = UnverifiedTransaction;
fn deref(&self) -> &Self::Target {
&self.transaction
}
}
pub struct UnverifiedTransaction {
unsigned: Transaction,
v: u64,
r: U256,
s: U256,
hash: H256,
}
impl Deref for UnverifiedTransaction {
type Target = Transaction;
fn deref(&self) -> &Self::Target {
&self.unsigned
}
}
pub struct Transaction {
pub nonce: U256,
pub gas_price: U256,
pub gas: U256,
pub action: Action,
pub value: U256,
pub data: Bytes,
}
pub enum Action {
Create,
Call(Address),
}
I have &SignedTransaction t with a value t.action = Action::Create (verified by manual print).
I am looking to get action value as VSCode shows a misleading value:
VSCode showing misleading value
I cannot manage to print only action value but the command p t.transaction outputs this (truncated) :
(ethcore_transaction::transaction::UnverifiedTransaction) $2 = {
unsigned = {
action = Call(((20) ['\', '!', '\xf6', '\xff', '\x7f', '\0', ...])) {
= Call(((20) ['\', '!', '\xf6', '\xff', '\x7f', '\0', ...])) {
RUST$ENUM$DISR = Create {...}
In the case where t.action = Action::Call() the value is correctly shown.
Why does it not show action = Create ? How can I print more cleanly action value ?
EDIT: the command fr v t->transaction.unsigned.action.RUST$ENUM$DISR shows the correct enum value. However I still don't know why fr v t->transaction.unsigned.action displays wrong values (which are also shown in the graphical interface).
I can use pattern matching on an enum that has one String parameter:
extern crate robots;
use std::any::Any;
use robots::actors::{Actor, ActorCell};
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String },
}
pub struct Dummy {}
impl Actor for Dummy {
// Using `Any` is required for actors in RobotS
fn receive(&self, message: Box<Any>, _context: ActorCell) {
if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
match *message {
ExampleMessage::Msg { param_a } => println!("got message"),
}
}
}
}
And yet I am unable to perform pattern matching on an enum with 2 parameters:
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String, param_b: usize },
}
impl Actor for Dummy {
// Using `Any` is required for actors in RobotS
fn receive(&self, message: Box<Any>, _context: ActorCell) {
if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
match *message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
}
}
This results in the error:
error[E0382]: use of moved value: `message`
--> src/example.rs:19:48
|
19 | ExampleMessage::Msg { param_a, param_b } => {
| ------- ^^^^^^^ value used here after move
| |
| value moved here
|
= note: move occurs because `message.param_a` has type `std::string::String`, which does not implement the `Copy` trait
I tried pattern matching on the same enum without downcasting before, and this works fine but I am required to downcast.
This just seems like very strange behavior to me and I don't know how to circumvent this error.
I am using Rust 1.19.0-nightly (afa1240e5 2017-04-29)
I tried pattern matching on the same enum without downcasting before, and this works fine
This is a good attempt at reducing the problem. The issue is that you reduced too far. Downcasting a Box<T> to a Foo doesn't return a Foo, it returns a Box<Foo>:
fn downcast<T>(self) -> Result<Box<T>, Box<Any + 'static>>
You can reproduce the problem with:
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String, param_b: usize },
}
fn receive2(message: Box<ExampleMessage>) {
match *message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
fn main() {}
The good news
This is a limitation of the current implementation of the borrow checker and your original code will work as-is when non-lexical lifetimes are enabled:
#![feature(nll)]
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String, param_b: usize },
}
fn receive2(message: Box<ExampleMessage>) {
match *message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
fn main() {}
The current reality
Non-lexical lifetimes and the MIR-based borrow checker are not yet stable!
When you match against a dereferenced value, the value is not normally moved. This allows you to do something like:
enum Foo {
One,
Two,
}
fn main() {
let f = &Foo::One;
match *f {
Foo::One => {}
Foo::Two => {}
}
}
In this case, you wish to take ownership of the thing inside the Box1 in order to take ownership of the fields when destructuring it in the match. You can accomplish this by moving the value out of the box before trying to match on it.
The long way to do this is:
fn receive2(message: Box<ExampleMessage>) {
let message = *message;
match message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
But you can also force the move by using curly braces:
fn receive2(message: Box<ExampleMessage>) {
match {*message} {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
I don't fully understand why a single field would work; it's certainly inconsistent. My only guess is that the ownership of the Box is moved to the first param, the param is extracted, then the compiler tries to move it again to the next parameter.
1 — Moving the contained element out via * is a special power that only Box supports. For example, if you try to do this with a reference, you get the "cannot move out of borrowed content" error. You cannot implement the Deref trait to do this either; it's a hard-coded ability inside the compiler.