# Public review of the Standard Library APIs \[Closed\]

**URL:** <https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362>\
**Category:** Libraries\
**Created:** [December 17, 2015, 1:32pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362 "2015-12-17T13:32:41Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![dalewking](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/dalewking/32/1496_2.png) [@dalewking](https://discuss.kotlinlang.org/u/dalewking)\
**Post date:** [December 30, 2015, 5:30pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/45 "2015-12-30T17:30:22Z")

</div>

> [@pniederw1](#):
>
> > [@jack128](#):
> >
> > apply - is sort of “object initializer” from C#.
> 
> I understand (and wonder if `configure` would have been a better name). Just saying that if some of the initialization is factored out into a separate method, `separateMethod(this)` looks a bit odd.

Configure in that case should be an extension function and then the point is moot:

```
myObject.apply { configure() }

```

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [December 30, 2015, 5:45pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/46 "2015-12-30T17:45:27Z")

</div>

> [@dalewking](#):
>
> Configure in that case should be an extension function and then the point is moot:

Technically speaking that’s an option, but I typically only use extension functions for things that I feel “belong” on the type. An “arbitrary” helper method doesn’t.

---

<div class="post-metadata">

**Author:** ![vbezhenar](https://avatars.discourse-cdn.com/v4/letter/v/35a633/32.png) [@vbezhenar](https://discuss.kotlinlang.org/u/vbezhenar)\
**Post date:** [January 2, 2016, 4:24pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/47 "2016-01-02T16:24:11Z")

</div>

I’ve found that working with match results in Regex API is not very nice.

```
val regex = Regex("""(\d+)-(\d+)""")
val str = "123-456"
val match = regex.matchEntire(str)
if (match == null) error("must match")
val g1 = match.groups[1]!!.value

```

First problem is, I have to write `!!` after `match.groups[1]`. I understand that it’s theoretically possible to write regexp, which will return null group. That’s possible result from Java regex API. But in practice I’ve never saw such regex. In my experience, group is always not-null. That’s the first problem. Second problem is that almost always I need only string value from group. So that `!!.value` suffix is just boring syntax noise.

I think that MatchResult class should define

```
public operator fun get(index: Int): String = groups[index]?.value ?: ""

```

now I can write

```
val g1 = match[1]

```

it’s very simple and similar to JavaScript.

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 2, 2016, 5:08pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/48 "2016-01-02T17:08:08Z")

</div>

`null` groups are real:

```nohighlight
  val r = Regex("(a+)|(b+)").matchEntire("bbb")
  if (r != null) {
    println(r.groups[1]) // null
    println(r.groups[2]) // bbb
  }

```

I agree that `r.groups[2]!!.value` doesn’t look great, but is there a better alternative?

---

<div class="post-metadata">

**Author:** ![vbezhenar](https://avatars.discourse-cdn.com/v4/letter/v/35a633/32.png) [@vbezhenar](https://discuss.kotlinlang.org/u/vbezhenar)\
**Post date:** [January 2, 2016, 5:26pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/49 "2016-01-02T17:26:09Z")

</div>

I agree that they are real. But in my experience almost always they can’t be null. So I think that API usage should allow to “by-pass” null checking for those 90% patterns. Of course if one does need nullable groups, API is there, it’s not changing, actually. I’m just suggesting a shorter alternative: `fun get(index: Int): String` defined in `MatchResult` class. Something like shortcut for common use-case.

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 2, 2016, 6:04pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/50 "2016-01-02T18:04:03Z")

</div>

> [@vbezhenar](#):
>
> I’m just suggesting a shorter alternative: fun get(index: Int): String defined in MatchResult class. Something like shortcut for common use-case.

I see, makes sense.

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 3, 2016, 5:14pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/51 "2016-01-03T17:14:00Z")

</div>

**File Readers/Writers**

`File.reader()` should return an `InputStreamReader` rather than a `FileReader`. (`FileReader` just hardcodes default encoding and buffer size, and does not provide any additional methods.) It should allow to specify a `Charset`, which should default to UTF-8.  
If there is a proven need to support `FileReader` as well, a separate `File.fileReader()` method should be introduced.

`File.bufferedReader()` should allow to specify a `Charset`, which should default to UTF-8.

`File.writer()` should return an `OutputStreamWriter` rather than a `FileWriter`. (`FileWriter` just hardcodes default encoding and buffer size, and does not provide any additional methods.) It should allow to specify a `Charset`, which should default to UTF-8.  
If there is a proven need to support `FileWriter` as well, a separate `File.fileWriter()` method should be introduced.

`File.bufferedWriter()` should allow to specify a `Charset`, which should default to UTF-8.

`File.printWriter()` should allow to specify a `Charset`, which should default to UTF-8.

`File` extension method overloads that accept encoding as a `String` rather than a `Charset` seem redundant (use `Charsets` for common cases and `Charset.forName` (or your own abstraction) otherwise), and should be removed.

Asymmetry: `File` has a `readLines` extension method (which produces a `List`), whereas `Reader` has a `useLines` extension method (which produces a `Sequence`).

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [January 4, 2016, 5:43am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/52 "2016-01-04T05:43:05Z")

</div>

> [@krupal](#):
>
> there is a “Java Puzzlers” behaviour in case of file.deleteRecursively()  
> it returns:
> 
> 1. true if can delete smth
> 2. false if can’t delete smth
> 3. and the puzzler → false when there is no such folder structure

We’re going to change the behaviour of `deleteRecursively` and make it return `false` only in case of incomplete (partial) deletion, and `true` in all other cases, such as missing directory being deleted.

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [January 4, 2016, 5:52am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/53 "2016-01-04T05:52:37Z")

</div>

> [@pniederw1](#):
>
> Asymmetry: Extension methods File.reader and File.writer have buffered variants (File.bufferedReader and File.bufferedWriter), whereas File.inputStream and File.outputStream don’t. (file.inputStream().buffered() isn’t bad, but neither is file.reader().buffered().)

We believe that instantiating a buffered char reader from file is more common task than buffered byte reader, so the former deserves to have a shortcut.

> [@pniederw1](#):
>
> Assertion APIs that fail fast (dominant at least on JVM), and assertion APIs that collect errors, should be separated. E.g., when using fail-fast it doesn’t feel right, and causes pain, that kotlin.test.assertFails returns Throwable? rather than Throwable, and that kotlin.test.fail returns Unit rather than Nothing.

I tend to agree, we should make assertions API exhibit the same fail-fast behavior on both platforms.

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [January 4, 2016, 6:02am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/54 "2016-01-04T06:02:37Z")

</div>

> [@pniederw1](#):
>
> Iterable.forEachIndexed: it should be forEachIndexed { elem, idx -\> … } rather than forEachIndexed { idx, elem -\> … }.

This change would be rather disruptive at this moment, does it provide the value that justifies it?  
Also, consider the `foldIndexed`/`reduceIndexed` [PR 796](https://github.com/JetBrains/kotlin/pull/796/files#diff-3ef5a352775b33b5514ec036d3616ec1R381), which we’re going to merge soon, does it feel natural to have index parameter after T in that case?

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 4, 2016, 1:47pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/55 "2016-01-04T13:47:18Z")

</div>

> [@ilya.gorbunov](#):
>
> This change would be rather disruptive at this moment, does it provide the value that justifies it?

I believe the proposed order is more logical, and the current order will take people by surprise. I’ll leave it to you whether you consider this worth fixing at this point. All I can say is that I’d happily adapt my own code, and that IntelliJ would likely do this for me anyways.

> [@ilya.gorbunov](#):
>
> Also, consider the foldIndexed/reduceIndexed PR 796, which we’re going to merge soon, does it feel natural to have index parameter after T in that case?

For any method `foo`, the order used for `coll.fooIndexed` should be consistent with `coll.withIndex().foo`. In my proposal, the order of `IndexedValue` arguments would change, hence `foldRightIndexed` would use `(R, Int, T) -> R`.

PS: For the record, Scala only has `withIndex` (named `zipWithIndex`), to avoid a combinatorial explosion of methods ([mapWithindex | The Scala Programming Language](http://www.scala-lang.org/old/node/1569.html#comment-5189)).

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 4, 2016, 2:29pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/56 "2016-01-04T14:29:38Z")

</div>

Function `kotlin.system.measureTimeNano()` should be named `measureTimeNanos` (or `measureNanoTime`).

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 4, 2016, 2:53pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/57 "2016-01-04T14:53:02Z")

</div>

**File APIs**

From what I can tell, Kotlin adopts the old Java way of reporting errors by returning `null` (e.g. in extension method `File.listFiles`) or `false` (e.g. in extension method `File.deleteRecursively`). This approach seems outdated, with newer File APIs such as those found in Apache Commons, Guava, and JDK 1.7+ generally favoring exceptions, and in some cases offering a “quiet” variant (which could perhaps also be a named parameter).

Implementation note: Not using JDK 1.7+ File APIs when available seems risky, and may degrade experience for users running on these platforms, compared to using JDK File APIs directly (in regard to performance, atomicity, correct symlink handling, etc.).

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [January 6, 2016, 1:23am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/58 "2016-01-06T01:23:42Z")

</div>

> [@andrewoma](#):
>
> Overloaded methods accepting a string Charset

> [@pniederw1](#):
>
> File extension method overloads that accept encoding as a String rather than a Charset seem redundant (use Charsets for common cases and Charset.forName (or your own abstraction) otherwise), and should be removed.

These overloads would be deprecated and removed soon.

> [@andrewoma](#):
>
> Inconsistent naming of block-like structures (block, body, operation, action)

`forEachLine/forEachBlock` would perform an `action` on element, same as `forEach`, and scope functions (`let/run/with/apply` etc) take a `block` and execute it.

> [@andrewoma](#):
>
> References to java.util

We have plans after 1.0 to add some common types from `java.lang` and `java.util` to `kotlin` package as type aliases.

> [@pniederw1](#):
>
> Asymmetry: File has a readLines extension method (which produces a List), whereas Reader has a useLines extension method (which produces a Sequence).

We cannot provide a method which returns a sequence of lines for `File` since it implies keeping stream open until the sequence is consumed and it’s unclear who should close the stream.  
However, we could provide `useLines` for `File` and `readLines` for `Reader`.

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [January 6, 2016, 1:38am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/59 "2016-01-06T01:38:09Z")

</div>

> [@vbezhenar](#):
>
> I’ve found that working with match results in Regex API is not very nice.

I’ve also spotted this inconvenience when going through [advent of code](http://adventofcode.com/).  
To mitigate this issue we’re going to provide a property `MatchResult.groupValues`. It would differ from `groups` in following:

- returns a list of strings. This list is a wrapper around `groups` collection.
- does not include zeroth group value corresponding to the entire match, so that `groupValues[0]` returns the value of the first group in regex.
- if some group was not matched the corresponding value in `groupValues` would be an empty string (“”).

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 6, 2016, 5:10am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/60 "2016-01-06T05:10:47Z")

</div>

> [@ilya.gorbunov](#):
>
> To mitigate this issue we’re going to provide a property MatchResult.groupValues.

Another solution that comes to mind: Do away with nullable groups, make `MatchResult.value` return empty string in case of a non-match (or, perhaps better, throw an exception), and add a boolean method `MatchResult.isMatch`.

> [@ilya.gorbunov](#):
>
> does not include zeroth group value corresponding to the entire match, so that groupValues[0] returns the value of the first group in regex.

So `result.groups[3]!!.value == result.groupValues[2]`? Sounds like asking for trouble to me (very similar looks/names, incompatible indices).

---

<div class="post-metadata">

**Author:** ![Suseika](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/suseika/32/1706_2.png) [@Suseika](https://discuss.kotlinlang.org/u/Suseika)\
**Post date:** [January 7, 2016, 10:12pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/61 "2016-01-07T22:12:23Z")

</div>

I would like an assertion function for equal doubles (the one with additional `tolerance` parameter) to be added to kotlin-test. I have to use JUnit’s Assert.assertEquals instead of Kotlin’s assertions for this. This introduces a bit of inconsistency into tests:

```
// Need to import org.junit.Assert for this
assertEquals(corner.angle, Math.PI/2, 1e-10)

```

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 8, 2016, 1:38am UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/62 "2016-01-08T01:38:11Z")

</div>

Another assertion function I’ve missed is `assertSame`.

---

<div class="post-metadata">

**Author:** ![medium](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/medium/32/10404_2.png) [@medium](https://discuss.kotlinlang.org/u/medium)\
**Post date:** [January 9, 2016, 8:46pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/63 "2016-01-09T20:46:35Z")

</div>

The [`split`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/kotlin.-char-sequence/split.html) method is not as handy as the Java counterpart, which accepts a plain string instead of a compiled Regex or Pattern. The existing `split` methods are especially confusing, because the Java counterpart has the same name and _almost_ same signature.

I suggest to change the signature to `fun split( regex: String, limit: Int = 0)` or to add such a variant.

---

<div class="post-metadata">

**Author:** ![pniederw1](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pniederw1](https://discuss.kotlinlang.org/u/pniederw1)\
**Post date:** [January 9, 2016, 10:35pm UTC](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362/64 "2016-01-09T22:35:09Z")

</div>

Java’s way of having some methods treat strings as plain strings, and other methods treat strings as regular expressions, is an anti-pattern. That’s probably why Kotlin uses distinct types. This clearly expresses the difference in the type system, avoiding bugs and puzzlers like “what’s the difference between `String.replace(CharSequence, CharSequence)` and `String.replaceAll(String, String)`”, which many Java devs get wrong.

[Previous page](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362.md?page=2)

[Next page](https://discuss.kotlinlang.org/t/public-review-of-the-standard-library-apis-closed/1362.md?page=4)
