This page is no longer maintained — Please continue to the home page at www.scala-lang.org

ScalaRunTime.stringOf : Generalization of “def mapInner”

25 replies
Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.

Hi Everybody engaged in ScalaRunTime

I’d been wondering for a long time why REPL-output for instances of
scala.collection.Graph differ from the result of toString on the same
instances. But finally, two days ago, I learned the reason for this
trough the answer to my ticket #4093: the special handling of
Traversable[_] in the scala package by ScalaRunTime.stringOf.

The current output - for example “Graph(3, 2, GraphBase(2, 3))”
instead of “Graph(3, 2, 2~3)” - is not really acceptable so we must
seek a way to achieve the latter in REPL. Basically, we have the
following two alternatives:

1)
Graph should no more be placed in the scala package.

I dislike this alternative because
a) users should not “learn” new package names for real collection
classes like Graph and
b) in case Graph or any other similar new collection member should
move to the library, packages should be shuffled back and forth at
source level.
The only advantage of this alternative is that stringOf may remain
unchanged.

2)
stringOf should be enhanced to cope with “non-standard” collection
element representation.

Currently, only Map is handled in a non-standard way: inner(k) + " ->
" + inner(v). The needs of Graph are similar but of more general
nature: edges, which are collection elements and themselves iterable
at the same time, have methods to determine what kind of brackets and
separators are to be used when printing them. This is the same as if
we defined for Map Entry which brackets (“(“ and “)”) and which
separator (“ -> “) were to be used to represent itself – instead of
defining this formatting in a constant way.

In conclusion, I’d propose to define something like

trait ElementFormatting {
def stringPrefix: String
def leftBracket: Char
def rightBracket: Char
def separator: String
}
and to enhance stringOf to handle this case when calling mkString for
inner elements of traversables – as a generalization of the current
“def mapInner”. Having done so, any collection, even Map, could have
elements mixing in this trait and stringOf need not handle special
cases like Map or Graph any more.

Please vote…

Cheers
Peter

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On 4/3/11 4:00 AM, Peter wrote:
> 1)
> Graph should no more be placed in the scala package.

Is there a mailing list I'm not on? Either I'm too much in the dark
(always a possibility) or you're assuming a lot.

> The only advantage of this alternative is that stringOf may remain
> unchanged.

Strawman convincingly slain. But my advice is still to move it out of
the scala package, because it isn't in it yet. And the standard library
needs to be getting smaller, not bigger. (And I have to get out from
under these policy bottlenecks. Did you know that it only exists
because of Array? True story!)

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

> > 1)
> > Graph should no more be placed in the scala package.
>
> Is there a mailing list I'm not on? Either I'm too much in the dark
> (always a possibility) or you're assuming a lot.

I don't think you are too much in the dark. I sure could have
referenced the discussion topic "Graph for Scala 2.9.0?" where Martin
told that Graph could go to the planned "extended core library".

> > The only advantage of this alternative is that stringOf may remain
> > unchanged.
>
> Strawman convincingly slain.  But my advice is still to move it out of
> the scala package, because it isn't in it yet.  And the standard library
> needs to be getting smaller, not bigger.  (And I have to get out from
> under these policy bottlenecks.  Did you know that it only exists
> because of Array? True story!)

To me it's not clear that using the package path "scala.collection"
must also mean that all members are in the standard library. Does this
constraint really exist? Anyway, I've asked the reader to inspect the
package structure of Graph in the above discussion, but got no
suggestions to this point - probably everybody felt is was too early
to dig into such a detail before Graph is officially out.

Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

> I don't think you are too much in the dark. I sure could have
> referenced the discussion topic "Graph for Scala 2.9.0?" where Martin
> told that Graph could go to the planned "extended core library".

Yes, but that doesn't mean that it will be in the scala package. In fact, it almost certainly will be in some other package name, to make it clear it's in the extended library. At least, that was my interpretation if his statement, which might be incorrect.

Donna

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On 3 Apr., 15:06, Donna Malayeri wrote:
> > I don't think you are too much in the dark. I sure could have
> > referenced  the discussion topic "Graph for Scala 2.9.0?" where Martin
> > told that Graph could go to the planned "extended core library".
>
> Yes, but that doesn't mean that it will be in the scala package. In fact, it almost certainly will be in some other package name, to make it clear it's in the extended library. At least, that was my interpretation if his statement, which might be incorrect.
>
> Donna

