- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
2.8 collections again: StringBuilder.dropRight and String.dropRight
Thu, 2010-07-01, 09:27
I've just spent several hours hunting down a bug which was ultimately caused by the following:
String.dropRight (inherited from IterableLike/IndexedSeqOptimized via StringOps) returns a String
StringBuilder.dropRight (also inherited from IterableLike/IndexedSeqOptimized) returns an IndexedSeq[Char]
Which means that:
scala> val sb = new StringBuilder sb: StringBuilder = StringBuilder()
scala> sb ++= "Hello World" res0: sb.type = StringBuilder(H, e, l, l, o, , W, o, r, l, d)
scala> sb.dropRight(1).toString res3: String = ArrayBuffer(H, e, l, l, o, , W, o, r, l)
scala> sb.toString.dropRight(1) res4: String = Hello Worl
Hmmm - I can't help but feel that this sort of thing (2.8 collections API) is going to provide similarly unpleasant surprises to peeps for some time to come. The precise issue in this instance is presumably that StringBuilder does not extend StringLike (extending IndexedSeqOptimized[Char,Repr]) and that it specifies that it is an indexed seq:
class StringBuilder .... with IndexedSeqOptimized[Char, IndexedSeq[Char]]
What is the rationale behind the decision that StringBuilder does not inherit from StringLike[StringBuilder]?
Chris
Get a new e-mail account with Hotmail - Free. Sign-up now.
String.dropRight (inherited from IterableLike/IndexedSeqOptimized via StringOps) returns a String
StringBuilder.dropRight (also inherited from IterableLike/IndexedSeqOptimized) returns an IndexedSeq[Char]
Which means that:
scala> val sb = new StringBuilder sb: StringBuilder = StringBuilder()
scala> sb ++= "Hello World" res0: sb.type = StringBuilder(H, e, l, l, o, , W, o, r, l, d)
scala> sb.dropRight(1).toString res3: String = ArrayBuffer(H, e, l, l, o, , W, o, r, l)
scala> sb.toString.dropRight(1) res4: String = Hello Worl
Hmmm - I can't help but feel that this sort of thing (2.8 collections API) is going to provide similarly unpleasant surprises to peeps for some time to come. The precise issue in this instance is presumably that StringBuilder does not extend StringLike (extending IndexedSeqOptimized[Char,Repr]) and that it specifies that it is an indexed seq:
class StringBuilder .... with IndexedSeqOptimized[Char, IndexedSeq[Char]]
What is the rationale behind the decision that StringBuilder does not inherit from StringLike[StringBuilder]?
Chris
Get a new e-mail account with Hotmail - Free. Sign-up now.
Thu, 2010-07-01, 21:57
#2
Re: 2.8 collections again: StringBuilder.dropRight and String.
On Thu, Jul 1, 2010 at 10:17 PM, Paul Phillips wrote:
> On Thu, Jul 01, 2010 at 08:27:07AM +0000, christopher marshall wrote:
>> Hmmm - I can't help but feel that this sort of thing (2.8 collections
>> API) is going to provide similarly unpleasant surprises to peeps for
>> some time to come. The precise issue in this instance is presumably
>> that StringBuilder does not extend StringLike (extending
>> IndexedSeqOptimized[Char,Repr]) and that it specifies that it is an
>> indexed seq:
>
> That is not necessarily how I would characterize the issue. toString is
> a coarse, unreliable, and all around terrible solution when it comes to
> turning things into Strings if correctness rides on the result. If you
> didn't know that, now you do. There are many ways for it to surprise
> even under the best of circumstances, and these aren't those.
>
> I think the only legit use of toString is debugging.
>
> scala> "Hello world" dropRight 1 mkString
> res0: String = Hello worl
>
> scala> (new StringBuilder ++= "Hello world") dropRight 1 mkString
> res1: String = Hello worl
>
> Looks good to me. And mkString calls toString in StringLike, so it's
> not even particularly inefficient.
>
But what that amounts to saying is that the user should not care what
the returned type is, as long as mkString works. I don't think it
works this way. Users do care. And that means StringBuilder should be
better integrated in the colleltions hierarchy.
Cheers
Thu, 2010-07-01, 22:17
#3
Re: 2.8 collections again: StringBuilder.dropRight and String.d
On Thu, Jul 01, 2010 at 10:40:33PM +0200, martin odersky wrote:
> But what that amounts to saying is that the user should not care what
> the returned type is, as long as mkString works. I don't think it
> works this way. Users do care. And that means StringBuilder should be
> better integrated in the colleltions hierarchy.
I have no problem giving StringBuilder some more parents or otherwise
kicking it around (naturally not, I practically rewrote it between rc6
and rc7! Clearly I live to change it!) but I stand by the idea that
there will always be corner cases with toString and we will never be
able to make good guarantees about it.
There's simply no way to robustly deal with these methods which exist on
java.lang.Object (yes equals, I'm talking to you too) in a world where a
very small change at the source level can ripple through type inference
until some expression not only has a different type, but originates from
a different library written by a different author in a different source
language and probably using vi instead of emacs. If you use toString
you (generic you) abandon all type safety: that's your privilege, but
you have to lower the expectations once you've leapt off the boat.
And I will interpret your email as endorsing a StringLike parent unless
you indicate otherwise.
Fri, 2010-07-02, 08:37
#4
RE: 2.8 collections again: StringBuilder.dropRight and String.d
> Date: Thu, 1 Jul 2010 13:17:00 -0700
> From: paulp [at] improving [dot] org
> To: oxbow_lakes [at] hotmail [dot] com
> toString is a coarse, unreliable, and all around terrible solution when it comes to
> turning things into Strings if correctness rides on the result. If you
> didn't know that, now you do.
*Desperately looks to find that statement in documentation*.StringBuilder's toString says:
"Returns a new String representing the data in this sequence."
So it does not seem unreasonable (especially coming from a Java background) to use it in this case. This issue is not (IMHO) with toString, it is with the fact that StringBuilder is not a StringLike[StringBuilder]. Perhaps there is a convincing case that this is not so (mutability, perhaps?).
But thanks for the pointer - I'll use mkString (which is ugly, again IMHO) as idiomatic scala from now on
Get a new e-mail account with Hotmail - Free. Sign-up now.
> From: paulp [at] improving [dot] org
> To: oxbow_lakes [at] hotmail [dot] com
> toString is a coarse, unreliable, and all around terrible solution when it comes to
> turning things into Strings if correctness rides on the result. If you
> didn't know that, now you do.
*Desperately looks to find that statement in documentation*.StringBuilder's toString says:
"Returns a new String representing the data in this sequence."
So it does not seem unreasonable (especially coming from a Java background) to use it in this case. This issue is not (IMHO) with toString, it is with the fact that StringBuilder is not a StringLike[StringBuilder]. Perhaps there is a convincing case that this is not so (mutability, perhaps?).
But thanks for the pointer - I'll use mkString (which is ugly, again IMHO) as idiomatic scala from now on
Get a new e-mail account with Hotmail - Free. Sign-up now.
Fri, 2010-07-02, 17:27
#5
Re: 2.8 collections again: StringBuilder.dropRight and String.
Err, what? I thought the problem was that the toString method was being applied to the result of drop, which is clearly documented as being IndexedSeq[Char], as unhelpful as that may be.
On Fri, Jul 2, 2010 at 4:27 AM, christopher marshall <oxbow_lakes [at] hotmail [dot] com> wrote:
--
Daniel C. Sobral
I travel to the future all the time.
On Fri, Jul 2, 2010 at 4:27 AM, christopher marshall <oxbow_lakes [at] hotmail [dot] com> wrote:
> Date: Thu, 1 Jul 2010 13:17:00 -0700
> From: paulp [at] improving [dot] org
> To: oxbow_lakes [at] hotmail [dot] com
> toString is a coarse, unreliable, and all around terrible solution when it comes to
> turning things into Strings if correctness rides on the result. If you
> didn't know that, now you do.
*Desperately looks to find that statement in documentation*.StringBuilder's toString says:
"Returns a new String representing the data in this sequence."
So it does not seem unreasonable (especially coming from a Java background) to use it in this case. This issue is not (IMHO) with toString, it is with the fact that StringBuilder is not a StringLike[StringBuilder]. Perhaps there is a convincing case that this is not so (mutability, perhaps?).
But thanks for the pointer - I'll use mkString (which is ugly, again IMHO) as idiomatic scala from now on
Get a new e-mail account with Hotmail - Free. Sign-up now.
--
Daniel C. Sobral
I travel to the future all the time.
On Thu, Jul 01, 2010 at 08:27:07AM +0000, christopher marshall wrote:
> Hmmm - I can't help but feel that this sort of thing (2.8 collections
> API) is going to provide similarly unpleasant surprises to peeps for
> some time to come. The precise issue in this instance is presumably
> that StringBuilder does not extend StringLike (extending
> IndexedSeqOptimized[Char,Repr]) and that it specifies that it is an
> indexed seq:
That is not necessarily how I would characterize the issue. toString is
a coarse, unreliable, and all around terrible solution when it comes to
turning things into Strings if correctness rides on the result. If you
didn't know that, now you do. There are many ways for it to surprise
even under the best of circumstances, and these aren't those.
I think the only legit use of toString is debugging.
scala> "Hello world" dropRight 1 mkString
res0: String = Hello worl
scala> (new StringBuilder ++= "Hello world") dropRight 1 mkString
res1: String = Hello worl
Looks good to me. And mkString calls toString in StringLike, so it's
not even particularly inefficient.