Proposal to remove XML literals from the language

You can either:

  • Convert your XML to Scala code using something like ScalaTags.

  • Use a template engine like Twirl.

FWIW I made myself an Ammonite script for converting HTML to the VDOM DSL used in scalajs-react (which I believe is based very closely on scalatags), which others might find useful (improvements welcome): https://gist.github.com/nafg/112bf83e5676ed316f17cea505ea5d93

@sjrd has written up a document summarizing the feedback so far in this thread https://docs.google.com/document/d/1BarbbG9WhF_hdHohfDNP4RAuFK4RN5DSHAPK1tRxmWo/edit?usp=sharing

1 Like

I am in favor of removing XML literals from the language. Never needed nor saw that before, actually.

I am also in favor. This reduces the burden on the compiler.

Off topic for just a moment because this tends to be a common source of confusion: Being willing to listen to feedback that one disagrees with is not the same as being willing to listen to unhelpful argumentative comments masquerading as feedback.

People’s tolerance for more strongly-worded feedback varies, and I don’t think it’s universally true that people will listen to strongly-worded yet entirely relevant feedback. But in this case, not wanting to waste time with unpleasant comments with invalid argumentation is, arguably, the prudent thing to do. Wasting time is, well, a waste of time. If you feel strongly about something, venting about it and trying hard to get it changed/improved are almost always mutually exclusive activities.

(Note: there was a suggestion of removing for which was akin to a suggestion I made regarding the discussion of procedure syntax, but the key there is that for without yield had the exact same issue as procedure syntax, so it’s entirely relevant.)


Regarding XML literals, I think the key to whether they should be kept or not is whether there is critical functionality that can’t be retained using string interpolation. So far, I’ve seen a number of comments about how people are productively using XML literals, but not very many that show why string interpolation can’t do the job.

The biggest concern I would have is that you’d need macros to adequately check the syntax (you basically have to run arbitrary code on the string), and the macro situation in Scala 3 isn’t clearly such that you could do this.

But overall, if we’re going for a simplification in Scala 3, it seems important to fix the situation where the compiler and language specification is complicated to a non-trivial extent in order to keep only one of a variety of markup languages.

So to me, if Scala 3 is going to get simpler at all, this seems one of the easiest decisions to make, despite it not being completely free from negative consequences.

6 Likes

