Skip to content
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

Introduce ReplPrinter as a hook for alternatives to replStringOf #5222

Closed
wants to merge 4 commits into from

Conversation

dwijnand
Copy link
Member

@dwijnand dwijnand commented Jun 9, 2016

Requires making the imports available during the eval phase of the REPL.

Review by @retronym.

@scala-jenkins scala-jenkins added this to the 2.12.0-RC1 milestone Jun 9, 2016
@dwijnand
Copy link
Member Author

dwijnand commented Jun 9, 2016

It would be lovely if this could make M5 :-)

Also i expect the unwrapping of $print will start failing once the repl wrappers are gone (#5220).

Requires making the imports available during the eval phase of the REPL.
@dwijnand
Copy link
Member Author

Ah didn't realise this had failed the tests. Updated test/files/run/repl-out-dir.check.

Also, review by @som-snytt?

@som-snytt
Copy link
Contributor

som-snytt commented Jun 11, 2016

The one everyone asks for is to quote strings. It might be nice to include a standard one for easy import from a suitable namespace, like ReplPrinter.Quoted.quoter so import ReplPrinter.Quoted._.

This isn't nuanced:

scala> "hi"
res0: String = hi

scala> import scala.tools.nsc.interpreter.ReplPrinter
import scala.tools.nsc.interpreter.ReplPrinter

scala> :pa
// Entering paste mode (ctrl-D to finish)

implicit val `quoted strings`: ReplPrinter[String] =
  new ReplPrinter[String] {
    def print(s: String, max: Int) =
      if (s.contains('"')) s"${"\""*3}$s${"\""*3}"
      else s""""$s""""
  }

// Exiting paste mode, now interpreting.

quoted strings: scala.tools.nsc.interpreter.ReplPrinter[String] = $anon$1@6ea246af

scala> res0
res1: String = "hi"

You quickly run into implicit management by name:

scala> implicit val `quoted strings`: ReplPrinter[String] = new ReplPrinter[String] {      
     | def print(s: String, max: Int) = s.toUpperCase
     | }
quoted strings: scala.tools.nsc.interpreter.ReplPrinter[String] = $anon$1@fd4459b

scala> res0
res2: String = HI

scala> implicit val upperly: ReplPrinter[String] = new ReplPrinter[String] {
     | def print(s: String, max: Int) = s.toUpperCase }
upperly: scala.tools.nsc.interpreter.ReplPrinter[String] = $anon$1@6200b644

scala> res0
<console>:19: error: ambiguous implicit values:
 both value quoted strings of type => scala.tools.nsc.interpreter.ReplPrinter[String]
 and value upperly of type => scala.tools.nsc.interpreter.ReplPrinter[String]
 match expected type scala.tools.nsc.interpreter.ReplPrinter[String]
 + "res3: String = " + _root_.scala.tools.nsc.interpreter.replStringOf(res3, 1000)
                                                                      ^

This is where smart imports is useful, either better automation or manually quarantine imports. The other ticket for spark has similar problem.

My only concern is how the object nesting in $eval affects spark, who introduced -Yrepl-class-based. Especially if all the imports are in play? That's what the other ticket is about, this PR #5210 for SI-9799.

Really, what's needed is a general way to specify the templating. For example, another requested feature is to emit val res1: String = "hi"so that the output line is code.

Since the concerns are out-of-scope, maybe just disable the change under the spark option; unless it's shown not to be a problem.

@dwijnand
Copy link
Member Author

@som-snytt I see. I've revert the behaviour under -Yrepl-class-based. WDYT?

@som-snytt
Copy link
Contributor

More ideas https://issues.scala-lang.org/browse/SI-9829 such as convert controls to escapes in color, CR -> \r or \u000d in red?

}

object ReplPrinter {
implicit def default[A]: ReplPrinter[A] = new ReplPrinter[A] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have one instance, like so:

