Skip to content

Commit edf9f3b

Browse files
committed
Merge branch 'align-splitn-with-other-languages' of https://github.com/shepmaster/rfcs into shepmaster-align-splitn-with-other-languages
2 parents 51dd32f + 67978cd commit edf9f3b

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
- Feature Name: n/a
2+
- Start Date: 2015-03-15
3+
- RFC PR:
4+
- Rust Issue:
5+
6+
# Summary
7+
8+
Make the `count` parameter of `SliceExt::splitn`, `StrExt::splitn` and
9+
corresponding reverse variants mean the *maximum number of items
10+
returned*, instead of the *maximum number of times to match the
11+
separator*.
12+
13+
# Motivation
14+
15+
The majority of other languages (see examples below) treat the `count`
16+
parameter as the maximum number of items to return. Rust already has
17+
many things newcomers need to learn, making other things similar can
18+
help adoption.
19+
20+
# Detailed design
21+
22+
Currently `splitn` uses the `count` parameter to decide how many times
23+
the separator should be matched:
24+
25+
```rust
26+
let v: Vec<_> = "a,b,c".splitn(2, ',').collect();
27+
assert_eq!(v, ["a", "b", "c"]);
28+
```
29+
30+
The simplest change we can make is to decrement the count in the
31+
constructor functions. If the count becomes zero, we mark the returned
32+
iterator as `finished`. See **Unresolved questions** for nicer
33+
transition paths.
34+
35+
## Example usage
36+
37+
### Strings
38+
39+
```rust
40+
let input = "a,b,c";
41+
let v: Vec<_> = input.splitn(2, ',').collect();
42+
assert_eq!(v, ["a", "b,c"]);
43+
44+
let v: Vec<_> = input.splitn(1, ',').collect();
45+
assert_eq!(v, ["a,b,c"]);
46+
47+
let v: Vec<_> = input.splitn(0, ',').collect();
48+
assert_eq!(v, []);
49+
```
50+
51+
### Slices
52+
53+
```rust
54+
let input = [1, 0, 2, 0, 3];
55+
let v: Vec<_> = input.splitn(2, |&x| x == 0).collect();
56+
assert_eq!(v, [[1], [2, 0, 3]]);
57+
58+
let v: Vec<_> = input.splitn(1, |&x| x == 0).collect();
59+
assert_eq!(v, [[1, 0, 2, 0, 3]]);
60+
61+
let v: Vec<_> = input.splitn(0, |&x| x == 0).collect();
62+
assert_eq!(v, []);
63+
```
64+
65+
## Languages where `count` is the maximum number of items returned
66+
67+
### C# ###
68+
69+
```c#
70+
"a,b,c".Split(new char[] {','}, 2)
71+
// ["a", "b,c"]
72+
```
73+
74+
### Clojure
75+
76+
```clojure
77+
(clojure.string/split "a,b,c" #"," 2)
78+
;; ["a" "b,c"]
79+
```
80+
81+
### Go
82+
83+
```go
84+
strings.SplitN("a,b,c", ",", 2)
85+
// [a b,c]
86+
```
87+
88+
### Java
89+
90+
```java
91+
"a,b,c".split(",", 2);
92+
// ["a", "b,c"]
93+
```
94+
95+
### Ruby
96+
97+
```ruby
98+
"a,b,c".split(',', 2)
99+
# ["a", "b,c"]
100+
```
101+
102+
### Perl
103+
104+
```perl
105+
split(",", "a,b,c", 2)
106+
# ['a', 'b,c']
107+
```
108+
109+
## Languages where `count` is the maximum number of times the separator will be matched
110+
111+
### Python
112+
113+
```python
114+
"a,b,c".split(',', 2)
115+
# ['a', 'b', 'c']
116+
```
117+
118+
### Swift
119+
120+
```swift
121+
split("a,b,c", { $0 == "," }, maxSplit: 2)
122+
// ["a", "b", "c"]
123+
```
124+
125+
# Drawbacks
126+
127+
Changing the *meaning* of the `count` parameter without changing the
128+
*type* is sure to cause subtle issues. See **Unresolved questions**.
129+
130+
The iterator can only return 2^64 values; previously we could return
131+
2^64 + 1. This could also be considered an upside, as we can now
132+
return an empty iterator.
133+
134+
# Alternatives
135+
136+
1. Keep the status quo. People migrating from many other languages
137+
will continue to be surprised.
138+
139+
2. Add a parallel set of functions that clearly indicate that `count`
140+
is the maximum number of items that can be returned.
141+
142+
# Unresolved questions
143+
144+
Is there a nicer way to change the behavior of `count` such that users
145+
of `splitn` get compile-time errors when migrating?
146+
147+
1. Add a dummy parameter, and mark the methods unstable. Remove the
148+
parameterand re-mark as stable near the end of the beta period.
149+
150+
2. Move the methods from `SliceExt` and `StrExt` to a new trait that
151+
needs to be manually imported. After the transition, move the methods
152+
back and deprecate the trait. This would not break user code that
153+
migrated to the new semantic.

0 commit comments

Comments
 (0)