So I'am looking forward to be informed what package path I should use
for Graph.

Thanks a lot,
Peter

spoon
Joined: 2008-07-01,
User offline. Last seen 1 year 21 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On Sun, Apr 3, 2011 at 7:00 AM, Peter wrote:
> The current output - for example “Graph(3, 2, GraphBase(2, 3))”
> instead of “Graph(3, 2, 2~3)” - is not really acceptable so we must
> seek a way to achieve the latter in REPL. Basically, we have the
> following two alternatives:

The REPL's special treatment of arrays is understandable but horrible.
It would be good to keep it contained instead of letting it sprout
ever more smarts.

Instead of trying to generalize the centralized stringOf to understand
all collections, wouldn't the following two things work:

1. The special stringOf method only checks for arrays. For anything
else, it calls toString.

2. Collection classes use stringOf instead of toString when printing
their elements.

Item 2 means that stringOf needs to be publicly available somewhere
rather than buried in the interpreter.

-Lex

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On 4/4/11 11:42 AM, Lex Spoon wrote:
> The REPL's special treatment of arrays is understandable but horrible.
> It would be good to keep it contained instead of letting it sprout
> ever more smarts.

Yes, this is exactly why I resist anything to do with graph appearing in
there. But keeping it contained is only the sensible answer inasmuch as
we continue to inflict toString on ourselves as the official way to
print things. As long as we do that, we can't fix null.toString and we
can't fix Array(1).toString. If we chose something else (which would
fall back on toString if it was not defined) then all these problems go
away. We can do the null check the same way we do for == before calling
equals, and we can have an implicit conversion from Array => { def
betterToString: String }.

> 1. The special stringOf method only checks for arrays. For anything
> else, it calls toString.
>
> 2. Collection classes use stringOf instead of toString when printing
> their elements.

It is not limited to the collections.

scala> (Array(1), List(1))
res0: (Array[Int], List[Int]) = (Array(1),List(1))

It is anything which contains arbitrary elements which it is likely to
print in its representation. I still don't have them all, I notice.