Yep, so far the disadvantages that I’m aware of with string interpolation versus direct parser support:

  • namespaces (honestly, I don’t really know how this works right now :-))
  • escaping/parsing (several issues: you don’t want $ from your xml literal accidentally blowing a hole in the interpolated string, and you’d have to escape """ in your xml literal to avoid prematurely closing the string, not sure how whitespace and unicode escapes work out)
  • the library side of things matters whether you support xml “natively” in the compiler or not

Since xml support is already implemented in dotty, I think the main discussion points are:

  • do we want to carry the xml spec around (implicitly) in ours for the next 10 years? (If only to decide when to switch between the xml and the scala parser.)

  • Since you could always implement xml support using string interpolators, do we want to potentially have to support both ways?

  • Finally, library support for xml is hard – whether we use string interpolators or direct support.

If we do keep direct xml support, I think we should consider the name-based proposal, and perhaps only supporting a subset of xml (so that we can at least embed the grammar in our own?).

1 Like

I think it depends on the goal of Scala 3.

  • Is it a compact language or a practical language?
  • Which one is more important, easing maintainers’ burden, or winning the war on TypeScript?
2 Likes

Compactness also simplifies learning. Of course, the empty language is the easiest one to learn, so we should balance with being practical/productive :slight_smile:

Now, how much does having to quote xml as interpolated strings hamper productivity? At first, yes, it will cost us in terms of migration and improving the tooling. After that, I think it’ll be a net win, because IDEs will become better at supporting languages embedded in interpolated strings (quoting pasted text, highlighting the quoted language,… I think IntelliJ already has the concept of language injection?), and the wins will apply to all languages that we embed this way (JSON etc).

IDE is not the first place when a beginner see the language. Will a potential user see the properly highlighted Scala code on a WIKI page, a Github issue, a blog article, a conference or a T-shirt?

2 Likes
class Test {
  // What are these double braces? I thought they were for blocks?
  def xmlGreet1(who: String) = <hello>{{who}}</hello> 
  def xmlGreet2(who: String) = xml"""<hello>$who</hello>"""
}

Hi Folks,

@fanf dropped into the Lift list to ask us to weigh in on the impact of this change to the Lift Framework. I’ve scanned through most of the conversation, and wanted to provide some input from our point of view.

First, Lift makes heavy use of XML literals in both our library code and in our documentation. We actually highlight the ease of using XML literals as one of the reasons folks could consider using Lift and Scala over other languages with more popular web frameworks. Defining the CSS bindings that make up our server-side rendering with XML literals is super intuitive. As such, we have a heavy interest in making sure that we preserve this ease of use in whatever comes next for Scala.

To that end, I think that the current proposal of the xml interpolator would preserve many of the benefits of XML literals while removing another special case from the Scala language. From a language complexity standpoint, I am strongly in favor of fewer special cases.

However, as a library maintainer, I’m a bit concerned about the lack of discussion over a migration path. If the SIP Committee wishes to remove XML literals, I am all for it. However, we should do so with a clear deprecation and migration path.

If this were done in Scala 3, as I’ve seen it discussed so far, it sounds like Lift would be left out in the cold until we tracked down and changed all of our XML literals in one cycle. This would be incredibly painful and would make it downright challenging for us to move. To boot, I don’t know how we would guarantee stability between releases with such a large change in one release.

Given that XML literals are already implemented in Dotty, can I suggest the following:

  • Enable the new xml interpolation style in Scala 3
  • Mark XML literals as deprecated in Scala 3.
  • Provide a compiler flag to totally disable XML literals in the Scala 3 compiler so that it would throw an error instead of deprecation warnings.
  • After a year, replace the Scala 3 flag with one that makes the XML literals opt-in instead of opt-out.
  • After another two years, remove XML literals entirely.

I realize it feels painful to wait three years to see the removal of these things entirely. However, this would permit Lift (and other libraries that are interested) to cross build between Scala 2.12, 2.13, and 3.0 for a time before going all in on Scala 3.0. This avoids hard breaks and makes things a lot easier on our maintainers and our users.

As an alternative, if the xml interpolator were somehow back-ported to Scala 2.12, I would be amenable to cutting out XML literals 1 year after the release of Scala 3.0 instead of three years after.

TL;DR As long as we can cross build between Scala 2.12, 2.13, and 3.0 for a period of two years and we get a least a year to root out all of our XML literals, we should be okay and I am in favor of this change.

Thanks,
Matt Farmer
Lift Committer

5 Likes

I don’t use XML literals myself, I would certainly like to see them removed but why now? My understanding is that Dotty has XML literals. Surely we’ve got enough on our plate getting from 2.12 to 3.0 (2.11 in the case of Spark and Scala-native). Wouldn’t it make sense to put this back to 3.1. Then there would be one less migration issue for the Scala community to worry about and, a proper migration path could be given the time, energy and focus that it requires

I think you forget about scala 2.14 that is meant to lower the gap between scala 2.x and 3.0. It may fit into your migration path nicely.

More broadly, I think there’s a tendency to feel that “Scala 3 is our chance to get in all the breaking changes so that we can avoid doing breaking changes too often.” I think that’s wrong. The need to have a strategy for evolving the language without leaving people behind should really be orthogonal to Dotty. Dotty/Scala 3 is primarily about changes to the underlying calculus. To the extent that any language change may affect that, it’s necessarily to design that change in tandem with releasing Dotty. In my opinion, any change that without doubt does not affect the premise of Dotty, should be pushed off to 3.1. We should get 3.0 released as soon as possible (but no sooner of course), and once it’s released work on getting 3.1 released as soon as possible.

A major side benefit of this approach is greatly mitigating the fears that abound, that Dotty will be a python-3-esque community split.

In that light I would agree with deferring XML deprecation. (Of course, then certain people will start saying it will never really happen. But that’s the lesser of the two evils. We should definitely prove them wrong, of course…)

4 Likes

Lift would be left out in the cold until we tracked down and changed all of our XML literals in one cycle.

How hard would that be with a re-write tool that modified everything for you? My understanding is that rewrite tools would be provided; there are lots of things changing with Scala 3 that need a migration tool and this would be one of them.

A rewrite tool may be an help, but it would be delusional to believe it will cover 100% of cases, especially with something as complexe as XML literals.

And the problem is not only on Liftweb framework part, but also in all the hundreds (thousands? Lift is OLD) applications using lift which will need to migrate. For example, Rudder used it, we have a faire amont (15k? More?) lines of html / xml which rely on XML literals. We will needs a good span of time to migrate all of that.

1 Like

Not doing the deprecation/removal too quickly seems sensible to me.

Perhaps by the time Scala 3.0 lands, we’ll have a better story for compiler warning suppression. In that case, 3.0 could contain the deprecation, people still using XML literals could easily selectively disable those warnings, and then the removal would come in 3.1.

3 Likes

Is there a reason to believe this? Offhand, this seems like one of the more straightforwardly mechanical rewrites. I can’t say I know the subject intimately, but I don’t see any reason offhand why we shouldn’t expect to be able to completely rewrite XML literals to XML string interpolators…

1 Like

XML is extremelly complexe. See for example the message by @adriaanm above. And there is tens of suble case because of the nature of XML class hierarchie.

In all cases, that tool does not exists yet. Once (if) it exists and prove that it can be performant, of course it will help. But I can’t believe it is a 3 month project - please prove me wrong on that.

1 Like