質問するログイン新規登録

回答編集履歴

5

スライスと実体のライフタイムの長さの要件が逆になっていたので修正しました

2018/11/06 02:52

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  > insert関数の中で有効でも、返り値として使用すれば、関数のスコープを抜けた際にアクセス出来ないようになるためエラーを出しているということでしょうか?
16
16
 
17
- スライスは型に参照`&`が現れているように、それ自体は値の実体を持たず、別の場所にある実体(配列、`Vec`など)を参照します。スライスは実体なしには存在できません。つまりスライスのライフタイム(生存期間)は実体のライフタイムよりもくなければなりません。
17
+ スライスは型に参照`&`が現れているように、それ自体は値の実体を持たず、別の場所にある実体(配列、`Vec`など)を参照します。スライスは実体なしには存在できません。つまりスライスのライフタイム(生存期間)は実体のライフタイムよりもくなければなりません。
18
18
 
19
19
  ではご質問のコードでそれらの実体はどこにあるでしょうか? 以下のようになっています。
20
20
 

4

私のinsert関数にバグがあったため修正しました

2018/11/06 02:52

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -35,7 +35,7 @@
35
35
  ```rust
36
36
  fn insert<'a, T: Ord + Clone>(x: T, v: &[T]) -> Vec<T> {
37
37
  if v.is_empty() {
38
- Vec::new()
38
+ vec![x]
39
39
  } else {
40
40
  if x < v[0] {
41
41
  let mut res = vec![x];

3

配列型の表記の間違いを修正しました

2018/11/05 02:11

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -1,5 +1,7 @@
1
- 最初に知っておいてほしいのは、`&[T]`はスライス型であって、配列型ではないことです。配列型は`&[T; 10]`のように、要素の型と要素数が入った型になります。`insert()`関数は任意の長さ(`N`とします)の配列を引数に取り、長さ`N + 1`の配列を返しますが、Rustではそのような関数は定義できません。
1
+ 最初に知っておいてほしいのは、`&[T]`はスライス型であって、配列型ではないことです。配列型は`[T; 10]`のように、要素の型と要素数が入った型になります。
2
2
 
3
+ `insert()`関数は任意の長さ(`N`とします)の配列を引数に取り、長さ`N + 1`の配列を返しますが、Rustではそのような関数は定義できません。
4
+
3
5
  ```rust
4
6
  // コンパイルエラーになる
5
7
  fn insert()<T: Ord+Clone>(x: T, v: [T; N]) -> [T; N + 1] {

2

説明を微修正

2018/11/05 02:01

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -57,6 +57,6 @@
57
57
  }
58
58
  ```
59
59
 
60
- なお上の実装では、`insert()`関数が呼ばれるたびに毎回新しいベクタを作るため効率はよくありません。これはもし配列が使えたとしても効率の面では同じです。
60
+ なお上の実装では、`insert()`関数が呼ばれるたびに新しいベクタを作るため効率はよくありません。これはもし配列が使えたとしても効率の面では同じです。
61
61
 
62
- もし`isort()`が引数にとったスライス(`&mut [T]`)をその場で変更してもよいのなら、効率の良い実装もできます。(その場合はかなり違ったプログラムになるので例は割愛します)
62
+ もし`isort()`と`insert()`が引数にとったスライス(`&mut [T]`)をその場で変更してもよいのなら、効率の良い実装もできます。(その場合はかなり違ったプログラムになるので例は割愛します)

1

誤字を修正しました

2018/11/05 01:52

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -5,7 +5,7 @@
5
5
  fn insert()<T: Ord+Clone>(x: T, v: [T; N]) -> [T; N + 1] {
6
6
 
7
7
  // これならコンパイルできるが、引数に長さ1の配列しか取れない
8
- fn insert()<T: Ord+Clone>(x: T, v: [T; 1]) -> [T; 2] {
8
+ fn insert()<T: Ord+Clone>(x: T, v: [T; 1]) -> [T; 2] {
9
9
  ```
10
10
 
11
11
  次にご質問のコードでなぜスライス`&[T]`を返せないかですが、
@@ -23,7 +23,7 @@
23
23
 
24
24
  > また、この問題はVecを使うことで解決することが出来たのですが、出来るだけVecではなく配列を使うべきだという話をよく聞きます。なので、配列ではどのような実装をすれば良いのか教えていただきたいです。
25
25
 
26
- 残念ながら、このプログラムですと配列またはスライスを返すことはできません。
26
+ 残念ながら、このプログラムですと配列またはスライスを返すことはできません。
27
27
 
28
28
  - 最初の理由により、任意の長さの配列を返す関数が書けない
29
29
  - 2番目の理由により、関数内で作った実体を参照するスライスは戻り値として返せない
@@ -57,4 +57,6 @@
57
57
  }
58
58
  ```
59
59
 
60
+ なお上の実装では、`insert()`関数が呼ばれるたびに毎回新しいベクタを作るため効率はよくありません。これはもし配列が使えたとしても効率の面では同じです。
61
+
60
- なお上の実装では、`insert()`関数が呼ばれるたびに毎回新しいベクタを作るため効率はよくありません。これはもし配列が使えたとしても効率の面では同じです。`isort()`が引数にとったスライス(&mut [T]`)をその場で変更してもよいのなら、効率の良い実装も可能です。(その場合はかなり違ったプログラムになるので例は割愛します)
62
+ もし`isort()`が引数にとったスライス(`&mut [T]`)をその場で変更してもよいのなら、効率の良い実装もできます。(その場合はかなり違ったプログラムになるので例は割愛します)