 implicit object defaultReplPrinter extends ReplPrinter[Any] {
  def print(x: Any, maxElements: Int) = ScalaRunTime.replStringOf(x, maxElements)
}

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good eye. Done.

scala>

scala> 23
res1: Int = 23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was expecting a "!" at the end here -- how come there's not?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this is the class-based one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps add a comment to the test case that says we don't enable custom string of under this mode

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everyone expects it to end with a bang.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure how to leave the comment, so I've opted for in the transcript.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment didn't fold because that line it's on didn't change, so, for clarity, I've added a commit that adds the comment.

@som-snytt
Copy link
Contributor

I just returned from remote regions; I'll give this another look and try it out.

@dwijnand
Copy link
Member Author

dwijnand commented Jul 9, 2016

Anything left here? This is a REPL-only change. Can it go in?

@som-snytt
Copy link
Contributor

The templating part may conflict with #5220, for which I have a test to fix still. I'll try to nail that down this weekend, and try this on top of it.

@@ -11,13 +11,17 @@ repl-out-dir-run.obj
$eval$.class
$eval.class
$line2
$eval$$iw$$iw$.class
$eval$$iw$.class
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean every repl line generates two additional classfiles? is there a drawback to this? (performance?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it does. I'm not sure what drawbacks there might be, but I avoided it for Spark-reasons.

@lrytz
Copy link
Member

lrytz commented Jul 13, 2016

I think it would be weird to have such a mechanism work only in one of object-based / class-based, there does not seem to be any inherent relation between the two concerns.

@dwijnand
Copy link
Member Author

Which two concerns do you mean? I removed it for class-based because @som-snytt was concerned about the performance impact for Spark.

@lrytz
Copy link
Member

lrytz commented Jul 13, 2016

i just think it doesn't make sense for a feature like the one you're implementing to be dependent on some internal representation within the repl.

@dwijnand
Copy link
Member Author

Yeah it's not ideal, but it's a compromise I personally was fine with.

How do we go about proving that this doesn't affect Spark?

Alternatively how do you feel about an opt-out option, for if it proves to be a problem?

@som-snytt
Copy link
Contributor

Also, sorry my weekend went to understanding how imports work. I still intend to help with the concerns.

@adriaanm adriaanm self-assigned this Aug 2, 2016
@adriaanm
Copy link
Contributor

adriaanm commented Aug 2, 2016

Could we do a bit of a cost/benefit analysis of this and #5220, as well as a risk assessment of causing a regression in the repl, which would lengthen the RC cycle? I'm tempted to push this to 2.12.1 so that we can consider this together with #5220 and go a bit deeper in dealing with some templating technical debt, rather than taking on more.

@dwijnand
Copy link
Member Author

dwijnand commented Aug 2, 2016

I don't like the idea of "shackling" together two pull requests which are doing distinct thing, even if they're in the same area of the codebase.

Why are you saying that this adds technical debt?

@adriaanm
Copy link
Contributor

adriaanm commented Aug 2, 2016

I don't think it's unreasonable to consider these PRs together, as they touch very similar parts of the REPL. Having to disable this for the class-based templates seems to imply we're going to have to come back to this and make it work there too, no?

@adriaanm
Copy link
Contributor

adriaanm commented Aug 2, 2016

I also would like to see a more technical response to @lrytz's concern. Everything is a compromise, but what are we conceding and what for? How would we solve this if we had more time? The REPL encoding is already very complicated, so any change is taking on technical debt for a nicer way of implementing the REPL.

@som-snytt
Copy link
Contributor

Sorry, I meant to devote time to this, but the day job got busy. Time flies. Also, it slipped my mind. Possibly I was hoping it was fixed in ammonite.

@adriaanm
Copy link
Contributor

adriaanm commented Aug 9, 2016

For the reasons stated above, and with this not being a release blocker, I'm re-assigning this to 2.12.1. It would be great to have a concerted effort in cleaning up the REPL encoding once 2.12.0 has shipped.

@adriaanm adriaanm modified the milestones: 2.12.1, 2.12.0-RC1 Aug 9, 2016
@dwijnand
Copy link
Member Author

dwijnand commented Aug 10, 2016

I would be happy help clean up the REPL (but I would need some guidance as I have no prior experience of REPL implementations to compare this one against). I'm fine with this going in 2.12.1 rather than 2.12.0, but I would just like it one way or another.

Without doing a cost/benefit analysis of this and #5220, or a risk assessment, would you consider this feature being opt-in via a compiler flag? Or is that a no-go?

@adriaanm
Copy link
Contributor

Thanks for understanding -- we're happy to help with this once 2.12.0 is out!

@som-snytt
Copy link
Contributor

I've been using spark for day job; you know spark shell doesn't even inherit the improved welcome message in 2.11.8? I sense that there's something important to do for repl re-use and customizability for 2.12, but not sure if I'll find time to realize it.

FTR, there's an episode of "Inspector Morse" which turns on the OED recommendation of "-ize". (A note writer uses "-ise" inappropriately and misspells "desperate" like "separate".) (It was a suicide note, putatively, and this was a few years before the internet.) In hindsight, I would have used stronger language about "-optimise."

http://blog.oxforddictionaries.com/2011/03/ize-or-ise/
http://www.oxforddictionaries.com/words/ize-ise-or-yse

@som-snytt
Copy link
Contributor

Because there is no ticket?, linking to https://issues.scala-lang.org/browse/SI-9829 about pretty printing against impossible odds.

@adriaanm
Copy link
Contributor

adriaanm commented Dec 1, 2016

would you consider this feature being opt-in via a compiler flag? Or is that a no-go?

sorry I missed this the first time -- I would prefer putting this under a flag, as I'm concerned this could slow down the REPL due to additional wrapping

@lrytz
Copy link
Member

lrytz commented Dec 2, 2016

I still think we should come up with a solution that is also fine for -Yrepl-class-based / spark. IUC we'd also like to switch to this encoding by default at some point, and then the feature would go away.

@dwijnand
Copy link
Member Author

dwijnand commented Dec 2, 2016

If I put it behind a feature flag, the feature would be enabled under class-based too, IMO.

@dwijnand
Copy link
Member Author

dwijnand commented Dec 2, 2016

Clearly there's more work to do here for this to be still in the 2.12.1 queue.

But thanks for the recent feedback.

@adriaanm adriaanm modified the milestones: 2.12.2, 2.12.1 Dec 2, 2016
@dwijnand
Copy link
Member Author

I don't have the stamina to take this to completion if it requires first delivering the "avoid $iw wrappers" change in the REPL.

@dwijnand dwijnand closed this Dec 11, 2016
@dwijnand dwijnand deleted the repl-printing branch December 11, 2016 00:58
@som-snytt
Copy link
Contributor

There's pressure both to de-wrapperize and avoid object wrappers entirely and also do customizable printing. To which I'd add customizable wrapping. This won't go unused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants