rust - 类型 `&[u8]` 不能被 `usize` 索引?

下面是测试代码:

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);
}

因为调用 seqs.to_owend() 很昂贵,所以我只想将它的引用传递给 reverse_complement_seq_u8,但是这会导致以下错误:

error[E0277]: the type `&[u8]` cannot be indexed by `usize`
  --> src/main.rs:17:48
   |
17 |     let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
   |                      ------------------------- ^^^^ `&[u8]` cannot be indexed by `usize`
   |                      |
   |                      required by a bound introduced by this call
   |
   = help: the trait `Index<usize>` is not implemented for `&[u8]`
   = help: the following other types implement trait `Index<Idx>`:
             [T; N]
             [T]
note: required by a bound in `reverse_complement_seq_u8`

最佳答案

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

一个可能的解决方法是在参数中使用seq: &T 这样T 将是可以索引的[u8]。这需要一个额外的 + ?Sized 绑定(bind),否则编译器会添加一个隐式的 Sized 绑定(bind),而切片不会实现:

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);
}

Playground

另一个也适用于盒装切片的选项是指定 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);
}

Playground

关于rust - 类型 `&[u8]` 不能被 `usize` 索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74848949/

相关文章:

c++ - 在 C++ 中有没有办法像在 Java 中那样进行垃圾回收?

python - 捕获具有正面前瞻性但不匹配模式的组的正则表达式

powershell - 如何在 PowerShell 方法链接中使用换行符

javascript - 使用 js 正则表达式验证 gsheet/excel 相对范围字符串

c# - 查找过去最近的日期

c# - Blazor (.net 7) 中的三种依赖注入(inject)语法有区别吗?

python - 什么时候值得在 if-else 语句上使用循环?

regex - Linux 提取特定字符串之间的文本

typescript - 从返回类型推断出窄字符串文字类型

r - 如何将整行作为列名?