scala> new scala.xml.Atom(Array(1,2))
res1: scala.xml.Atom[Array[Int]] = [I@79bf3519

So I should properly be duplicating the case class toString method as well.

But it would be a lot easier and more futureproof if we would just
define a better toString method.

This would actually close the circle on the three abstract methods in
"Any": equals, hashCode, and toString. We have now had to create
wrappers for 2/3 of those, and thanks to a last minute assist from
someone in trac, ## does the null check like == does. So let's define a
null-safe @@ or whatever and drink in the beautiful symmetry.

> Item 2 means that stringOf needs to be publicly available somewhere
> rather than buried in the interpreter.

Clearly an argument for letting the stringify logic go with the relevant
class rather than trying to centralize it.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On 4/4/11 11:42 AM, Lex Spoon wrote:
> Item 2 means that stringOf needs to be publicly available somewhere
> rather than buried in the interpreter.

By the way, it is: it's scala.runtime.ScalaRunTime.stringOf. It's just
not official API.

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

Hi Paul, hi Lex,

>   1. The special stringOf method only checks for arrays. For anything
> else, it calls toString.

>   2. Collection classes use stringOf instead of toString when printing
> their elements.
>
from my point of view:

toString should stringify the whole object even if it's huge - maybe
the caller wants to do something special with it, not just send it to
the console.

stringOf is helpful to cut the output in REPL to a maximum length and
doing other stuff...

So both have their value.

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner


On Mon, Apr 4, 2011 at 10:22 PM, Peter <peter.empen@arcor.de> wrote:
Hi Paul, hi Lex,

>   1. The special stringOf method only checks for arrays. For anything
> else, it calls toString.

>   2. Collection classes use stringOf instead of toString when printing
> their elements.
>
 from my point of view:

toString should stringify the whole object even if it's huge - maybe
the caller wants to do something special with it, not just send it to
the console.

stringOf is helpful to cut the output in REPL to a maximum length and
doing other stuff...

So both have their value.

Yes, that makes sense. -- Martin

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”
How about changing the type signature from
def stringOf(arg: Any): String
to
def stringOf[T: REPLString](arg: T): String
Where
trait REPLString[-T] {  def stringRepr(v: T): String}
Seems to me it would be able to handle neatly the present needs and enable anyone to easily provide REPL representations. Hell, even override them inside a session.
On Mon, Apr 4, 2011 at 16:36, Paul Phillips <paulp@improving.org> wrote:
On 4/4/11 11:42 AM, Lex Spoon wrote:
The REPL's special treatment of arrays is understandable but horrible.
It would be good to keep it contained instead of letting it sprout
ever more smarts.

Yes, this is exactly why I resist anything to do with graph appearing in there.  But keeping it contained is only the sensible answer inasmuch as we continue to inflict toString on ourselves as the official way to print things.  As long as we do that, we can't fix null.toString and we can't fix Array(1).toString.  If we chose something else (which would fall back on toString if it was not defined) then all these problems go away.  We can do the null check the same way we do for == before calling equals, and we can have an implicit conversion from Array => { def betterToString: String }.

  1. The special stringOf method only checks for arrays. For anything
else, it calls toString.

  2. Collection classes use stringOf instead of toString when printing
their elements.

It is not limited to the collections.

scala> (Array(1), List(1))
res0: (Array[Int], List[Int]) = (Array(1),List(1))

It is anything which contains arbitrary elements which it is likely to print in its representation.  I still don't have them all, I notice.

scala> new scala.xml.Atom(Array(1,2))
res1: scala.xml.Atom[Array[Int]] = [I@79bf3519

So I should properly be duplicating the case class toString method as well.

But it would be a lot easier and more futureproof if we would just define a better toString method.

This would actually close the circle on the three abstract methods in "Any": equals, hashCode, and toString.  We have now had to create wrappers for 2/3 of those, and thanks to a last minute assist from someone in trac, ## does the null check like == does.  So let's define a null-safe @@ or whatever and drink in the beautiful symmetry.

Item 2 means that stringOf needs to be publicly available somewhere
rather than buried in the interpreter.

Clearly an argument for letting the stringify logic go with the relevant class rather than trying to centralize it.




--
Daniel C. Sobral

I travel to the future all the time.
spoon
Joined: 2008-07-01,
User offline. Last seen 1 year 21 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On Mon, Apr 4, 2011 at 3:36 PM, Paul Phillips wrote:
> On 4/4/11 11:42 AM, Lex Spoon wrote:
>>   1. The special stringOf method only checks for arrays. For anything
>> else, it calls toString.
>>
>>   2. Collection classes use stringOf instead of toString when printing
>> their elements.
>
> It is not limited to the collections.

Absolutely. I wrote "collections" because that was the motivating
example on the thread. Really, anything that recursively prints
sub-structure should use this alternate method rather than toString.
That would include: the generated toString methods in case classes,
the mkString helper, and the + operator when it's producing a string.

> So let's define a null-safe @@ or whatever and drink in the beautiful symmetry.

SGTM. Note that this can be a final method. For everything except
arrays, it is of marginal value to have toString and @@ do different
things.

Lex

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

Please help me, I cannot remedy this flaw on my own!

This change request is really not intended to make things in stringOf
more complicated but to lift a specific treatment of Map to a generic
feature. Moreover, it would be desirable for REPL not to indirectly
impose restrictions on package name usage.

I’d really very much appreciate if you supported to extend stringOf to
be more flexible in 2.9.0 (or @Donna @martin gave an ultimate
statement of a package name to be used by Graph if other than
scala.collection). Otherwise this issue could evolve to a real show-
stopper.

Is the way Daniel / Lex have proposed not practicable? Tell me if you
simply don’t have time and feel you could benefit from a code
proposal.

Good news is that scalaists are picking up scala.collection.Graph even
though not yet officially announced. One of them wrote: “First of all,
thanks for scala-graph, it has helped me write some amazingly
expressive code so far. As I'm migrating some of it towards
production…”.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

On Sun, Apr 24, 2011 at 05:23, Peter wrote:
> Please help me, I cannot remedy this flaw on my own!
>
> Is the way Daniel / Lex have proposed not practicable? Tell me if you
> simply don’t have time and feel you could benefit from a code
> proposal.

No, my way is not practical. A repl test case showed why:

scala> val l: Any = Array(1, 2, 3)
l: Any = Array(1, 2, 3)

The use of implicits, as I suggested, relies on the static type. In
the case above, where the static type is Any, it would have to fall
back to ".toString". Maybe the idea can still be used in a more
limited form, but, obviously, it falls on whoever is suggesting to
provide an implementation.

> Good news is that scalaists are picking up scala.collection.Graph even
> though not yet officially announced. One of them wrote: “First of all,
> thanks for scala-graph, it has helped me write some amazingly
> expressive code so far. As I'm migrating some of it towards
> production…”.

Good to know. Very good to know. Have you announced it through
implicit.ly, by the way? I find that's the best resource to get the
word around.

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

Hi Daniel,

> The use of implicits, as I suggested, relies on the static type. In
> the case above, where the static type is Any, it would have to fall
> back to ".toString". Maybe the idea can still be used in a more
> limited form, but, obviously, it falls on whoever is suggesting to
> provide an implementation.

I think
case x: Traversable[_]
could be extended by a "sub-match" for "inner": if inner supported a
given trait, that custom format could be output instead of
(x.stringPrefix + "(", ", ", ")").

> Good to know. Very good to know. Have you announced it through
> implicit.ly, by the way? I find that's the best resource to get the
> word around.

For many users REPL is the medium they get their first impression
evaluating new functionality.
So I'am actually withholding any announcment until this flow is
resolved. I'd be very much ashamed of the current REPL output indeed.
But I expect to follow every advice of you later.

Ittay Dror 2
Joined: 2010-05-05,
User offline. Last seen 42 years 45 weeks ago.
השב: Re: Re: ScalaRunTime.stringOf : Generalization of “def map


בתאריך יום ראשון, 24 באפריל 2011 20:31:23 UTC+3, מאת Daniel Sobral:
On Sun, Apr 24, 2011 at 05:23, Peter <peter...@arcor.de> wrote:
> Please help me, I cannot remedy this flaw on my own!
>
> Is the way Daniel / Lex have proposed not practicable? Tell me if you
> simply don’t have time and feel you could benefit from a code
> proposal.

No, my way is not practical. A repl test case showed why:

scala> val l: Any = Array(1, 2, 3)
l: Any = Array(1, 2, 3)

The use of implicits, as I suggested, relies on the static type. In
the case above, where the static type is Any, it would have to fall
back to ".toString". Maybe the idea can still be used in a more
limited form, but, obviously, it falls on whoever is suggesting to
provide an implementation.


Maybe create a runtime mechanism for this?

Given a value a, the REPL  takes a.getClass and tries to find a companion object by adding '$'. If the companion has a method displayString (or more generally, a value of type DisplayString[a.getClass]), then it is used to print a. Otherwise, The default of ScalaRunTime.stringOf is used.

Ittay

> Good news is that scalaists are picking up scala.collection.Graph even
> though not yet officially announced. One of them wrote: “First of all,
> thanks for scala-graph, it has helped me write some amazingly
> expressive code so far. As I'm migrating some of it towards
> production…”.

Good to know. Very good to know. Have you announced it through
implicit.ly, by the way? I find that's the best resource to get the
word around.

--
Daniel C. Sobral

I travel to the future all the time.

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: השב: Re: Re: ScalaRunTime.stringOf : Generalization of “def

Hello again,

the following works for "object ScalaRunTime" and could be considered
for inclusion because it allows any collection (in or outside of
scala.x) to take care of REPL formatting:

1) import TraversableLike
2) Insert into "object ScalaRunTime":

