2015-02-01 3 views
4

Как вы обычно используете функциональный способ для замены if-without-else в Scala?Заменить if-without-else в Scala

Например, как этот типичный шаблон в императивном стиле:

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 

Я имею в виду, как это сделать его функциональным:

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

Может ли быть лучшим способом без использования переменного посреднического ?

Так кто может поделиться, как вы устраняете if-without-else в scala?

+1

В функциональном программировании, там обычно не 'if' без' else' - вы всегда должны получить * некоторые * значение обратно. Вам может не потребоваться явно объявлять его, когда вы используете функцию, которая предоставляет значение по умолчанию. – Bergi

+5

Ваша вторая версия выглядит хорошо для меня. Ясно, что происходит, нет изменчивых варсов, нет проблем –

ответ

4

Как правило, лучше избегать загромождения пространства имен временными переменными. Так что-то вроде этого было бы лучше:

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

или

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

Если вы обнаружили, что делает это много и производительность не является большой проблемой, это может быть полезно, чтобы определить метод расширения , У меня есть один в моей личной библиотеке, которая выглядит следующим образом:

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 
} 

Вы бы использовать это как так:

List("a", "b", "c").pickFn(_ => flag){ "x" :: _ } 
+1

Я полностью согласен с менее «переменными» принципами. За меньшее количество помех вы можете заменить 'x' в первом совпадении на' _' –

+3

Не должно ли это быть '' x ":: x' в этом случае' match'? – Bergi

+0

@ Берги - Да, это должно. Исправлено, спасибо! (Я должен знать лучше, чем пытаться переименовать переменные после тестирования.) –

0

Это может быть сделано с помощью тройного оператора scalaz в

import scalaz._ 
import Scalaz._ 

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


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

Вы можете оштрафовать кошку, сделав необязательную дополнительную деталь:

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) 

или наоборот

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) 
Смежные вопросы