Let's drop postfix operators


#1

At least since Scala 2.10 postfix operators have been considered to be more or less deprecated, because the interact badly with semicolon inference. They’ve been hidden behind a compiler flag ever since, but they have never actually been deprecated. The documentation says that’s because “several DSLs written in Scala need the notation”. I personally don’t know of any of these DSLs that can’t live without them. I know the duration dsl in the std library used to promote them, but honestly: it’s just as easy and much less error prone to write 2.seconds instead of 2 seconds.

To me it seems the only people using postfix ops are people who are new the language, who only end up getting confused when they get strange results or compiler errors. I was half expecting Dotty to have already gotten rid of postfix ops, or that someone else would have suggested it since we’re planning on dropping or simplifying a bunch of stuff in the future. But I’ve seen no discussion about them anywhere. Perhaps people have forgotten they exist?

So if nobody else will suggest it, then I will: let’s deprecate and drop postfix operators, and make Scala a bit less confusing still. Or are there still convincing reasons to keep them?


#2

There is always the compelling reason not to drop anything: don’t break people’s code! You never know how much (old) code in the wild still uses postfix operators.

Breaking existing code must be compensated by significant benefits of dropping the feature. You only mention confusing by beginners. We can address that without dropping the feature: turn the warning that we get if we don’t have import scala.language.postfixOps into an error.

That will still allow old codebases to work unchanged (either with the import or with the -language:postfixOps compiler option), but should seriously detract new users from using them.


#3

I think there’s a better solution to postfix operators, which would be to introduce some limited measure of indentation sensitivity to Scala’s syntax.

val x = foo bar
baz
// means:
val x = foo bar;
baz

val x = foo bar
  baz
// means:
val x = foo bar baz

I think this will avoid confusing newcomers, since it’s a natural convention that most people already follow – that a non-indented line does not normally continue the expression above.

The same principle could be used to get rid of the fact that removing a comment in some places can break Scala code, which many people seem to find inexcusable.

foo.bar
{ ... }
// means:
foo.bar;
{ ... }

foo.bar
  { ... }
// means:
foo.bar { ... }

// same as:

foo.bar
// comment
  { ... }

// same as:

foo.bar

  { ... }

#4

I don’t think there is “the compelling” reason of not breaking code and that “only mentioning confusing by beginners” is an only. It’s a good reason. We should strive to keep the language simple, and I don’t see a huge benefit in expressivity having this quite marginal feature. AFAIK post-fix syntax makes parsing code harder, and I think it also lacks regularity; for example, can you use post-fix syntax with types like List String?

Before arguing that it will break people’s code, one would have to present some statistics of how widely it is used. My guess is that the number of uses are neglible, and where it is used, authors wouldn’t have a strong stylistic opinion on it.

Does Dotty support post-fix syntax?

best, .h.h.


#5

I think not breaking code is a compelling argument for not dropping postfix operators, although I dislike them and would personally like them to see removed. At least, before doing so, I’d like to see a migration story — maybe something like a scalafix rewrite could do it?


#6

Someone should PR @olafurpg’s https://github.com/olafurpg/scalafix/commit/da7374d0c0ed2775c1e2fa1f024307fbcd1fbd1d.


#7

I like it! Would someone like to PR that in scala/scala for Scala 2.13…? (I can’t promise ahead of time it would be merged, but I would certainly argue for it.)


#8

Here is a shot at promoting the feature opt-in to “required” in 2.13, and in 2.14 to require -language:postfixOps to even consider parsing postfix, and still to require the import at the use site (or more precisely, the implicit).


#9

That’s an attack on our creative freedoms.


#10

I forgot to mention that whenever you enable postfixOps, google will start serving you ads relating to any of post, fix or ops.


#11

What’s the point of making this a parser error, which is usually much more cryptic?

If a beginner copy-pastes some code from stackoverflow, I would much rather them see “postfix operators now need to be explicitly enabled” rather than some confusing message such as “found }, expected identifier.”


#12

In this case, the error is more explicit, but I was just floating the idea. I will probably drop it because it doesn’t much improve the parsing experience; what’s actually needed is to intercept the dread Int doesn't take parms error when it occurs on a multiline expression and add some helpful text.