scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Scaladoc comment for List#dropWhile can be more clear #12045

Closed tjsyangxuelong closed 1 year ago

tjsyangxuelong commented 4 years ago

使用的版本scala2.11.12 问题描述:在使用List.dropWhile()方法从原List中删除元素时,出现了删除不掉的问题,源码中没有注释描述,后发现只能从index(0)开始删除,如果要删除的元素不从index(0)开始,是无法删除的。

eed3si9n commented 4 years ago

Thanks for the report. I'm going to try to unpack this with the help of Google translate.

I am trying to understand this in terms of steps, problem, and expectation.

steps

scala> List(100, 1, 2, 3).dropWhile(_ < 10)

problem

scala> List(100, 1, 2, 3).dropWhile(_ < 10)
res0: List[Int] = List(100, 1, 2, 3)

Are you saying that it's surprising that it did not drop 1, 2, and 3 because the first element at index(0) failed; and this behavior is not adequately explained in the following Scaladoc comment?

Scala_Standard_Library_2_13_2_-_scala_collection_immutable_List

expectation

I am guessing that your expectation is that Scaladoc clearly explain the "longest prefix of elements" means it starts from the 0-th element.

eed3si9n commented 4 years ago

目前我不确定是我使用的不正确,还是版本的bug

For List("a","b","c").dropWhile(_=="b"), List("a","b","c") is correct. This not a bug in Scala or any versions. So in your words, you are using it incorrectly (您使用不正确).

tjsyangxuelong commented 4 years ago

能否请给出一个明确的解释? 我不太明白为什么做这样的设定? 从字面意思看“dropWhile”理解为循环删除,为何第一个元素失败,就要导致整个操作的失败呢? 这样设定的考虑是什么呢?

------------------ 原始邮件 ------------------ 发件人: "eugene yokota"<notifications@github.com>; 发送时间: 2020年6月19日(星期五) 中午12:30 收件人: "scala/bug"<bug@noreply.github.com>; 抄送: "大米老虎"<tjs_yangxuelong@qq.com>;"Author"<author@noreply.github.com>; 主题: Re: [scala/bug] Scaladoc comment for List#dropWhite can be more clear (#12045)

目前我不确定是我使用的不正确,还是版本的bug

For List("a","b","c").dropWhile(_=="b"), List("a","b","c") is correct. This not a bug in Scala or any versions. So in your words, you are using it incorrectly (您使用不正确).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

eed3si9n commented 4 years ago

Here's how I think about dropping while some condition is true.

scala> {
     |   var xs = List("a", "b", "c")
     |   while (xs.nonEmpty && xs.head == "b") {
     |     xs = xs.drop(1)
     |   }
     |   xs
     | }
res0: List[String] = List(a, b, c)
dwijnand commented 4 years ago

That's filter:

scala> List("a","b","c").filter(el => el != "b")
val res0: List[String] = List(a, c)

scala> for (el <- List("a","b","c") if el != "b") yield el
val res1: List[String] = List(a, c)

It took me a long time before I started remembering if filter means "filter-in" or "filter-out" (it's filter-in) and probably would've preferred takeIf and dropIf. But I feel the "while" in dropWhile is a good indicator that something, the dropping, will finish at some point.

Unfortunately, Scala's too big of a language and dropWhile is too well established by now to change its semantics.

I am guessing that your expectation is that Scaladoc clearly explain the "longest prefix of elements" means it starts from the 0-th element.

Sounds like a good improvement.

mariogalic commented 4 years ago

It took me a long time before I started remembering if filter means "filter-in" or "filter-out" (it's filter-in)

Same here. I always incorrectly think filter means filter-out. Maybe providing filterOut as synonym for filterNot would help clarify filter does not mean filter-out.

dwijnand commented 4 years ago

Runar fixed that for me:

Think of filter as flatMap where true is pure/unit/return and false is mempty/nothing.

https://twitter.com/runarorama/status/1187785271749890048

som-snytt commented 4 years ago

I don't see the misunderstanding, but I see the sneaker as pink and the dress as gold. Java's Stream.dropWhile adds:

If this stream is ordered then the longest prefix is a contiguous sequence of elements of this stream that match the given predicate. The first element of the sequence is the first element of this stream, and the element immediately following the last element of the sequence does not match the given predicate.

cull is the term for partition(p)._1.

It's a useful word, meaning "collect", because it can mean either selection for undesirable properties, as applied to livestock, or the opposite, as applied to literature.

filter is a misnomer because it means "filter out": a filtrum made of felt removes impurities from a medicine. Or we say "filtered water". Or "coffee" to mean the brown liquid and not the used grounds.

sieve may imply we're interested in the larger particles? or Eratosthenes' primes. But we sift flour or garden soil to remove them.

nogurenn commented 4 years ago

Would providing a quick reference to filterNot do?

Drops longest prefix of elements that satisfy a predicate.

To remove all possible elements in a collection `xs` that
satisfy the predicate `p`, use `xs.filterNot` instead.

That amount of additional space is also enough for an example instead.

Drops longest prefix of elements that satisfy a predicate.

Example:
{{{
    List(1, 2, 3, 100, 4).dropWhile(_ < 10) == List(100, 4)
}}}

Also, does amending a method doc mean every other method of the same name needs to be changed as well? I found some of them, and maybe a couple of dropWhile not having docs at all.

som-snytt commented 1 year ago

I took the suggestions, and added that partition is (filter, filterNot) which is (in, out). The mnemonic for that is In'n'Out.