2016-08-24 4 views
3

간단한 구조체를 사용하여 Index을 구현하고 싶지만 Rust의 신입 사원으로는 차용 검사기에 많은 문제가 있습니다. usize에 의해 색인 때 내 구조체 나는 그것이 시작 단계 값을 저장해야하고 싶습니다, 아주 간단합니다, 그것은 start + idx * step를 반환해야합니다 :참조가 아닌 값을 반환하는 인덱스 특성 구현

pub struct MyStruct { 
    pub start: f64, 
    pub step: f64, 
} 

내 직감은 단순히 가지고 갈 수있을 것이다 내 유형의 Index의 서명과 플러그 :

impl Index<usize> for MyStruct { 
    type Output = f64; 

    fn index(&self, idx: usize) -> &f64 { 
     self.start + (idx as f64) * self.step 
    } 
} 

expected type &f64, found type f64 말하는 오류 mismatched types을 제공합니다. 완전히 녹의 타입 시스템이 어떻게 작동하는지 이해하는 것이 아직 누군가가 단순히 발현에 & 두드림 시도로 :

fn index(&self, idx: usize) -> &f64 { 
    &(self.start + (idx as f64) * self.step) 
} 

이 이제 borrowed value does not live long enough, 그래서 어쩌면 평생 변수를 필요 하더군요?

fn index<'a>(&self, idx: usize) -> &'a f64 { 
    &(self.start + (idx as f64) * self.step) 
} 

오류는 동일하지만 노트는 지금 lifetime 'a 대신 lifetime #1 제공, 그래서 나는 그 필요는 없습니다 생각,하지만 난 붙어있어 같은이 시점에서 나는 생각합니다. 나는 대부분의 언어에 대한 간단한 연습이 Rust에서 구현하기가 너무 어렵다는 것을 혼란스럽게 생각한다. 왜냐하면 내가하고 싶은 것은 참조 뒤에있는 함수에서 계산을 반환하기 때문이다. 값이 수요에 따라 계산되는 간단한 구조에 대해 Index을 구현하려면 어떻게해야합니까?

답변

3

Index 특성은 self의 멤버 (예 : Vec의 항목)에게 빌린 포인터를 반환하기위한 것입니다. index 메서드의 서명은 index에 의해 반환 된 모든 값을 self에 저장하고 MyStruct이 삭제 될 때까지 포인터가 유효한 상태로 유지되어야하므로 특성을 설명하기 위해 구현하는 것은 실용적이지 못합니다.

+0

MyStruct에서'us'를 가져 와서'f64'를 반환하는'index' 또는'at' 메소드를 구현하는 것이 더 낫겠습니까? 또한 Python 슬라이스에 상응하는 색인 ​​생성 기능을 구현하고 싶습니다 ('Range'는 녹이 생각합니다).'... '구문을 함수 인수로 사용할 수 있습니까? – bheklilr

+0

독립 실행 형'index' 메소드를 작성할 수는 있지만 인덱스 구문 ('x [i]')과 함께 사용할 수는 없습니다. 범위 구문은 표준 라이브러리가 제공하는 유형의 값을 생성합니다 (예 :'x..y'는 ['Range']를 생성합니다 (https://doc.rust-lang.org/stable/std/ops/struct.Range.html) 값). –

+0

그래서 근본적으로 나는 단지 여기에서 운이 없다? 오, 그렇다고 새로운 언어를 배우는 것은 다른 패러다임이 아닙니다. – bheklilr

1

이 사용 사례는 Index의 직관과 일치하지 않습니다. myStruct[3]을 볼 때, 나의 직관은 배열과 마찬가지로 이미 초기화 된 데이터에 대한 포인터를 얻고 있습니다. Index의 인터페이스는 이러한 직관을 뒷받침합니다. 당신의 자료 구조에 대한 좋은 색인 구문을 얻기

  1. :

    나는이 잠재적으로 달성하려고 수 있습니다 것을 볼 수 있습니다. 내가 Index을 구현의 전제에 대한 추천 단지 대신 이렇게 같은 &f64f64를 반환하는 방법을 제공하는 것이이 경우

.

impl MyStruct { 
    pub fn index(&self, idx: usize) -> f64 { 
     self.start + (idx as f64) * self.step 
    } 
} 

당신은 []을 읽는 누군가가 포인터를 얻고 있었다 생각으로 오해 될 수 있기 때문에 좋은 연산자를하지 않습니다. 그러나 원하는 기능을 얻을 수 있습니다. 사용 사례에 따라이 메서드의 이름을 바꿀 수 있습니다.

  1. Index 경계가있는 매개 변수에 MyStruct을 전달합니다.

이는 까다로운 이유가 있습니다. Index은 요청하기 전에 데이터가 있어야합니다. indexf64을 반환하기 때문에 생성하고 반환 할 수 없으므로 데이터 구조에 생성 할 수 없으며 포인터는 &mut self이 아니기 때문에 반환 할 수 없습니다. index으로 전화하기 전에이 값을 채워야합니다. 일부 재 설계는 순서대로 이루어지며 재 설계의 방향은 문제의보다 큰 맥락에 달려 있습니다.

+1

내 직감이 녹의 관례와 다른 것을 알았습니다. 그러나 녹이 여전히 아주 어린 언어이기 때문에이 정보는 찾기가 다소 어렵습니다. 필자의 접근 방식은 기본적으로 첫 번째 제안이다. 비록 내가 ''이라는 이름의 특성을'at '라는 단 하나의 메소드와 함께'Index'의 디자인을 모델로 삼아 사용했다. 나는 이미'At '에 대한'impl '이 존재한다면'Range '로 자동적으로'at'할 수있는 방법을 알아 냈습니다. 이것은 녹이 할 수 있기 때문에 매우 편리합니다. – bheklilr

관련 문제