2017-07-28 20 views
6

WHEN maddesini > veya < karşılaştırması ile kullanmaya çalışıyorum.Kotlin'i Kullanma WHEN yan tümcesi <, <=, > =,> karşılaştırmaları

Bu, derlenmiyor. Bunu etkinleştirmek için normal bir boolean işleç kümesini (< < =,> =>) karşılaştırma yönteminin bir yolu var mı?

val foo = 2 

// doesn't compile 
when (foo) { 
    > 0 -> doSomethingWhenPositive() 
    0 -> doSomethingWhenZero() 
    < 0 -> doSomethingWhenNegative() 
} 

Sınırsız bir aralık karşılaştırması bulmayı denedim, ancak bu işi yapamadım mı? Bunu sınırsız bir aralık olarak yazmak mümkün mü?

// trying to get an unbounded range - doesn't compile 
when (foo) { 
    in 1.. -> doSomethingWhenPositive() 
    else -> doSomethingElse() 
} 

tamam ama gereksiz çoğaltma gibi görünüyor ikinci bölümünde, bütün ifadeyi koyabilirsiniz. En azından derler ve çalışır.

when { 
    foo > 0 -> doSomethingWhenPositive() 
    foo < 0 -> doSomethingWhenNegative() 
    else -> doSomethingWhenZero() 
} 

Ancak, yıllardır yaptığımız if-else alternatifinden daha kolay olduğunu emin değilim. Bir şey gibi: Tabii

if (foo > 0) { 
    doSomethingWhenPositive() 
} 
else if (foo < 0) { 
    doSomethingWhenNegative() 
} 
else { 
    doSomethingWhenZero() 
} 

, gerçek dünya problemleri üzerinde daha karmaşıktır ve WHEN fıkra çekici ama bu tür karşılaştırmalar için beklediğiniz gibi çalışmaz.

cevap

6

Kotlin gibi esnek bir dil bile, her bir durum için "zarif"/DRY çözümüne sahip değildir.

Sen gibi bir şey yazabilirsiniz:

when (foo) { 
    in 0 .. Int.MAX_VALUE -> doSomethingWhenPositive() 
    0 -> doSomethingWhenZero() 
    else -> doSomethingWhenNegative() 
} 

Ama sonra değişken türüne bağlıdır.

aşağıdaki formu KOTLIN en deyimsel olduğuna inanıyoruz:

when { 
    foo > 0 -> doSomethingWhenPositive() 
    foo == 0 -> doSomethingWhenZero() 
    else  -> doSomethingWhenNegative() 
} 

Evet ... (minimal) kodu çoğaltma yoktur.

Bazı diller (Ruby ?!) herhangi bir durum için uber-zarif bir form sağlamaya çalıştı - ancak bir dezavantaj var: dil bir programcının uçtan uca bilmesi için daha karmaşık ve daha zor hale geliyor.

whenCondition (used by whenEntry) 
    : expression 
    : ("in" | "!in") expression 
    : ("is" | "!is") type 
    ; 

Bu, yalnızca olmak gerekmez is veya in gibi özel durumlarda kullanabileceğiniz anlamına gelir şu şekildedir:

Benim 2 sent

...

3

bir when durum için grammar olduğunu tam bir ifade; her şey normal bir ifade olmalı. > 0 geçerli bir ifade olmadığı için bu derleme yapılmayacaktır. Ayrıca, aralıklar Kotlin'de kapalıdır, bu nedenle sınırsız bir aralık kullanmaya çalışmaktan kurtulamazsınız.

Onun yerine, sen örnekte olduğu gibi tam bir ifade ile when deyimini kullanmalısınız: alternatif

when { 
    foo > 0 -> doSomethingWhenPositive() 
    foo < 0 -> doSomethingWhenNegative() 
    else -> doSomethingWhenZero() 
} 

Veya:

when { 
    foo < 0 -> doSomethingWhenNegative() 
    foo == 0 -> doSomethingWhenZero()   
    foo > 0 -> doSomethingWhenPositive()   
} 

daha okunabilir olabilen.

+0

Dilbilgisini görmek ilginç. Yani ilk 'ifade ', booleanı döndüren bir ifade olması gerektiği gibi görünüyor, bu benim derlediğim örnekte kullandığım şey. Bu doğru mu. "In" cümlesiyle ikinci ifade, bir tür koleksiyon döndüren bir ifadedir ve "olan" sadece bir tür bildiridir. Sağ? Her neyse, her vaka için tam ifadenin burada en temiz seçenek olduğunu tahmin edin. –

1

Kodunuzun zarif olmasını istiyorsunuz, bu nedenle neden when ifadesinde kalın. Kotlin uzantısı kullanarak yeni bir tane inşa etmek için yeterince esnektir.

Öncelikle Comparable<T> kodunu iletebileceğimizi bildirmeliyiz çünkü değerini karşılaştırması yapmanız gerekiyor. Eğer mutluysan

case("g") { 
    (it is String) - { println("hello") } // normal comparison, like `is` 
    outside("gg") - { println("gg again") } // invoking the contains method 
} 

case(233) { 
    lt(500) - { println("less than 500!") } 
    // etc. 
} 

, sen compareTo ve getiri minus fonksiyonunu yeniden adlandırabilirsiniz: gibi biz zarif bir kod olabilir Bundan sonra

fun <T: Comparable<T>> case(target: T, tester: Tester<T>.() -> Unit) { 
    val test = Tester(target) 
    test.tester() 
    test.funFiltered?.invoke() ?: return 
} 
class Tester<T : Comparable<T>>(val it: T) { 
    var funFiltered: (() -> Unit)? = null 
    infix operator fun Boolean.minus(block:() -> Unit) { 
     if (this && funFiltered == null) funFiltered = block 
    } 

    fun lt(arg: T) = it < arg 
    fun gt(arg: T) = it > arg 
    fun ge(arg: T) = it >= arg 
    fun le(arg: T) = it <= arg 
    fun eq(arg: T) = it == arg 
    fun ne(arg: T) = it != arg 
    fun inside(arg: Collection<T>) = it in arg 
    fun inside(arg: String) = it as String in arg 
    fun outside(arg: Collection<T>) = it !in arg 
    fun outside(arg: String) = it as String !in arg 
} 

: Sonra

, bizim çerçeveye sahip 0. Böylelikle -'u scala gibi görünen => ile değiştirebilirsiniz.

+0

Bu, ihtiyacım olandan biraz daha karmaşık bir şey yapmanın kullanışlı bir örneğidir. Ben sadece standart WHEN cümleciğini kullanmayı planlıyorum, ancak benzer bir doğaya daha çok karışmış bir şey için bu örneğe başvurmak isteyebilirim. –

+1

Bu çerçeve ölçeklenebilir, desen eşleştirme gibi birçok şekilde genişletebilirsiniz. – ice1000

İlgili konular