trait StringFormatter {
def stringPrefix = "" // already present in TraversableLike
def stringBracketLeft = "(" // currently hard-coded
def stringBracketRight = ")" // do.
def stringSeparator = ", " // do.
}
final object DefaultStringFormatter extends StringFormatter

3) insert into "def stringOf":

final class TraversableLikeStringFormatter(override val
stringPrefix: String) extends StringFormatter
def format(t: TraversableOnce[String], x: AnyRef) = {
def mkString(f: StringFormatter) =
t mkString (f.stringPrefix + f.stringBracketLeft,
f.stringSeparator,
f.stringBracketRight)
val formatter = x match {
case f :StringFormatter => f
case t: TraversableLike[_,_] => new
TraversableLikeStringFormatter(t.stringPrefix)
case _ => DefaultStringFormatter
}
mkString(formatter)
}

4) Change in "def inner":

case x: Traversable[_] => x take maxElements map inner
mkString (x.stringPrefix + "(", ", ", ")")
case x: Product if isTuple(x) => x.productIterator map inner
mkString ("(", ",", ")")
to
case x: Traversable[_] => format (x take maxElements map
inner, x)
case x: Product if isTuple(x) => format (x.productIterator map
inner, x)

5) Remove "def isScalaClass" and change in "def useOwnToString"
because "trait StringFormatter" allows now custom REPL formatting:

