惯用 Rust:字符串标记化应该是函数、特殊特征还是 TryFrom 特征?
Idiomatic Rust: should string tokenization be a function, a special trait or a TryFrom trait?
我在空格处拆分了一行文本,并希望将所有类似 ALA
、LEU
、VAL
等形式的片段转换为 Token
类型。匹配很简单,但我是 rust 的新手,我不确定如何推理实现转换本身。
我将它实现为 String
的 TryFrom
特征(见下文),因为对于初始文本中的大多数字符串片段,转换将失败,所以我认为这是一个很好的方法有过滤机制。我应该宁愿使用独立功能吗?我最终如何为 &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(_) => {},
}
}
}
请参阅 playground 上的完整示例。
实现这个特性允许你在任何 str
上调用 .parse()
来错误地获取值。我只针对您的 AminoAcid
类型介绍了它,但您可以了解如何针对 Token
及以后的类型进行操作。
我在空格处拆分了一行文本,并希望将所有类似 ALA
、LEU
、VAL
等形式的片段转换为 Token
类型。匹配很简单,但我是 rust 的新手,我不确定如何推理实现转换本身。
我将它实现为 String
的 TryFrom
特征(见下文),因为对于初始文本中的大多数字符串片段,转换将失败,所以我认为这是一个很好的方法有过滤机制。我应该宁愿使用独立功能吗?我最终如何为 &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(_) => {},
}
}
}
请参阅 playground 上的完整示例。
实现这个特性允许你在任何 str
上调用 .parse()
来错误地获取值。我只针对您的 AminoAcid
类型介绍了它,但您可以了解如何针对 Token
及以后的类型进行操作。