Optional parens

This is probably an Intellij inspection. I’m pretty sure the compiler doesn’t warn on unneccessary parentheses.

3 Likes

The warnings come from IntelliJ, not Scala. IntelliJ has its own Scala presentation compiler, so yes, file a bug for the Scala plugin.

2 Likes

https://youtrack.jetbrains.com/issue/IDEA-256692

It’s a bit subjective, but your style is a bit unorthodox, IMO. I would enclose the parameter list in parens, not just the type of it:

withSetCollector { (collect: Int => Unit) => 
  ...
}

This way, IntelliJ does no longer complain.

2 Likes

Would you put the param list in parens even if the type were not an arrow type or even if no type were specified? When I first started learning Scala, I always put the parameter list in parens, but stopped over time.

For such local uses (locally scoped variables), I usually omit the type altogether and in this case also omit the parenthesis.

Thus, I also have scalafmt’s RedundantParens rewrite rule enable and no longer think about this… :relieved:

I’m not sure about the connection to scalafmt as I’ve never used it, but if I omit the type declaration Int => Unit, I get additional errors.

missing parameter type
    val numVars:Int = withSetCollector{collect => for {

for the following code

    val numVars:Int = withSetCollector{collect => for {
      (_, lengthHash) <- hash
      (_, rectHash) <- lengthHash
      (rectified, _) <- rectHash
      literal <- rectified
    } collect(literal) }.size

and IntelliJ squiggle-highlights the argument of collect.
Screenshot 2020-12-03 at 12.42.23

That probably depends on how you defined withSetCollector. Is it parameterized?

Yes it is parameterized. It is defined like this.

  def withSetCollector[A](f: (A => Unit) => Unit): Set[A] = {
    var objects: Set[A] = Set()

    def collect(obj: A): Unit = {
      objects = objects+obj
    }

    f(collect)
    objects
  }

In this case, you have to give the compiler a hint as to what the A parameter should be. I would write

withSetCollector[Int] { collect => 
  ...
}

And BTW, it seems you tried to implement a builder pattern here. The usual approach would be to use a mutable collection inside a builder function like this and then call .toSet when returning it. Otherwise you create lots of immutable Sets.

edit:

def withSetCollector[A](f: (A => Unit) => Unit): Set[A] = {
    val objects = collection.mutable.Set[A]() 

    f(objects.add)
    
    objects.toSet
  }

edit 2: Speaking of builders, you could also use

  def withSetCollector[A](f: (A => Unit) => Unit): Set[A] = {
    val b = Set.newBuilder[A]
    f(b.addOne)
    b.result()
  }
1 Like

I see, that’s not very intuitive. but once I see it it is much easier.

Thanks, i’ve made you suggested change in my code. It is a good suggestion.

BTW, when I look at that code, I see another problem in the file which I don’t know how to convert from 2.12 to 2.13. The warning is View bounds are deprecated.

def withMaximizer[A <% Ordered[A]](init: A)(f: (A => Unit) => Unit): A = {
    withReducer(init, (a:A,b:A)=>if (a < b) b else a)(f)
  }

  def withMinimizer[A <% Ordered[A]](init: A)(f: (A => Unit) => Unit): A = {
    withReducer(init, (a:A,b:A)=>if (a > b) b else a)(f)
  }

Yes, view bounds where a mechanism to say: there should be some conversion from type A to some other type B (so A could be “viewed” as a B). That’s the same as stating there should be a mapping / function from A to B implicitly available…

IntelliJ provides a quick fix for this (I’m an the latest version IntelliJ 20.03 and Scala plugin).

It would rewrite this to:

def withMaximizer[A](init: A)(f: (A => Unit) => Unit)(implicit ev$1: A => Ordered[A]): A = {
    withReducer(init, (a:A,b:A)=>if (a < b) b else a)(f)
}

interesting. yes, IntelliJ does insert the variable name containing a $ sign. Can I rename ev$1 to ev? or does the $ have some special meaning?

There’s also builders for Scala collections:

def withSetCollector[A](f: (A => Unit) => Unit): Set[A] = {
val objects = Set.newBuilder[A]

f(objects += _)

objects.result()
}

@curoli Ha, if you look at my second edit here, the code is very similar to yours… :smiley:

(I guess edits are not really put through to emails?!)

You can name it however you want, IntelliJ probably only tries to generate an abstruse name that does not clash with existing ones.

No, unfortunately, edits to post are not sent via e-mail.

glad you got my edit to my last message :smile: I use the email interface on the phone myself, but typing answers usually in the browser.