J'essaie d'éviter de telles constructions:
val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result
Ok, dans cet exemple, les branches then
et else
sont simples, mais vous pouvez en imaginer des complexes . J'ai construit ce qui suit:
object TernaryOp {
class Ternary[T](t: T) {
def is[R](bte: BranchThenElse[T,R]) = if (bte.branch(t)) bte.then(t) else bte.elze(t)
}
class Branch[T](branch: T => Boolean) {
def ?[R] (then: T => R) = new BranchThen(branch,then)
}
class BranchThen[T,R](val branch: T => Boolean, val then: T => R)
class Elze[T,R](elze: T => R) {
def :: (bt: BranchThen[T,R]) = new BranchThenElse(bt.branch,bt.then,elze)
}
class BranchThenElse[T,R](val branch: T => Boolean, val then: T => R, val elze: T => R)
implicit def any2Ternary[T](t: T) = new Ternary(t)
implicit def fct2Branch[T](branch: T => Boolean) = new Branch(branch)
implicit def fct2Elze[T,R](elze: T => R) = new Elze(elze)
}
Défini cela, je peux remplacer l'exemple simple ci-dessus par:
this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}
Mais comment puis-je me débarrasser du s: String =>
? Je veux quelque chose comme ça:
this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}
J'imagine que le compilateur a besoin d'éléments supplémentaires pour déduire des types.
Nous pouvons combiner Comment définir un opérateur ternaire dans Scala qui conserve les jetons menant? avec la réponse à L'option wrapper une valeur est-elle un bon modèle? obtenir
scala> "Hi".getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res0: String = String
scala> List.getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res1: String = List
Est-ce adéquat pour vos besoins?
De Le blog Lambda de Tony Morris :
J'entends beaucoup cette question. Oui. Au lieu de
c ? p : q
, il s'agit de écritif(c) p else q
.Cela peut ne pas être préférable. Peut-être aimeriez-vous l'écrire en utilisant le Même syntaxe que Java. Malheureusement, vous ne pouvez pas. C'est parce que
:
n'est pas un identifiant valide. Ne crains rien,|
c'est! Voulez-vous vous contenter de cela?c ? p | q
Ensuite, vous aurez besoin du code suivant. Remarquez l'appel par nom (
=>
) annotations sur les arguments. Cette stratégie d'évaluation est nécessaire pour réécrire correctement l’opérateur ternaire de Java. Cela ne peut pas être fait en Java lui-même.case class Bool(b: Boolean) { def ?[X](t: => X) = new { def |(f: => X) = if(b) t else f } } object Bool { implicit def BooleanBool(b: Boolean) = Bool(b) }
Voici un exemple utilisant l'opérateur new que nous venons de définir:
object T { val condition = true import Bool._ // yay! val x = condition ? "yes" | "no" }
S'amuser ;)
Réponse de Rex Kerr exprimée en Scala de base:
"Hi".getClass.getSimpleName match {
case x if x.endsWith("$") => x.init
case x => x
}
bien que je ne sache pas quelle partie de la construction if – else vous souhaitez optimiser.
Puisque les constructions if-else dans Scala renvoient une valeur, vous pouvez utiliser cette
val a = if (1 < 0) 1 else 2
Plus d'infos: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples
Puisque: par lui-même ne sera pas un opérateur valide sauf si vous êtes d'accord pour l'échapper toujours avec des ticks arrière :
, vous pourriez utiliser un autre caractère, par exemple. "|" comme dans l'une des réponses ci-dessus. Mais que diriez-vous d'elvis avec une barbiche? ::
implicit class Question[T](predicate: => Boolean) {
def ?(left: => T) = predicate -> left
}
implicit class Colon[R](right: => R) {
def ::[L <% R](pair: (Boolean, L)): R = if (q._1) q._2 else right
}
val x = (5 % 2 == 0) ? 5 :: 4.5
Bien sûr, cela ne fonctionnera à nouveau pas si vos valeurs sont des listes, car elles ont elles-mêmes l'opérateur ::.