case x: Traversable[_] => !x.hasDefiniteSize || !isScalaClass(x)
to
case x: Traversable[_] => !x.hasDefiniteSize

Hope to have helped a bit with this...?

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

On 4/4/11 4:03 PM, Lex Spoon wrote:
>> So let's define a null-safe @@ or whatever and drink in the beautiful symmetry.
>
> SGTM. Note that this can be a final method. For everything except
> arrays, it is of marginal value to have toString and @@ do different
> things.

It would definitely be final, just like its compatriots-to-be == and ##.

Any_== = newMethod(AnyClass, nme.EQ, anyparam, booltype) setFlag FINAL
Any_!= = newMethod(AnyClass, nme.NE, anyparam, booltype) setFlag FINAL
Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype) setFlag FINAL

I opened a ticket.

https://lampsvn.epfl.ch/trac/scala/ticket/4546

(I jumped to the conclusion that SGTM means "sounds good to me" and not "stupid, go to moon!" or any other less endorsy interpretation.)

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

>  https://lampsvn.epfl.ch/trac/scala/ticket/4546

Thanks for getting back to this issue, Paul. Just because it's not
quite obvious to me, could you please summarize / clarify the future
impact of the above step for
a) repl users and
b) collection (or any other class) designers?

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

On 5/7/11 1:51 AM, Peter Empen wrote:
> Thanks for getting back to this issue, Paul. Just because it's not
> quite obvious to me, could you please summarize / clarify the future
> impact of the above step for
> a) repl users and
> b) collection (or any other class) designers?

If we did it, the impact would be:

ScalaRunTime.stringOf would vanish
we'd print things by calling x.@@ or whatever it would be called.

You, collection writer, receive the call to @@. Do whatever you want
with it.

Repl users would presumably notice none of this.

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: ScalaRunTime.stringOf : Generalization of “def mapInner”

> If we did it, the impact would be:
>
>   ScalaRunTime.stringOf would vanish
>   we'd print things by calling x.@@ or whatever it would be called.
>
> You, collection writer, receive the call to @@.  Do whatever you want
> with it.

How this will work if you plan @@ to be final?

>
> Repl users would presumably notice none of this.

All in all, that would be great!

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

On 5/7/11 3:03 AM, Peter Empen wrote:
>> You, collection writer, receive the call to @@. Do whatever you want
>> with it.
>
> How this will work if you plan @@ to be final?

All it does is call toString, unless you are an Array (which you will
not be, I wager) or null (also not you.)

Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

While we are discussing the use of type classes for implementing ==
would it make sense to use them for the toString replacement, too?

If I'm not mistaken Haskell uses the Show type class for this, isn't it?

Regards,
Rüdiger

2011/5/7 Paul Phillips :
> On 5/7/11 3:03 AM, Peter Empen wrote:
>>> You, collection writer, receive the call to @@.  Do whatever you want
>>> with it.
>>
>> How this will work if you plan @@ to be final?
>
> All it does is call toString, unless you are an Array (which you will
> not be, I wager) or null (also not you.)
>

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

On 5/7/11 10:19 AM, Rüdiger Keller wrote:
> While we are discussing the use of type classes for implementing ==
> would it make sense to use them for the toString replacement, too?

Yes. I proposed #4546 in a manner symmetric with == and ## as presently
implemented in the belief it would have the lowest barrier to entry. If
we were going to escape into a typier world with those it'd be nice to
do so here as well.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

On Sat, May 7, 2011 at 12:48, Paul Phillips wrote:
> On 5/7/11 3:03 AM, Peter Empen wrote:
>>> You, collection writer, receive the call to @@.  Do whatever you want
>>> with it.
>>
>> How this will work if you plan @@ to be final?
>
> All it does is call toString, unless you are an Array (which you will
> not be, I wager) or null (also not you.)

So all collections would have their toString methods modified to call
@@ instead of toString on its elements? And, presumably, anyone who
wants their "toString" to look nice?

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: ScalaRunTime.stringOf : Generalization of “def mapInner

On 5/7/11 7:19 PM, Daniel Sobral wrote:
> So all collections would have their toString methods modified to call
> @@ instead of toString on its elements? And, presumably, anyone who
> wants their "toString" to look nice?

Yes to the first question, just as everything calls .## now instead of
hashCode. (And == instead of equals.) And yes, anyone who prefers not
running into NPEs and not seeing Array-squiggle in their string
representations would also use it.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland