-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[REPL] Add show capability to common types #1761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
5c607cd
Add basic Show capability
felixmulder c619f76
Fix `Option[Nothing]` show
felixmulder 8bb9c84
Make repl use show instances where possible
felixmulder 8b7a7ea
Print List and Map abbreviated
felixmulder a190cfe
Get rid of nesting implicits
felixmulder e4f7b38
Optimize `Show[String]` instance
felixmulder 8a754cf
Get rid of null in evidence param
felixmulder 214258f
Add documentation to `Show`
felixmulder 1594bb0
Fix repl tests
felixmulder d63e971
Fix tasty bootstrap
felixmulder 454f09e
Fix literal type printing
felixmulder 3a11ff7
Use Nil.type and None.type instead of superclasses
felixmulder 35e8fcb
Add comment regarding prettification
felixmulder File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package dotty | ||
|
||
import scala.annotation.implicitNotFound | ||
|
||
@implicitNotFound("No member of type class Show could be found for ${T}") | ||
trait Show[-T] { | ||
def show(t: T): String | ||
} | ||
|
||
/** Ideally show would only contain `defaultShow` and the pimped generic class, | ||
* but since we can't change the current stdlib, we're stuck with providing | ||
* default instances in this object | ||
*/ | ||
object Show { | ||
private[this] val defaultShow: Show[Any] = new Show[Any] { | ||
def show(x: Any) = x.toString | ||
} | ||
|
||
/** This class implements pimping of all types to provide a show method. | ||
* Currently it is quite permissive, if there's no instance of `Show[T]` for | ||
* any `T`, we default to `T#toString`. | ||
*/ | ||
implicit class ShowValue[V](val v: V) extends AnyVal { | ||
def show(implicit ev: Show[V] = defaultShow): String = | ||
ev.show(v) | ||
} | ||
|
||
implicit val stringShow: Show[String] = new Show[String] { | ||
// From 2.12 spec, `charEscapeSeq`: | ||
// ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) | ||
def show(str: String) = | ||
"\"" + { | ||
val sb = new StringBuilder | ||
str.foreach { | ||
case '\b' => sb.append("\\b") | ||
case '\t' => sb.append("\\t") | ||
case '\n' => sb.append("\\n") | ||
case '\f' => sb.append("\\f") | ||
case '\r' => sb.append("\\r") | ||
case '\'' => sb.append("\\'") | ||
case '\"' => sb.append("\\\"") | ||
case c => sb.append(c) | ||
} | ||
sb.toString | ||
} + "\"" | ||
} | ||
|
||
implicit val intShow: Show[Int] = new Show[Int] { | ||
def show(i: Int) = i.toString | ||
} | ||
|
||
implicit val floatShow: Show[Float] = new Show[Float] { | ||
def show(f: Float) = f + "f" | ||
} | ||
|
||
implicit val doubleShow: Show[Double] = new Show[Double] { | ||
def show(d: Double) = d.toString | ||
} | ||
|
||
implicit val charShow: Show[Char] = new Show[Char] { | ||
def show(c: Char) = "'" + (c match { | ||
case '\b' => "\\b" | ||
case '\t' => "\\t" | ||
case '\n' => "\\n" | ||
case '\f' => "\\f" | ||
case '\r' => "\\r" | ||
case '\'' => "\\'" | ||
case '\"' => "\\\"" | ||
case c => c | ||
}) + "'" | ||
} | ||
|
||
implicit def showList[T](implicit st: Show[T]): Show[List[T]] = new Show[List[T]] { | ||
def show(xs: List[T]) = | ||
if (xs.isEmpty) "Nil" | ||
else "List(" + xs.map(_.show).mkString(", ") + ")" | ||
} | ||
|
||
implicit val showNil: Show[List[Nothing]] = new Show[List[Nothing]] { | ||
def show(xs: List[Nothing]) = "Nil" | ||
} | ||
|
||
implicit def showOption[T](implicit st: Show[T]): Show[Option[T]] = new Show[Option[T]] { | ||
def show(ot: Option[T]): String = ot match { | ||
case Some(t) => "Some("+ st.show(t) + ")" | ||
case none => "None" | ||
} | ||
} | ||
|
||
implicit val showNone: Show[Option[Nothing]] = new Show[Option[Nothing]] { | ||
def show(n: Option[Nothing]) = "None" | ||
} | ||
|
||
implicit def showMap[K,V](implicit sk: Show[K], sv: Show[V]): Show[Map[K,V]] = new Show[Map[K,V]] { | ||
def show(m: Map[K, V]) = | ||
"Map(" + m.map { case (k, v) => sk.show(k) + " -> " + sv.show(v) } .mkString (", ") + ")" | ||
} | ||
|
||
implicit def showMapOfNothing: Show[Map[Nothing,Nothing]] = new Show[Map[Nothing,Nothing]] { | ||
def show(m: Map[Nothing, Nothing]) = m.toString | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package dotty | ||
|
||
import org.junit.Test | ||
import org.junit.Assert._ | ||
|
||
class ShowTests { | ||
import Show._ | ||
|
||
@Test def showString = { | ||
assertEquals("\"\\thello world!\"", "\thello world!".show) | ||
assertEquals("\"\\nhello world!\"", "\nhello world!".show) | ||
assertEquals("\"\\rhello world!\"", "\rhello world!".show) | ||
assertEquals("\"\\b\\t\\n\\f\\r\\\'\\\"\"", "\b\t\n\f\r\'\"".show) | ||
} | ||
|
||
@Test def showFloat = { | ||
assertEquals("1.0f", 1.0f.show) | ||
assertEquals("1.0f", 1.0F.show) | ||
} | ||
|
||
@Test def showDouble = { | ||
assertEquals("1.0", 1.0d.show) | ||
assertEquals("1.0", 1.0.show) | ||
} | ||
|
||
@Test def showChar = { | ||
assertEquals("'\\b'", '\b'.show) | ||
assertEquals("'\\t'", '\t'.show) | ||
assertEquals("'\\n'", '\n'.show) | ||
assertEquals("'\\f'", '\f'.show) | ||
assertEquals("'\\r'", '\r'.show) | ||
assertEquals("'\\''", '\''.show) | ||
assertEquals("'\\\"'", '\"'.show) | ||
} | ||
|
||
@Test def showCar = { | ||
case class Car(model: String, manufacturer: String, year: Int) | ||
implicit val showCar = new Show[Car] { | ||
def show(c: Car) = | ||
"Car(" + c.model.show + ", " + c.manufacturer.show + ", " + c.year.show + ")" | ||
} | ||
|
||
case class Shop(xs: List[Car], name: String) | ||
implicit val showShop = new Show[Shop] { | ||
def show(sh: Shop) = | ||
"Shop(" + sh.xs.show + ", " + sh.name.show + ")" | ||
} | ||
|
||
assertEquals("Car(\"Mustang\", \"Ford\", 1967)", Car("Mustang", "Ford", 1967).show) | ||
} | ||
|
||
@Test def showOptions = { | ||
assertEquals("None", None.show) | ||
assertEquals("None", (None: Option[String]).show) | ||
assertEquals("Some(\"hello opt\")", Some("hello opt").show) | ||
} | ||
|
||
@Test def showMaps = { | ||
val mp = scala.collection.immutable.Map("str1" -> "val1", "str2" -> "val2") | ||
assertEquals("Map(\"str1\" -> \"val1\", \"str2\" -> \"val2\")", mp.show) | ||
} | ||
|
||
@Test def withoutShow = { | ||
case class Car(model: String, manufacturer: String, year: Int) | ||
|
||
assertEquals("Car(Mustang,Ford,1967)", Car("Mustang", "Ford", 1967).show) | ||
assertEquals("Map()", Map().show) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you try defining
Show[Nil]
andShow[None]
instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did, but I didn't push it! (=
It actually gives a better representation of list:
instead of printing
Nil
for both.