首页 文章

Enum和Structs上可编码特征限制的问题

提问于
浏览
1

采取Rust试驾 . 到目前为止很有趣,但我不确定如何在这个实例中设置特征边界来做一些有用的事情 .

无法为T找到trait serialize :: serialize :: Encodable,std :: io :: IoError>的实现

在我看来,我需要在枚举 List<T: Encodable> 上设置一个界限 . 但是,当我尝试这个时,编译器有点不高兴 .

错误:枚举定义中不允许使用特征边界

所以我假设我必须把限制放在实现 impl<T:Encodable> 上,但得到了这个......

错误:类型参数数量错误:预期2但找到0

如果是这样的话,我会如何在Rust中做这样的事情?

extern crate serialize;
use serialize::{ json, Encodable };

#[deriving(Decodable, Encodable)] 
pub enum List<T> {
    Node(T, Box<List<T>>),
    Nil
}

impl<T> List<T> {
fn to_json(&self) -> String {
    json::Encoder::str_encode(self)
}
}

我工作时似乎工作正常,不要尝试封装编码,因为它知道int是可编码的...

let mut list: List<int> = Nil;
...
let encoded_string = json::Encoder::str_encode(&list);
println!("{}", encoded_string);

1 回答

  • 4

    目前,界限不能放在结构和枚举上 . 这可能会改变,但在此之前, impl 是您定义这些约束的地方 .

    让我们看一下特质的定义:Encodable<S: Encoder<E>, E> . SE 是它抱怨的东西,希望你定义它们 .

    现在让我们通过使用扩展该属性的 rustc --pretty expanded 编译代码来查看 #[deriving(Encodable)] 的作用 .

    #![feature(phase)]
    #![no_std]
    #![feature(globs)]
    #[phase(plugin, link)]
    extern crate std = "std#0.11.0-pre";
    extern crate native = "native#0.11.0-pre";
    extern crate serialize;
    use std::prelude::*;
    use serialize::{json, Encodable};
    
    pub enum List<T> { Node(T, Box<List<T>>), Nil, }
    #[automatically_derived]
    impl <__S: ::serialize::Encoder<__E>, __E,
          T: ::serialize::Encodable<__S, __E>> ::serialize::Encodable<__S, __E>
         for List<T> {
        fn encode(&self, __arg_0: &mut __S) -> ::std::result::Result<(), __E> {
            match *self {
                Node(ref __self_0, ref __self_1) => {
                    let _e = __arg_0;
                    _e.emit_enum("List",
                                 |_e|
                                     _e.emit_enum_variant("Node", 0u, 2u, |_e| {
                                                          match _e.emit_enum_variant_arg(0u,
                                                                                         |_e|
                                                                                             (*__self_0).encode(_e))
                                                              {
                                                              Ok(__try_var) =>
                                                              __try_var,
                                                              Err(__try_var) =>
                                                              return Err(__try_var)
                                                          };
                                                          return _e.emit_enum_variant_arg(1u,
                                                                                          |_e|
                                                                                              (*__self_1).encode(_e));
                                                      }))
                },
                Nil => {
                    let _e = __arg_0;
                    _e.emit_enum("List",
                                 |_e|
                                     _e.emit_enum_variant("Nil", 1u, 0u, |_e| {
                                                          return ::std::result::Ok(());
                                                      }))
                }
            }
        }
    }
    #[automatically_derived]
    impl <__D: ::serialize::Decoder<__E>, __E,
          T: ::serialize::Decodable<__D, __E>> ::serialize::Decodable<__D, __E>
         for List<T> {
        fn decode(__arg_0: &mut __D) -> ::std::result::Result<List<T>, __E> {
            __arg_0.read_enum("List",
                              |_d|
                                  _d.read_enum_variant(["Node", "Nil"],
                                                       |_d, i|
                                                           ::std::result::Ok(match i
                                                                                 {
                                                                                 0u
                                                                                 =>
                                                                                 Node(match _d.read_enum_variant_arg(0u,
                                                                                                                     |_d|
                                                                                                                         ::serialize::Decodable::decode(_d))
                                                                                          {
                                                                                          Ok(__try_var)
                                                                                          =>
                                                                                          __try_var,
                                                                                          Err(__try_var)
                                                                                          =>
                                                                                          return Err(__try_var)
                                                                                      },
                                                                                      match _d.read_enum_variant_arg(1u,
                                                                                                                     |_d|
                                                                                                                         ::serialize::Decodable::decode(_d))
                                                                                          {
                                                                                          Ok(__try_var)
                                                                                          =>
                                                                                          __try_var,
                                                                                          Err(__try_var)
                                                                                          =>
                                                                                          return Err(__try_var)
                                                                                      }),
                                                                                 1u
                                                                                 =>
                                                                                 Nil,
                                                                                 _
                                                                                 =>
                                                                                 ::std::rt::begin_unwind("internal error: entered unreachable code",
                                                                                                         "s.rs",
                                                                                                         4u)
                                                                             })))
        }
    }
    
    impl <T> List<T> {
        fn to_json(&self) -> String { json::Encoder::str_encode(self) }
    }
    

    是的,这很麻烦 . 但它显示了 Encodable 实现和正在编写的边界 . 基本上,预期约束将由您以相同的方式编写:您不关心任何特定类型,只是您有一个编码器 . 这就是它归结为:

    impl<S: Encoder<E>, E, T: Encodable<S, E>> Encodable<S, E> for List<T> {
        fn encode(&self, encoder: &mut S) -> Result<(), E> {
            …
        }
    }
    

相关问题