类型“&[u8]”无法通过“usize”索引?

Moo*_*old 2 rust

以下是测试代码:

pub fn reverse_complement_seq_u8<T>(seq: T, len: usize) -> Vec<u8> 
    where T: std::ops::Index<usize, Output = u8>
{
    (0..len).rev().map(|i| match seq[i] {
            65 | 97  => 84, // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99  => 71, // 'C' | 'c' => 'G'
            n => n,
        } 
    ).collect()
}


fn main() {
    let seqs = "ACGATGCTACGA".as_bytes();//generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}
Run Code Online (Sandbox Code Playgroud)

因为调用seqs.to_owend()成本很高,所以我只想将其引用传递给reverse_complement_seq_u8,但这会导致以下错误:

pub fn reverse_complement_seq_u8<T>(seq: T, len: usize) -> Vec<u8> 
    where T: std::ops::Index<usize, Output = u8>
{
    (0..len).rev().map(|i| match seq[i] {
            65 | 97  => 84, // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99  => 71, // 'C' | 'c' => 'G'
            n => n,
        } 
    ).collect()
}


fn main() {
    let seqs = "ACGATGCTACGA".as_bytes();//generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}
Run Code Online (Sandbox Code Playgroud)

Jmb*_*Jmb 8

问题在于,虽然切片本身[u8]可以被索引,但对切片的引用&[u8]却不能。大多数情况下,对切片引用进行索引是有效的,因为 Rust 会根据需要自动取消引用,但在使用泛型时,您需要更加严格地告诉编译器。

seq: &T一种可能的解决方法是在参数中使用,以便可以T[u8]which 进行索引。这需要一个额外的+ ?Sized边界,否则编译器会添加一个Sized切片不实现的隐式边界:

pub fn reverse_complement_seq_u8<T>(seq: &T, len: usize) -> Vec<u8>
where
    T: std::ops::Index<usize, Output = u8> + ?Sized,
{
    (0..len)
        .rev()
        .map(|i| match seq[i] {
            65 | 97 => 84,  // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99 => 71,  // 'C' | 'c' => 'G'
            n => n,
        })
        .collect()
}

fn main() {
    let seqs = "ACGATGCTACGA".as_bytes(); //generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}
Run Code Online (Sandbox Code Playgroud)

操场

也适用于装箱切片的另一个选项是指定T必须取消引用某些可索引类型:

use std::ops::Deref;
pub fn reverse_complement_seq_u8<T, U>(seq: T, len: usize) -> Vec<u8>
where
    T: Deref<Target = U>,
    U: std::ops::Index<usize, Output = u8> + ?Sized,
{
    (0..len)
        .rev()
        .map(|i| match seq[i] {
            65 | 97 => 84,  // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99 => 71,  // 'C' | 'c' => 'G'
            n => n,
        })
        .collect()
}

fn main() {
    let seqs = "ACGATGCTACGA".as_bytes(); //generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}
Run Code Online (Sandbox Code Playgroud)

操场