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

Change wildcards from _ to ? ? #2041

Closed
odersky opened this issue Feb 28, 2017 · 10 comments
Closed

Change wildcards from _ to ? ? #2041

odersky opened this issue Feb 28, 2017 · 10 comments

Comments

@odersky
Copy link
Contributor

odersky commented Feb 28, 2017

Using the underscore for wildcards in types was unfortunate, because it causes a notational discrepancy for types and for values.

  • For types, C[_] means an existential: ex(T).C[T]
  • For values, c(_) means a universal: x => c(x).

We'd also like to use some notation for projecting types, but _ is already taken. So @non's kind projector uses ? instead. But now things get really confusing.

  • For higher kinded definitions, you write F[_], but for partial applications it's F[?].
  • ? is the same as Java's wildcard, but Java's wildcard means _ in Scala.
  • Function placeholders are written _ for terms but ? for types.

It seems we have everything wrong here and it's no wonder people are confused.

Everything would be so much nicer if we could go back in time and express wildcards with ? instead of _.

  • We could then use _ as a placeholder for type parameters.
  • This would make F[_] and f(_) mean the same thing.
  • It also means that F[_] produces a higher-kinded type at definition sites as well as use sites.
  • The wildcard notation would be aligned with Java

Changing to dotty might give us the one and only chance to actually achieve that.

  • We have a rewrite tool that could automatically rewrite all wildcard occurrences of _ to ?.
  • We could at the same time do the opposite rewrite to _ for kind projector's ?.

It's still a large step, though. So I am on the fence whether we should do it.

@smarter
Copy link
Member

smarter commented Feb 28, 2017

I wholeheartedly agree that this would be better. I think the main argument against this is cross-compilation support (which is something that we haven't spent enough time thinking about yet I think). Assuming the old syntax is supported under -language:Scala2 by dotty, then everyone will continue using it until they can drop support for Scala 2.x, this means that both syntax will survive in the wild for a very long time which will make the situation even more confusing. If we commit to getting the new syntax implemented in Scala 2.11/2.12/2.13 under a flag like -Xfuture, then the situation may be somewhat better. My opinion is that the amount of energy that this will require (not just for the implementation, remember Wadler's law) could be better applied elsewhere.

@smarter
Copy link
Member

smarter commented Feb 28, 2017

However, there is one thing which I think is worth trying to fix: preventing people from writing foo[M[_] <: List[_]] when they meant foo[M[X] <: List[X]], I opened an issue for that some times ago: https://github.com/lampepfl/dotty/issues/1809

@odersky
Copy link
Contributor Author

odersky commented Feb 28, 2017

Yes, foo[M[_] <: List[_]] highlights the most glaring problems of the status quo. Let's think about migration. Here's a possible strategy:

  • For Dotty 0.1, we allow ? as an alternative for _, and offer rewrites under -language:future.
  • For Dotty 0.2, we deprecate _, and offer rewrite in normal mode.
  • For Dotty 0.3, we remove _.
  • For Dotty 0.4, we re-introduce _ as partial application.

Kind projector would not work during this transition (and would not be needed afterwards because the compiler does it natively). There's less need for kind projector in dotty anyway because we have native type lambdas instead of the atrocity involving structural types. But if it's useful one could port a version of kind-projector that uses (say) ?? instead of ?.

@DarkDimius
Copy link
Member

DarkDimius commented Feb 28, 2017

@odersky, as most people will be migrating from Scala 2.12-2.13 to Dotty 1.0\Scala 3.0,
I think that depredations should affect Scala2.

@adriaanm, would it be possible to consider adding support for ? syntax and providing deprecation warnings for the _ in 2.12? Better by default, but otherwise under a flag.

@adriaanm
Copy link
Contributor

adriaanm commented Feb 28, 2017

I support the direction, but I don't think we can deprecate this in 2.12. We could support the ? wildcard notation for existentials in 2.13 (or possibly 2.12) under a flag (in addition to _), but cross-compilation will cause drag here for a while, as smarter said.

@odersky
Copy link
Contributor Author

odersky commented Mar 1, 2017

If we had ? under an -Xfuture flag we could deprecate _ and rewrite in the first version of dotty, which would speed up the conversion.

The same holds for with --> &. If we could get & under -Xfuture we could deprecate and rewrite immediately in dotty.

@adriaanm
Copy link
Contributor

adriaanm commented Mar 1, 2017

I'd welcome a PR implementing those under -Xsource:dotty in 2.12.3 (the 2.12.2 queue is closing soon, and I'd prefer not to rush this) or 2.13.0-M1.

@Atry
Copy link
Contributor

Atry commented Dec 12, 2017

A discussion about coding convention of higher kinded type declaration:
https://gitter.im/scala/contributors?at=5a2f68980163b02810269751

We can change the style documentation right now, to avoid accidentally written foo[M[_] <: List[_]].

@Glavo
Copy link
Contributor

Glavo commented May 10, 2018

I very much agree with this proposal, because I've repeated the use of _ for many times, I think reducing the meaning of _ can reduce beginners' confusion.

@smarter
Copy link
Member

smarter commented Nov 3, 2018

Closed in favor of #5379 where the discussion can continue

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

No branches or pull requests

6 participants