我怎样才能得到一个Any类型的数组?

时间:2018-07-30 22:26:16

标签: arrays rust generic-programming

我正在尝试对类似数据框的结构建模。我知道在这里如何使用use std::any::{Any}; use std::fmt::Debug; pub trait Value: Any + Sized { fn as_any(&self) -> &Any { self } fn as_any_mut(&mut self) -> &mut Any { self } } impl Value for i32 {} #[derive(Debug)] struct Frame { data: Vec<Box<Any>>, } fn make_int(of: Vec<i32>) -> Frame { let data = of.into_iter().map(|x| Box::new(x.as_any())).collect(); Frame { data: data, } } ,但是我正在探索如何与C#/ Python / etc类似。

我尝试关注Rust Trait object conversion,但工作不正常:

error[E0277]: the trait bound `std::vec::Vec<std::boxed::Box<std::any::Any>>: std::iter::FromIterator<std::boxed::Box<&std::any::Any>>` is not satisfied
  --> src/main.rs:40:61
   |
40 |     let data = of.into_iter().map(|x| Box::new(x.as_any())).collect();
   |                                                             ^^^^^^^ a collection of type `std::vec::Vec<std::boxed::Box<std::any::Any>>` cannot be built from an iterator over elements of type `std::boxed::Box<&std::any::Any>`
   |
   = help: the trait `std::iter::FromIterator<std::boxed::Box<&std::any::Any>>` is not implemented for `std::vec::Vec<std::boxed::Box<std::any::Any>>`

编译器抱怨:

[root@localhost student_program]# python db_setup.py
Connection successful!!
Database already exists: students
create_table
/usr/local/lib/python3.6/site-packages/pymysql/cursors.py:329: Warning: (1050, " Table 'students_info' already exists")
  self._do_get_result()
use students;
Enter the first name :Frank
Enter the last name: Brady
Enter the email address: frank@noemail.com
Enter the address: 300 Main Street, Belfast
Enter the DOB in YYYY-MM-DD: 1980-02-02
Enter the english mark: 90
Enter the maths mark: 80
Enter the history mark: 70
Enter the science mark: 45
('INSERT into students_info (firstname, lastname,email,address,DOB,english,maths,history,science) VALUES  (%s,%s,%s,%s,%s,%s,%s,%s,%s);', ('Frank', 'Brady', 'frank@noemail.com', '300 Main Street, Belfast', '1980-02-02', '90', '80', '70', '45'))


######### Program below #################

     import os,pymysql

    mariadb_root = '/var/lib/mysql/'

    db_to_create = 'students'

    conn = pymysql.connect(host='localhost',  user='xxx', passwd='xxx',  cursorclass=pymysql.cursors.DictCursor)

    print('Connection successful!!')


# Check if db exists, if not create

def check_db_exists():
    dbfile = os.path.join(mariadb_root, db_to_create)
    if not os.path.exists(dbfile):
        cur = conn.cursor()
        command = "CREATE DATABASE %s;" % db_to_create
        print(command)
        cur.execute(command)
        print("Database created %s:", db_to_create)
    else:
        print("Database already exists: %s" % db_to_create)
check_db_exists()

def create_database():
    cur = conn.cursor()
    command = "use %s; " %db_to_create
    cur.execute(command)
    create_table = ("""
                CREATE TABLE IF NOT EXISTS students_info (
                ID int NOT NULL AUTO_INCREMENT,
                firstname varchar(255),
                lastname varchar(255),
                email varchar(255),
                address varchar(255),
                DOB DATE,
                english varchar(255),
                maths varchar(255),
                history varchar(255),
                science varchar(255),
                PRIMARY KEY (ID));
                """)
    print("create_table")
    cur.execute(create_table)
    print(command)

create_database()

def add_student():
    firstname = input("Enter the first name :")
    lastname = input("Enter the last name: ")
    email = input("Enter the email address: ")
    address = input("Enter the address: ")
    DOB = input("Enter the DOB in YYYY-MM-DD: ")
    english = input("Enter the english mark: ")
    maths = input("Enter the maths mark: ")
    history = input("Enter the history mark: ")
    science = input("Enter the science mark: ")

    cur = conn.cursor()
    command = "use %s; " %db_to_create
    cur.execute(command)

    cur.execute = ("""INSERT into students_info (firstname, lastname,email,address,DOB,english,maths,history,science) VALUES  (%s,%s,%s,%s,%s,%s,%s,%s,%s);""",
    (firstname,lastname,email,address, DOB,english,maths,history,science))
    print(cur.execute)

    cur.close()
    conn.close()
add_student()

1 个答案:

答案 0 :(得分:2)

主要问题在于此功能:

fn as_any(&self) -> &Any {
    self
}

这意味着您可以借用Value作为&Any,(它将&Value转换为&Any)。

但是,您想从该Box<Any>创建一个&Any。这永远不会起作用,因为&Any是借来的值,而Box<Any>是拥有的。

最简单的解决方案是更改特征以返回装箱的值(拥有的特征对象):

pub trait Value: Any + Sized {
    fn as_boxed_any(&self) -> Box<Any> {
        Box::new(self)
    }
    //The mut variation is not needed
}

现在make_int函数很简单:

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| x.as_boxed_any()).collect();
    Frame {
        data: data,
    }
}

更新:稍作修改,我发现您可以通过编写以下内容来创建Vec<Box<Any>>

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| Box::new(x) as Box<Any>).collect();
    Frame {
        data: data,
    }
}

如果您仅为此转换编写特征,则实际上并不需要它。