5

How do you usually use to replace if-without-else in Scala in functional way?

For example, like this typical pattern in imperative style:

var list = List("a", "b", "c")

if (flag) { // flag is boolean variable
    // do something inside if flag is true
    list = "x" :: list
}
// if flag is false, nothing happened

I'm thinking like this to make it functional:

val tempList = List("a", "b", "c")
val list = if (flag) "x" :: tempList else tempList

Could there be a better way without using intermediary variable?

So anyone can share how do you eliminate if-without-else in scala?

2
  • 1
    In functional programming, there usually is no if without an else - you always need to get some value back. You only might not need to declare it explicitly, when you use a function that provides a default value. Commented Feb 1, 2015 at 14:34
  • 5
    Your second version looks fine to me. Clear what's going on, no mutable vars, no problem Commented Feb 1, 2015 at 15:19

3 Answers 3

4

It's generally better to avoid cluttering your namespace with temporary variables. So something like this would be better:

val list = {
  val temp = List("a", "b", "c")
  if (flag) "x" :: temp else temp
}

or

val list = List("a", "b", "c") match {
  case x if flag => "x" :: x
  case x => x
}

If you find yourself doing this a lot and performance is not a big concern, it might be handy to define an extension method. I have one in my personal library that looks like this:

implicit class AnythingCanPickFn[A](private val underlying: A) extends AnyVal {
  /** Transforms self according to `f` for those values where `p` is true. */
  @inline def pickFn(p: A => Boolean)(f: A => A) =
    if (p(underlying)) f(underlying) else underlying
}

You'd use this one like so:

List("a", "b", "c").pickFn(_ => flag){ "x" :: _ }
Sign up to request clarification or add additional context in comments.

3 Comments

I totally agree with the less local "variables" principle. For even less cluttering, you can replace the x in the first match with a _
Shouldn't that be "x" :: x in that match case?
@Bergi - Yes it should. Fixed, thanks! (I should know better than to try to rename variables after testing.)
2

You could skin the cat by making the optional part optional:

scala> val flag = true
flag: Boolean = true

scala> Option("x").filter(_ => flag).toList ::: "a" :: "b" :: "c" :: Nil
res0: List[String] = List(x, a, b, c)

scala> val flag = false
flag: Boolean = false

scala> Option("x").filter(_ => flag).toList ::: "a" :: "b" :: "c" :: Nil
res1: List[String] = List(a, b, c)

or conversely

scala> sys.props.get("flag")
res3: Option[String] = None

scala> sys.props.get("flag").map(_ => "x").toList ::: List("a","b","c")
res4: List[String] = List(a, b, c)

scala> sys.props("flag") = "true"

scala> sys.props.get("flag").map(_ => "x").toList ::: List("a","b","c")
res6: List[String] = List(x, a, b, c)

Comments

0

It can be done using scalaz's ternary operator

import scalaz._
import Scalaz._

val temp = List("a", "b", "c")
val list = (flag) ? ("x" :: temp) | temp


libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.6"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.