Soru Üçlü Operatör Benzer?:


Bunun gibi yapılardan kaçınmaya çalışıyorum:

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

Tamam, bu örnekte then ve else şube basit, ancak karmaşık olanları görüntüleyebilirsiniz. Ben şunları inşa ettim:

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

Tanımlayın ki yukarıdaki basit örneği aşağıdaki gibi değiştirebilirim:

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

Ama nasıl kurtulabilirim s: String =>? Ben böyle bir şey istiyorum:

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

Derleyicinin türlerini bulmak için ekstra şeylere ihtiyaç duyduğunu düşünüyorum.


76
2018-02-09 16:20


Menşei


Benim cevabımda buna sahip olmadığımdan - sorun yaşamanızın nedeni bu tür çıkarımın soldan sağa doğru en iyi şekilde çalışmasıdır, ancak operatör önceliği nedeniyle belirteçleri sağdan sola birleştiriyorsunuz. Tüm ifadelerinizi (aynı önceliğe sahip) sözcükler yaparsanız ve şeyleri gruplama şeklini değiştirirseniz, istediğiniz çıkarımı elde edersiniz. (Yani sen olurdu HasIs, IsWithCondition, ConditionAndTrueCase ifadenin bölümlerini soldan sağa doğru oluşturacak sınıflar.) - Rex Kerr
Bilinçsizce soldan sağa doğru tür çıkarım yolunu tahmin ettim, ancak özellikle de başlayarak operatörün önceliği ve yöntem isimlerinin birliği ile tıkanmıştım. ? Başka bir alfasay char önce bir yöntem adı olarak ilk char ve bir : sol çağrışım için. Bu yüzden soldan sağa doğru çalışan çıkarımı elde etmek için yeni yöntem isimlerini yeniden düşünmeliyim. Teşekkürler! - Peter Schmitz


Cevaplar:


Birleştirebiliriz Scala'da öncü belirteçleri koruyan üçlü operatör nasıl tanımlanır? cevabı ile Option bir değere iyi bir desen mi katıyor? almak

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

Bu ihtiyaçlarınız için yeterli mi?


21
2018-02-09 16:45



Bu aklımda olana çok yakın. güzel yaklaşım. Bunu düşüneceğim. İlk koddan kaçınmamın sebebi, geçici bir süre geçmemek konusunda daha özlü olmaktı. valaşağıdaki için if-statement: Bir satırda anlaşılabilir, tıpkı birinin aklında olduğu gibi. - Peter Schmitz


itibaren Tony Morris 'Lambda Blog:

Bu soruyu çok duyuyorum. Evet öyle. Yerine c ? p : q, bu   yazılı if(c) p else q.

Bu tercih edilmeyebilir. Belki de   Java ile aynı sözdizimi. Ne yazık ki, yapamazsın. Bunun nedeni ise : değil   geçerli tanımlayıcı. Korkma, | olduğunu! Buna razı olur musun?

c ? p | q

Ardından aşağıdaki koda ihtiyacınız olacak. İsme göre isme dikkat edin (=>)   argümanlar hakkında ek açıklamalar. Bu değerlendirme stratejisi   Java’nın üçlü operatörünü doğru şekilde yeniden yazabilir. Bu Java'da yapılamaz   kendisi.

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

İşte yeni tanımladığımız yeni operatörü kullanarak bir örnek:

object T {   val condition = true

  import Bool._

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

İyi eğlenceler ;)


104
2018-02-09 19:06



Evet, bunu daha önce de görmüştüm, ama fark şu ki, ilk ifademin (değerlendirilmiş) bir argümanı olarak bir argüman olarak then ve else fıkra. - Peter Schmitz
@Imre: Bağlantıyı düzelttim ve içeriği kopyaladım. - Landei
aldım if(c) p else q yaklaşım ... diş tellerinin yokluğu beni rahatsız ediyor, ama bu sadece bir şey - rjohnston


Rex Kerr’ın cevabı temel Scala'da ifade edildi:

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

if-else yapısının hangi parçasını optimize etmek istediğinizden emin değilim.


14
2018-02-09 16:52



çok düz bir şekilde. Bazen günlük kullanım eşleşmesi / vaka ifadeleri unutulur. Ben sadece bir satır üçlüye yapıştım if then else deyim, ama gerçekten çözülmesi anlaşılır bir yol. - Peter Schmitz
Pattern Eşleştirme, ikiden fazla şubeye kolayca ölçeklenir. - Raphael


Scala'daki if-else yapıları bir değer döndürdüğünden, bunu kullanabilirsiniz

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

Daha fazla bilgi: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples


2
2018-02-13 13:53





Şu andan itibaren: her zaman geri çekilişle kaçmak istemediğiniz sürece geçerli bir operatör olmayacaktır. :Başka bir karakterle gidebilirsin, ör. "|" Yukarıdaki cevaplardan birinde olduğu gibi. Ama nasıl bir keçi ile elvis hakkında? ::

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

Tabii ki, bu değerler, listelerin kendileri olduğu için listelendiklerinde işe yaramaz.


0
2018-01-25 20:43