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

Proposal: Add void to Predef #43

Closed
BalmungSan opened this issue Nov 19, 2020 · 10 comments
Closed

Proposal: Add void to Predef #43

BalmungSan opened this issue Nov 19, 2020 · 10 comments

Comments

@BalmungSan
Copy link
Contributor

I have found this little helper (courtesy of Rob) to be very useful. Especially when you enable compiler options like -Wvalue-discard or -Wunused:implicits (and friends)

@inline final def void(args: Any*): Unit = (args, ())._2

While adding this into all of my projects is not really "painful" I would like if this would be part of Predef.

So I thought this would be the right place to start a discussion about if it would be worth it to add it; and if such addition could be done here until 3.1?

@SethTisue
Copy link
Member

the main previous discussion I can think of is scala/scala#9161 , perhaps there are others

given that both val _ = ... and ...: Unit work (don't they?), I'm not sure we need a third way to do this? but offhand I don't recall all twists and turns in past discussions

@SethTisue
Copy link
Member

(args, ())._2

going through Tuple2 seems like an unnecessary allocation?

@Daenyth
Copy link

Daenyth commented Nov 19, 2020

: Unit doesn't work when using -Ywarn-value-discard.

@BalmungSan
Copy link
Contributor Author

BalmungSan commented Nov 19, 2020

given that both val _ = ...

AFAIK there are some problems with that one. First, it can not be reused like you can not (or couldn't in previous versions) to do this

val _ = foo
val _ = bar

Also, I remember there was something funny about the way it was treated by the compiler.
I believe it was @tpolecat the one that explained that to me.
(I believe the funny thing was that it couldn't be reused, but maybe there was more, I can't remember tbh sorry)

and ...: Unit

Actually didn't know about this one, a quick test in a shell seems to work but will try latter on a real project using sbt-tpolecat.

I'm not sure we need a third way to do this

A plus is that this one also works for unused values.

going through Tuple2 seems like an unnecessary allocation?

Yeah, also the Seq of the varargs.
I was also planning to open a discussion if it would be possible that the compiler treats such function especially and simply replaces it with a no-op. But, first I wanted to see if more people find it useful.

@eed3si9n
Copy link
Member

On Scala 2.12.12 there isn't a great solution: spurious "a pure expression does nothing" warning (awkward to suppress in 2.12, prone to occur in sbt builds) scala/bug#12112

To workaround that sbt now includes

  /** This works around Scala 2.12.12's
   * "a pure expression does nothing in statement position"
   *
   * {{{
   * Def.unit(copyResources.value)
   * Def.unit(compile.value)
   * }}}
   */
  def unit(a: Any): Unit = ()

since sbt/sbt#5743.

If val _ = ... gets backported to 2.12.x that could be the way to go.

@SethTisue
Copy link
Member

SethTisue commented Nov 19, 2020

For scala-library-next, 2.12 doesn't matter. Even 2.13 and 3.0 don't matter. We shouldn't add anything here unless it will be needed in the Scala-3-only world we will eventually be in.

@Sciss
Copy link

Sciss commented Nov 19, 2020

Doesn't the warning occur only in end-of-block position? I do the following now, which I think is also clear intention when reading the code:

def file: java.io.File

def cleanUp(): Unit = {
  file.delete()
  ()
}

@BalmungSan
Copy link
Contributor Author

BalmungSan commented Nov 19, 2020

Ok, I just tested in a project (using Scala 2.13.3) where I was using void and it seems that both val _ = ... and (... : Unit) work for silencing both warnings (value discard and unused values).
And given that "For scala-library-next, 2.12 doesn't matter", it seems the moment of glory for void would have been the release of 2.13.0.

So, for now, I am closing this.


However, I believe we can take something positive about this and it is that such techniques should be documented somewhere. I think it is fair to say that sbt-tpolecat is somewhat common and even without it -Wvalue-discard is highly recommended on its own. And given that folks that use and recommend such flag (Gavin, Rob and myself to name a few) didn't know about what is probably the best way to deal with it; is, at least, hilarious.

I would like to contribute with such documentation, but I am not sure where would be the best place. But, I believe such a question is a bit off-topic for this issue and this repo in general, so I am moving the discussion to gitter.

Edit

For the record: here are the docs.

@SethTisue
Copy link
Member

SethTisue commented Nov 19, 2020

I am not sure where would be the best place

maybe people will google it and find this ticket :-)

(I am joking, yet also partly serious)

@martijnhoekstra
Copy link

To spruce up the potential google juice, maybe those googling for how to fix or suppress the phrase "discarded non-Unit value" will end up here too now that I've added it, and put some potential search phrases next to it.

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

No branches or pull requests

6 participants