首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对字符串和`Borrow`使用`RangeFull`语法

对字符串和`Borrow`使用`RangeFull`语法
EN

Stack Overflow用户
提问于 2020-06-03 03:54:00
回答 1查看 59关注 0票数 1

我正在为Rust开发一个pandas-like库,我想要支持的一个功能是使用Rust range语法(例如0..=5..74....等)使用RangeBounds对索引(以及后面的序列/帧)进行伪切片。

此外,我希望支持使用对索引中包含的数据的引用作为范围的界限,而不仅仅是整数。因此,如果索引包含["dog", "cat", "bird", "sheep"],我希望支持查找.loc_range(&"dog"..=&"bird")以返回第一个、第二个和第三个条目。

我已经达到了支持作为标签的原语Copy类型完美工作的地步,但是我被String卡住了。不仅使用"str"而不是&"str"感觉很奇怪(请参阅下面的代码示例,比较charString的用法,可能值得提出一个新的SO问题),而且String版本上的朴素..调用根本无法编译!相反,我必须指定类型参数,如最后一行代码所示。

如果这是一个内部呼叫,我只会进行更改并继续。但我希望这是一个面向用户的函数,我不希望用户需要为这种边缘情况指定类型参数。有什么办法可以解决这个问题吗?更具体地说,我希望能够不必为TestIndex<String>::loc_range(..)案例指定类型变量。

代码语言:javascript
复制
use std::fmt::Debug;
use std::hash::Hash;
use std::borrow::Borrow;
use std::ops::RangeBounds;

pub trait TestLabel: Debug + Clone + Sized + PartialEq +
                     Eq + Hash + PartialOrd + Ord {}

impl TestLabel for char {}
impl TestLabel for String {}

pub struct TestIndex<L: TestLabel>(Vec<L>);

impl<L: TestLabel> TestIndex<L> {
    pub fn loc_range<'a, R, Q: 'a>(&self, range: R) -> Option<Vec<usize>>
    where
        R: RangeBounds<&'a Q>,
        L: Borrow<Q>,
        Q: Hash + Eq + ?Sized,
    {
        // Actual code uses `IndexSet` and does a set lookup,
        // hence the use of `Borrow`.
        // This is just dummy code to get a minimum working example.
        None
    }

    pub fn test() {
        let i = TestIndex(vec!['a', 'b', 'c']);

        // OK!
        println!("{:?}", i.loc_range(&'a'..&'c'));
        println!("{:?}", i.loc_range(..&'c'));
        println!("{:?}", i.loc_range(&'a'..));
        println!("{:?}", i.loc_range(..));

        let i = TestIndex(vec![
            String::from("a"),
            String::from("b"),
            String::from("c"),
        ]);

        // Strange that no '&' is needed, but compiles
        println!("{:?}", i.loc_range("a".."c"));
        println!("{:?}", i.loc_range(.."c"));
        println!("{:?}", i.loc_range("a"..));

        // ERROR E0283
        // cannot resolve `std::string::String: std::borrow::Borrow<_>`
        println!("{:?}", i.loc_range(..));

        // Compiles, but feels very unergonomic!
        println!("{:?}", i.loc_range::<_, str>(..));
    }
}

注意:我把这个问题贴在了Rust Discord上,但我也想在这里得到一些意见和见解,特别是因为我可以为我的用例提供更多的上下文和背景!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-03 06:40:28

我想你需要创造出你自己的特点

像这样:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f08dba83840f06bc69ffa203bf9838a4

(注意:我没有填写所有必需的实现,您将需要为每个范围类型提供一个LocRange<_>实现)您可以通过返回如下函数来最小化样板

代码语言:javascript
复制
pub fn generic_loc_range_impl<'a, R, L, Q: 'a>(test_index: &TestIndex<L>, range: R) -> Option<Vec<usize>>
    where
        R: RangeBounds<&'a Q>,
        L: Borrow<Q> + TestLabel,
        Q: Hash + Eq + ?Sized,
{
    ...
}

在每个实现中,这些实现只是为了删除导致推理失败的RangeFull的不必要类型参数。在RangeFull实现中,你可以像generic_loc_range_impl::<RangeFull, L, L>(self, ..)一样调用它

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62160327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档