Skip to content

Clarify example in opaque type documentation #8440

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 1 commit into from
Mar 5, 2020

Conversation

panacekcz
Copy link
Contributor

The last example at https://dotty.epfl.ch/docs/reference/other-new-features/opaques.html causes repeated confusion, showing in #7259, #8423 and https://contributors.scala-lang.org/t/proposal-for-opaque-type-aliases/2947/90 .

This PR attempts to remove all possible sources of confusion and unambiguously describe my understanding of the example.

Copy link
Member

@dottybot dottybot left a comment

Choose a reason for hiding this comment

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

Hello, and thank you for opening this PR! 🎉

All contributors have signed the CLA, thank you! ❤️

Have an awesome day! ☀️

@panacekcz panacekcz mentioned this pull request Mar 4, 2020
@DaniRey
Copy link
Contributor

DaniRey commented Mar 5, 2020

Great catch @panacekcz

Currently this example is a bit of a Dotty Puzzler (http://www.javapuzzlers.com/), which is maybe not the best way to introduce a concept.

I would suggest to rewrite the code as follows. and combine this with the additional description you suggested.

object Access {

  opaque type Permissions = Int
  opaque type PermissionChoice = Int
  opaque type Permission <: Permissions & PermissionChoice = Int

  def (x: Permissions) and (y: Permissions): Permissions = x | y
  def (x: PermissionChoice) or (y: PermissionChoice): PermissionChoice = x | y
  def (x: Permissions).is(y: Permissions) = (x & y) == y
  def (x: Permissions).isOneOf(y: PermissionChoice) = (x & y) != 0

  val NoPermission: Permission = 0
  val ReadOnly: Permission = 1
  val WriteOnly: Permission = 2
}

object User {
  import Access._

  case class Item(rights: Permissions)

  //if this would be in Access it would have to use `|` instead of `and`,
  //because Permissions is an Int within Access
  val ReadWrite: Permissions = ReadOnly and WriteOnly

  val ReadOrWrite: PermissionChoice = ReadOnly or WriteOnly

  val x = Item(ReadOnly)  // OK, since Permission <: Permissions

  assert( x.rights.is(ReadWrite) == false )
  assert( x.rights.isOneOf(ReadOrWrite) == true )
}

I moved ReadWrite and ReadOrWriteto the User object and replaced | and & with and and or to better disambiguate between the extension method and the operators on Int

Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

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

Yes, much better this way.

@odersky
Copy link
Contributor

odersky commented Mar 5, 2020

Thanks for making the improvements!

@odersky odersky merged commit 86e3c53 into scala:master Mar 5, 2020
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.

4 participants