繁体   English   中英

惯用的 Rust:字符串标记化应该是 function、特殊特征还是 TryFrom 特征?

[英]Idiomatic Rust: should string tokenization be a function, a special trait or a TryFrom trait?

我在空白处分割了一行文本,并希望将所有类似于ALALEUVAL等形式的片段转换为Token类型。 匹配很简单,但我是 rust 的新手,不知道如何推理实现转换本身。

我将它实现为StringTryFrom特征(见下文),因为对于初始文本中的大多数字符串片段,转换将失败,所以我认为这是拥有过滤机制的好方法。 我是否应该使用独立的 function? 我最终将如何为&str实现这个(这次我失败了,因为借用规则)?


#[derive(Debug)]
enum AminoAcid {
    VAL,    GLN,    ARG,    LEU,
    THR,    TYR,    SER,    PRO,
    CYS,    GLY,    ALA,    MET,
}
#[derive(Debug)]
struct Coordinate {
    x: f32,    y: f32,    z: f32,
}
#[derive(Debug)]
enum Token {
    Coordinate(Coordinate),
    AminoAcid(AminoAcid),
}

fn match_string(tgt: &str) -> Option<Token> {
    match tgt {
        "VAL" => Some(AminoAcid::VAL.into()),
        ..., // etc.
        "ALA" => Some(AminoAcid::ALA.into()),
        "MET" => Some(AminoAcid::MET.into()),
        _ => None,
    }


impl TryFrom<String> for Token {
    type Error = ();
    fn try_from(value: String) -> Result<Self, Self::Error> {
        let x = match match_string(&value) {
            Some(uu) => Ok(uu),
            None => Err(()),
        };
        x
    }
}

fn process_line(line: &str) -> Vec<Token> {
    let tokens = line.split_whitespace().collect::<Vec<&str>>();
    let mut results: Vec<Token> = vec![];
    for template_string in tokens {
        match template_string.to_string().try_into() {
            Ok(token) => {
                println!("Parsed to Token : {:?}", token);
                results.push(token)
            }
            _ => continue,
        };
    }
    return results;
}

我再次对经验丰富的 Rust 用户会考虑的权衡感兴趣。 谢谢你。

有很多方法可以做到这一点,但不建议FromStr作为从字符串解析值的惯用方式是有害的:

use std::str::FromStr;

#[derive(Debug)]
enum AminoAcid {
    VAL,    GLN,    ARG,    LEU,
    THR,    TYR,    SER,    PRO,
    CYS,    GLY,    ALA,    MET,
}

struct AminoAcidParseError;

impl FromStr for AminoAcid {
    type Err = AminoAcidParseError;
    fn from_str(s: &str) -> Result<AminoAcid, AminoAcidParseError> {
        match s {
            "VAL" => Ok(AminoAcid::VAL),
            // ... others
            "ALA" => Ok(AminoAcid::ALA),
            "MET" => Ok(AminoAcid::MET),
            _ => Err(AminoAcidParseError),
        }
    }
}

fn process_line(line: &str) {
    for s in line.split_whitespace() {
        match s.parse::<AminoAcid>() {
            Ok(a) => println!("Parsed to AminoAcid : {:?}", a),
            Err(_) => {},
        }
    }
}

查看操场上的完整示例。

实现此 trait 允许您在任何str上调用.parse()以错误地获取值。 我只为您的AminoAcid类型介绍了它,但您可以看到如何为Token及其他类型执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM