Pertanyaan Operator Ternary Mirip Dengan?:


Saya mencoba menghindari konstruksi seperti ini:

val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result

Oke, dalam contoh ini then dan else cabangnya sederhana, tetapi Anda dapat membayangkan yang rumit. Saya membangun yang berikut:

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)
}

Ditetapkan itu, saya dapat mengganti contoh sederhana di atas dengan:

this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}

Tapi bagaimana saya bisa menyingkirkan s: String =>? Saya menginginkan sesuatu seperti itu:

this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}

Saya kira compiler membutuhkan barang tambahan untuk menyimpulkan jenis.


76
2018-02-09 16:20


asal


Jawaban:


Kita bisa menggabungkan Bagaimana cara menetapkan operator terner di Scala yang mempertahankan token terkemuka? dengan jawabannya Apakah Opsi membungkus nilai sebagai pola yang bagus? mendapatkan

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

Apakah ini cukup untuk kebutuhan Anda?


21
2018-02-09 16:45



Dari Blog Lambda Tony Morris:

Saya banyak mendengar pertanyaan ini. Ya, benar. Dari pada c ? p : q, ini   tertulis if(c) p else q.

Ini mungkin tidak disukai. Mungkin Anda ingin menulisnya menggunakan   sintaks yang sama dengan Java. Sedihnya, Anda tidak bisa. Hal ini karena : bukan sebuah   pengenal yang valid. Jangan takut, | aku s! Apakah Anda puas dengan ini?

c ? p | q

Maka Anda perlu kode berikut. Perhatikan panggilan demi nama (=>)   penjelasan tentang argumen. Strategi evaluasi ini diperlukan untuk   menulis ulang dengan benar operator terner Java. Ini tidak bisa dilakukan di Jawa   diri.

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) 
}

Berikut ini contoh menggunakan operator baru yang baru saja kami definisikan:

object T {   val condition = true

  import Bool._

  // yay!   
  val x = condition ? "yes" | "no"
}

Selamat bersenang-senang ;)


104
2018-02-09 19:06



Jawaban Rex Kerr diungkapkan dalam Scala dasar:

"Hi".getClass.getSimpleName match {
  case x if x.endsWith("$") => x.init
  case x => x
}

meskipun saya tidak yakin bagian apa dari konstruk if-else yang ingin Anda optimalkan.


14
2018-02-09 16:52



Karena konstruksi if-else di Scala mengembalikan nilai, Anda dapat menggunakan ini

val a = if (1 < 0) 1 else 2

Info lebih lanjut: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples


2
2018-02-13 13:53



Karena: dengan sendirinya tidak akan menjadi operator yang valid kecuali Anda ok dengan selalu melarikan diri dengan kutu belakang :, Anda dapat menggunakan karakter lain, mis. "|" seperti dalam salah satu jawaban di atas. Tapi bagaimana dengan elvis berjenggot? ::

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

Tentu saja ini tidak akan berfungsi jika Anda menghargai daftar, karena mereka memiliki :: operator sendiri.


0
2018-01-25 20:43