Я пытаюсь избежать таких конструкций:
val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result
Хорошо, в этом примере ветки then
и else
просты, но вы можете имитировать сложные.
Я построил следующее:
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)
}
Определено, что я могу заменить приведенный выше простой пример:
this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}
Но как я могу избавиться от s: String =>
? Я хочу что-то вроде этого:
this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}
Я думаю, компилятору нужны дополнительные материалы для вывода типов.
Ответ 1
Мы можем комбинировать Как определить тернарный оператор в Scala, который сохраняет ведущие токены? с ответом на Is Опция обертывает значение хорошего шаблона?, чтобы получить
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
Соответствует ли это вашим потребностям?
Ответ 2
Из Блог Лэмбды Тони Морриса:
Я часто слышу этот вопрос. Да. Вместо c ? p : q
написано if(c) p else q
.
Это может быть нежелательно. Возможно, вам захочется написать его, используя тот же синтаксис, что и Java. К сожалению, вы не можете. Это связано с тем, что :
не является допустимым идентификатором. Не бойтесь, |
есть! Вы согласились бы на это?
c ? p | q
Тогда вам понадобится следующий код. Обратите внимание на аннотации по имени (=>
) по аргументам. Эта стратегия оценки необходима для правильной перезаписи тернарного оператора Javas. Это невозможно сделать в самой Java.
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)
}
Вот пример использования нового оператора, который мы только что определили:
object T { val condition = true
import Bool._
// yay!
val x = condition ? "yes" | "no"
}
Удачи;)
Ответ 3
Ответ Рекса Керрса, выраженный в базовом Scala:
"Hi".getClass.getSimpleName match {
case x if x.endsWith("$") => x.init
case x => x
}
хотя я не уверен, какую часть конструкции if-else вы хотите оптимизировать.
Ответ 4
Поскольку: сам по себе не будет действительным оператором, если вы не уверены, что всегда избегаете его обратными тиками :
, вы можете пойти с другим символом, например. "|" как в одном из ответов выше. Но как насчет Элвиса с бородкой?::
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
Конечно, это снова не будет работать, если вы являетесь списками, поскольку они имеют:: operator сами.