https://kotlinlang.org logo
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
language-proposals
  • m

    Marc Knaup

    11/30/2020, 12:33 PM
    Idea: auto-generated
    equals()
    implementation for lambdas.
    Button(
        label = "Print count",
        onClick = @Equatable { println(count) }
    )
    
    data class ButtonProps(val label: String, val onClick: () -> Unit)
    That’s useful in Kotlin React development and similar. If the props (arguments) of a component are equal between two rendering attempts then the second rendering can be skipped (memoization). Unfortunately that doesn’t work if the props contain lambdas because they’ll never be equal to the previous instance. React provides a workaround like
    val onClick = useCallback(count) { println(count) }
    which only uses the passed instance of the lambda if
    count
    has changed and the previous one otherwise. This is more boilerplate and you have to move the lambda further away from where it’s actually used. More importantly it easily leads to errors where you forget to add a dependency (a bound variable) and therefor an old function with different variable bindings will be used.
    @Equatable
    could tell the compiler to generate an
    equals
    method for that lambda which compares all bound variables automatically - in this case
    count
    . That would solve the issue and eliminate that cause of errors.
    d
    y
    • 3
    • 8
  • y

    Yash Grover

    12/04/2020, 1:18 PM
    I think we should be able to add multiple conditions with the
    else
    block too. I once faced a situation where a choice and fallback led to the same action. So I thought this might be something nice to have. Something like this
    fun main():Unit{
        var a = 5
        when(a){
            1,2-> print("Case 1")
            5,else -> print("Fallback")
        }	
    }
    I don't know if this has been discussed before so I thought I should ask about the suggestion here.
    🤔 2
    ➕ 3
    d
    • 2
    • 2
  • s

    samuel

    12/15/2020, 2:04 PM
    Something that could “help” improve some scenarios using DSL would be to possibly infer the receiver for infix function when the receiver is “directly” available, for example:
    class SomeClass() {
        infix fun SomeClass.someFunction (someParam: SomeType) {
            // some code
        }
    }
    
    fun inSomeClass(action: SomeClass.() -> Unit) {
        SomeClass().action()
    }
    
    inSomeClass { 
        this someFunction "param"
        someFunction "param" // Receiver could possibly implied
    }
    l
    • 2
    • 2
  • l

    louiscad

    12/15/2020, 10:30 PM
    Union types: They can be introduces in a limited, yet useful way: In the only place where we also have intersection types, which is the
    where
    clause that specifies type arguments constraints for a function. I think that would satisfy many use cases where we currently write multiple functions (often extensions). The
    when
    expression would also need to be tweaked to make use of this I think, and probably some compiler magic, and maybe
    @JvmOverloads
    , unless these functions are required to have the union type constrained generic argument to be
    reified
    , which requires the function to be
    inline
    , and always inlining the code.
    ➕ 1
    i
    a
    +2
    • 5
    • 8
  • m

    Marc Knaup

    12/16/2020, 4:24 PM
    It would be amazing if we could reference to generic arguments of a type.
    interface Box<out Value> { val value: Value }
    class IntBox(override val value: Int): Box<Int>
    
    val value: IntBox.Value = 1 // IntBox.Value is basically an alias for Int
    This would be very useful in generic contexts:
    interface Operation<out Result>
    
    interface OperationExecutor<in TOperation : Operation<*>> {
        suspend fun execute(operation: TOperation): TOperation.Result // <<< here
    }
    
    
    class IntToStringOperation(val value: Int) : Operation<String>
    
    object IntToStringOperationExecutor : OperationExecutor<IntToStringOperation> {
    
        override suspend fun execute(operation: IntToStringOperation): String =
            operation.value.toString()
    }
    Currently we’d have to introduce a second type argument for that which makes generics more complicated to at the use-site:
    interface OperationExecutor<TOperation : Operation<Result>, Result>
    
    object IntToStringOperationExecutor : OperationExecutor<IntToStringOperation, Int>
    (same for generic functions)
    👍 1
    r
    • 2
    • 1
  • m

    Marc Knaup

    12/23/2020, 5:27 PM
    It would be great to have this:
    val Foo.property = "foo"
    as syntactic sugar for something like that:
    private const val _foo = "foo"
    val Foo.property get() = _foo
    Typically such a construct is used when the value • is computed and must not change between invocations • is expensive to compute even if pure For example:
    // avoid that value changes
    val Foo.staticProperty = generateRandomId()
    
     // avoid repeated expensive computation
    val Foo.expensiveProperty = someExpensiveSetup()
    
     // avoid temporary object creation
    val Foo.someComplexData = SomeComplexData(…)
    val Foo.someDependentProp1 get() = someComplexData.prop1
    val Foo.someDependentProp2 get() = someComplexData.prop2
    val Foo.someDependentProp3 get() = someComplexData.prop3
    val Foo.someDependentProp4 get() = someComplexData.prop4
    Because such a value is static, i.e. independent of the actual instance of
    Foo
    , you can’t use
    this
    in that context except for referring to other such static values or if the receiver is an
    object
    . I personally use such properties often in two situations: • add static values to an
    object
    or
    companion object
    • add static values to marker interfaces (e.g. for DSL)
    ➕ 1
    j
    d
    • 3
    • 8
  • m

    Marc Knaup

    12/27/2020, 4:32 PM
    It would be helpful if we can a) access the companion object of the class of an instance without using reflection, and a) define that a type implementing an interface must also have their companion object implement a specific interface.
    interface WithCompanion<T : Any>
    
    fun <T : Any> companionOf(instance: WithCompanion<T>): T =
        TODO() // intrinsic
    Now the following would be possible:
    interface FooInterface: WithCompanion<Any>
    
    fun bar(foo: FooInterface) {
       val companion: Any = companionOf(foo)
       // …
    }
    Which would be very useful for a frequent pattern, where you have instances of something that has a shared definition across all instances:
    // Types implement `Event` must also have their companion implement `Event.Type`
    interface Event : WithCompanion<Event.Type> {
        interface Type {
            val id: String
        }
    }
    
    // We can get the companion of an Event instance without reflection.
    val Event.type get() = companionOf(this)
    
    // Example
    class SunriseEvent : Event {
        companion object : Event.Type {
            override val id = "sunrise"
        }
    }
    
    fun storeEvent(event: Event) {
         // Not possible like this at the moment without manually adding `type` to every single class implementing `Event` 
        val typeId = event.type.id
        // …
    }
    👍 1
    r
    h
    d
    • 4
    • 8
  • m

    Marc Knaup

    01/01/2021, 8:10 PM
    I suggest that
    object
    types automatically satisfy
    equals
    and
    hashCode
    requirements of an interface/superclass.
    object
    types are typically equal to themselves and have a hash code based on their instance automatically which is sufficient. I can only think of very very few exceptions where you would want an object to not be equal to itself or have some custom implementation 🤔
    interface Foo {
        override fun equals(other: Any?): Boolean
        override fun hashCode(): Int
    }
    
    data class Bar1(val bar: Int) : Foo // fine
    object Bar2 : Foo // error because equals() and hashCode() are missing
    I’m often using explicit abstract
    equals
    and
    hashCode
    to not forget to provide an implementation in implementing types. Typically I use
    data class
    or
    object
    but it’s too easy to forget the
    data
    .
    g
    l
    m
    • 4
    • 5
  • m

    Marc Knaup

    01/12/2021, 1:23 PM
    It would be really nice for DSLs to be able to overload assignments to a String 🙃 Dynamic configuration in this particular case.
    👍 1
    👎 4
    o
    h
    +4
    • 7
    • 51
  • j

    Javier

    01/13/2021, 5:21 PM
    Should be great that
    typealias
    for annotations could be shortcuts for annotatinos with params, sample:
    typealias ViewModelInject = Inject(param1 = param1, param2 = param2, ...) // doesn't work
    I think it is only possible to do
    typealias ViewModelInject = Inject
    j
    • 2
    • 2
  • p

    pablisco

    01/18/2021, 6:25 PM
    Currently, when using sealed types in Kotlin we get auto cast on the subject of the clause. However, if we have something like this:
    sealed class Input<A> {
      object ForInt : Input<Int>()
      object ForString : Input<String>()
      object ForDouble : Input<Double>()
    }
    
    fun <A> process(input: Input<A>): A = when(input) {
      ForInt -> fetchInt() // returns Int
      ForString -> fetchString() // returns String
      ForDouble -> fetchDouble() // returns Double
    }
    This won’t compile, despite being correct. One way to solve it is like this:
    @Suppress("UNCHECKED_CAST")
    fun <A> process(input: Input<A>): A = when(input) {
        ForInt -> fetchInt() // returns Int
        ForString -> fetchString() // returns String
        ForDouble -> fetchDouble() // returns Double
    } as A
    The problem with this is that now we get rid of all type safety since we can return any values, which can result on fun runtime errors. We have all the information there, so I think the compiler should be able to infer the type from the input and the case and tell us if we are returning the right type or not :) Is there any plan to support auto cast on the result of a when clause like this? If not, I’ll happily create a KEEP for it.
    l
    h
    r
    • 4
    • 11
  • y

    Youssef Shoaib [MOD]

    01/23/2021, 1:54 PM
    This is more of a missing optimisation that it is a feature per se, but it's still quite useful. Currently when you have a very simplistic usecase like this:
    inline fun <T> identity(block: () -> T): () -> T = block
    inline fun <T> perform(block: () -> T): T = block()
    fun main() {
        println(perform(identity { "hello" })
    }
    A useless lambda object gets created due to the compiler believing that because the lambda is returned by
    identity
    then it must exist as an actual object. This prevents certain wrapping tricks for lambdas that can provide interesting behaviours without overhead (think for example a lambda being passed into multiple functions one by one that affect whether it executes or not and even does
    suspend
    calls in between and ultimately gets inlined into the call site directly with all that new behaviour being abstracted away from the user). I propose that, whenever you have a lambda being returned by an
    inline
    function, and all of the subsequent usages of that lambda are only passed as
    inline
    parameters, that the lambda gets entirely inlined through all of the inline functions that calls it and ultimately ends up at the call site with all of the wrapping code from the
    inline
    functions around it, just as if you used that exact lambda but rewrote the functions to pass it down instead. Effectively, the above usecase would get compiled down into roughly the equivalent of this:
    fun main () {
        println("hello")
    }
    I'd love to know if there's anything currently preventing this from working as expected, because it seems to me that the current inline mechanism should be enough. Yes this will probably mess up debugging possibly, but that could be circumvented just as if you would debug an inline function today. This is basically just inversing the call stack in a way of how you would do this normally and allows for better decomposition. For example, the usecase above can currently be rewritten to this:
    inline fun <T> identity(block: () -> T): T = block()
    inline fun <T> perform(block: () -> T): T = identity(block)
    fun main() {
        println(perform { "hello" })
    }
    and if you imagine this with actual logic surrounding the lambdas you can basically recreate any example of that form, but it ruins composability and requires the lambda call to always be at the very very bottom of the call hierarchy instead of allowing for more complex lambda-returning functions with no overhead. For another example, consider this maybe:
    val shouldPerform = true
    val shouldRunSpecial = true 
    inline fun <T> specialLogic(block: () -> T): () -> T? = if(shouldRunSpecial) block else { null } // can also be converted to one big lambda instead that does the check on shouldRunSpecial when it's actually called like this: = { if(shouldRunSpecial) block() else null }. Those 2 styles should be roughly equal in the end since all the lambdas get inlined
    inline fun <T> performOrThrow(block: () -> T): T = if(shouldPerform) block() else TODO()
    fun main() {
        println(perform(specialLogic { "hello" })
    }
    // Turns into this:
    fun main() {
        println(
            if(shouldPerform) {
                if (shouldRunSpecial) "hello" 
                else null 
            } 
            else TODO())
    }
    This is currently what this code runs like logically today, but the only difference is that it'll be all inlined without the need for any lambda objects. Keep in mind that the object itself will need to materialise if it gets used in a non-inline context (i.e. if you pass it to a regular function or query its class for example). This could possibly be extended to fun interfaces themselves being inlined if you use a lambda to call them and then pass them to an inline function, which can have a lot of great impacts for some functional abstractions since it allows you to, for example, have a reference to a
    fun interface Functor
    that gets passed around to only inline functions and in the actual compiled code completely disappears since it isn't needed in any non-inlined contexts. I'm sure the Arrow team and other similar functional proponents would be interested in this because it decreases the cost of those functional abstractions even more (Note: if this can result in some backwards-compatibility issues, then this can instead be a new feature under the name
    inline fun interface
    that works similarly to inline classes but utilises the fact that lambdas that are used in only inline contexts don't ever need to be actual objects and can instead just be copied and inlined everywhere at compile time). I do realise that this is kind of multiple proposals in one but these 2 features are very connected and kinda go hand in hand because they require similar compile-time machinery, however I personally think that at the very least the first one should be implemented first if it isn't possible to implement both at the moment because then libraries like Arrow can temporarily sacrifice some of the type safety that
    fun interface
    brings in lieu of the optimisation of regular lambdas being inlined when returned by a function. If the whole
    inline fun interface
    idea just sounds too compilcated, then instead we could possibly have `inline class`es with lambdas for their backing field that also receive the same optimisations in this proposal of inlining lambdas along with type safety of course. Personally however I think that
    inline fun interface
    s make more sense because they mirror how inline functions look like. Any thoughts or criticisms about this are greatly appreciated😄! Again I'd love to know if I made an oversight here and if this could even be impossible, so don't hesitate to point out any flaws in my reasonings.
    i
    • 2
    • 10
  • a

    aerb

    02/05/2021, 11:19 PM
    I just had a thought about a possibly useful extension of the Delegation feature. This is mostly in service of testing, but it would be handy to have a keyword (
    throwing
    ?) where the compiler auto-generates interface implementations that just
    throw
    , but that you have an option to override. This would basically be for creating fakes on massive interfaces without reflection proxying. Eg:
    class FakeConnection : java.sql.Connection by throwing {
      override fun prepareCall(sql: String) {
        // ... some assertion.
      } 
    }
    I definitely see potential for abuse, but in a testing context super handy.
    ➕ 1
    j
    • 2
    • 1
  • n

    Nico

    02/10/2021, 9:07 PM
    I understand one of the main setbacks of KEEP-213 (and destructuring as it is now in the language, really) is positional vs nominal access to data, as well as Java interop. I was wondering what people might think of a nominal pattern matching approach which could possibly look like the following (taking over @jw 's original example):
    sealed class Download
    data class App(val name: String, val developer: Developer) : Download()
    data class Movie(val title: String, val director: Person) : Download()
    val download: Download = // ...
    
    // placeholder syntax
    val result = when(download) {
      is App(.name, .developer: Person(val devName = .name))
        if (devName == "Alice") -> "Alice's app $name"
      is Movie(.title, .director: Person(val dirName = .name))
        if (dirName == "Alice") -> "Alice's movie $name"
      is App, Movie -> "Not by Alice"
    }
    Note how - Matching is purely nominal thanks to a 'access' operator (I chose
    .
    but could be
    &
    or nothing at all, really) - Nested patterns are achieved using
    :
    for a 'is-of-type' relation - Destructured properties (like
    .name
    ) are made available in the RHS of the
    when
    clause - Properties can be desambiguated by explicitly declaring new variables for them - Guards can be used to match for equality - Proposed syntax is in the spirit of https://youtrack.jetbrains.com/issue/KT-21661 or https://youtrack.jetbrains.com/issue/KT-44729 If deconstruction in Java is implemented as described in https://github.com/openjdk/amber-docs/blob/master/eg-drafts/deconstruction-patterns-records-and-classes.md#translation, the deconstructed parameters could correspond to the names of those of the record that
    <deconstruct>()
    returns
    ➕ 3
    e
    a
    • 3
    • 7
  • a

    aerb

    02/12/2021, 6:27 PM
    Regex literals so
    Regex("\\s\\\\")
    becomes
    r"\s\\"
    ?
    e
    d
    • 3
    • 9
  • s

    stantronic

    02/23/2021, 12:23 PM
    Is kotlin meant to support file-private typealiases currently? If not it could be a nice feature. I can write
    private typealias Binding = ItemRotaBinding
    in the IDE without lint errors, but then when I try to create another one (e.g.
    private typealias Binding = ItemShiftBinding
    ) in an adjacent file, it complains about redeclaration
    a
    i
    • 3
    • 7
  • r

    Ruckus

    02/23/2021, 6:21 PM
    Proposal: Allow named parameters in
    get
    and
    set
    operators Currently, you can have default parameters in
    get
    and
    set
    operators, but you cannot address them out of order. For example, given this:
    class Thing<T>(...) {
        operator fun set(coordinates: IntArray, depth: Int = this.depth, isDestructive: Boolean = true, value: T) { ... }
    }
    Which allows this:
    thing[coordinates] = value
    But it would be nice to be able to do this:
    thing[coordinates, isDestructive = false] = value
    However, there doesn't appear to be a way to do so. Instead, I'm stuck either adding a second
    set
    operator, or doing
    thing[coordinates, thing.depth, false] = value
    (Which only works assuming
    thing.depth
    is accessible. If not, and there isn't an overloaded
    set
    operator, I don't believe it's possible.) Yes, I am aware this can be simply worked around by calling the set function directly and not using the operator, which is why this is a proposal and not a bug report.
    ➕ 2
    k
    • 2
    • 2
  • z

    Zach Klippenstein (he/him) [MOD]

    02/23/2021, 9:20 PM
    Has anyone built a compiler plugin that gives lambdas & anonymous functions more meaningful implementations of `equals`/`hashcode`/`toString`? I work with a lot of code that creates data classes to hold both data and functions (event handlers), and it would be great to actually define lambda equality in a meaningful way. Especially in tests, debugging output, etc. I’ve put some ideas into a twitter thread and as great an excuse as this would be to learn the IR plugin API, would love to just play with someone else’s if it exists.
    e
    • 2
    • 9
  • k

    Kevin K

    02/25/2021, 4:30 AM
    Hello, I've been working with the experimental time measurement API recently. I like how the API provides the
    measureTimedValue
    method to measure time while still allowing capture of the code block result. I found it a little cumbersome to work with the
    TimedValue
    result though; it isn't very fluent. I made this extension function to help, and I was thinking maybe it would be a good addition to the API?
    @ExperimentalTime
    inline fun <T> TimedValue<T>.capture(block: (Duration) -> Unit): T {
        block(duration)
        return value
    }
    
    @ExperimentalTime
    fun main() {
        // Without the capture function
        val (result, duration) = measureTimedValue {
            Thread.sleep(500)
            "foobar"
        }
        println("Duration: $duration")
        println("Result: $result")
    
    
        // With the capture function
        measureTimedValue {
            Thread.sleep(500)
            "foobar"
        }.capture {
            println("Duration: $it")
        }.also {
            println("Result: $it")
        }
    }
    (P.S. - I'm not very satisfied with the name
    capture
    ...feel like there's definitely a better word to use, just can't think of it)
    r
    i
    e
    • 4
    • 9
  • d

    deviant

    03/12/2021, 2:20 PM
    hey guys! i'm playing with flutter now. and found dart lang pretty interesting. have anything from this list considered as future kotlin feature? https://www.netguru.com/codestories/dart-from-kotli-perspective particularly i'm interested in spread operator and collection literals.
    b
    i
    • 3
    • 2
  • m

    melatonina

    03/15/2021, 9:07 AM
    Hello. Is this kind of syntax (or something similar) already been discussed? The purpose is saving nested let expressions when we want an expression to be be null if any one of a set variables on which it depends are null:
    fun f(a: A, b: B): T = TODO()
    
    fun g(a: A?, b: B?) {
        val x = f(a?, b?)
    }
    where
    x
    has type
    T?
    and is
    null
    if either a or b or both are
    null
    , instead of
    fun g(a: A?, b: B?) {
        val x = a?.let { actualA -> b?.let { actualB -> f(actualA, actualB) } }
    }
    or
    fun g(a: A?, b: B?) {
        val x = if (a != null && b != null) f(a, b) else null
    }
    which would not work if
    a
    or
    b
    were
    var
    , or
    fun g(a: A?, b: B?) {
        val x = a?.let { b?.let { f(a, b) } }
    }
    which is a bit silly and would not work if
    a
    or
    b
    were
    var
    . Not groundbreaking but I often would like it.
    k
    u
    +2
    • 5
    • 11
  • b

    Ben Woodworth

    03/29/2021, 5:29 PM
    How about default class implementations for interfaces? Especially when it comes to composition/delegation, this is a common pattern I see:
    interface SomeTrait { ... }
    
    private class SomeTraitImpl(...) : SomeTrait { ... }
    
    fun SomeTrait(...): SomeTrait = SomeTraitImpl(...)
    And used like this:
    class MyClass : SomeTrait by SomeTrait(...)
    
    // Or just used to get an instance of the default implementation:
    val trait = SomeTrait(...)
    What if a default implementation could be given, something like this:
    interface SomeTrait {
        ...
    
        default class(...) { // Optional name, like companion objects. Implicitly implements SomeTrait.
            ...
        }
    }
    
    // No need for a pseudo-constructor function:
    val trait = SomeTrait(...) // gets an instance of the default class
    Maybe treat "extending" this interface as delegation to the default implementation:
    class MyClass : SomeTrait(...)
    
    // Desugars to:
    class MyClass : SomeTrait by SomeTrait(...)
    It'd probably just be unnecessary added complexity to the language, but it seems like it has potential to simplify some things, it avoids the whole
    *Impl
    naming controversy, and it's definitely fun to consider :)
    h
    a
    +2
    • 5
    • 10
  • h

    hfhbd

    04/10/2021, 9:36 AM
    Hey, after the seeing the change in https://github.com/Kotlin/KEEP/issues/190 and the discussion about
    2.days or Duration.days(2)
    I would bring a pitch solving this design:
    val timeToFix: Duration = .days(2)
    This design is used in Swift. In Swift, every static function (or enum case) can be called by using a short dot annotation. This is also useful in function parameters
    fun something(r: Result<String>) { }
    
    something(.success("Hello")
    In Kotlin, there are no static functions, but there is a
    companion object
    . All functions of the companion object could be called using this syntax.
    ➖ 2
    e
    • 2
    • 2
  • f

    Fleshgrinder

    04/10/2021, 4:46 PM
    I am really missing a standard feature of other languages in Kotlin, and that is the ability to escape the line feed in a multiline string. I can do this easily in e.g. Bash or Python but there really is no nice solution in Kotlin. Especially not because line feeds are platform dependent (
    \n
    vs
    \r\n
    ). Basically what we should have:
    println("""\
    This is the first line in this \
    multi-line string.
    
    This is the second line in this \
    multi-line string.
    """)
    The above would result in:
    This is the first line in this multi-line string.
    
    This is the second line in this multi-line string.
    I guess the fact that the backslash has no special meaning in multi-line strings today would be a blocker for this, because it suddenly would need to be escaped and existing code would break. At the same time it would have been nice to use it as escaper so that we could simply write
    \$
    instead of
    ${'$'}
    but too late. I fear an alternative approach is needed here. Maybe
    f""
    for a multi-line string with normal escape behavior (so
    \"
    needs to be used). 🤔 Anyways, just wanted to get this off my chest.
    ➕ 1
    e
    l
    • 3
    • 7
  • e

    eduardog3000

    04/16/2021, 2:37 PM
    Proposal: An elvis type operator that catches exceptions. Example and proposed syntax:
    exampleString.toInt() !: -1
    👀 1
    e
    l
    +3
    • 6
    • 7
  • c

    Christian Dräger

    04/22/2021, 7:09 PM
    I am writing a DSL that allows to parse HTML in kotlin.
    (example: <https://github.com/skrapeit/skrape.it#parse-and-verify-html-from-string>)    
    since *  is common to use in this context (e.g. when it comes to css selectors) it would feel natural if the DSL could do as well. Therefore it would be handy if it would be possible to overload a unaryTimes operator.
    since kotlin already supports unaryPlus and unaryMinus overload, why there isn't a unaryTimes?
    here is an example what it looks like right now:
    @Test
    fun `can parse html from String`() {
        htmlDocument("""
            <html>
                <body>
                    <h1>welcome</h1>
                    <div>
                        <p>first p-element</p>
                        <p class="foo">some p-element</p>
                        <p class="foo">last p-element</p>
                    </div>
                </body>
            </html>""") {
            h1 {
                findFirst {
                    text toBe "welcome"
                }
                p {
                    withClass = "foo"
                    findSecond {
                        text toBe "some p-element"
                        className  toBe "foo"
                    }
                }
                p {
                    findAll {
                        text toContain "p-element"
                    }
                    findLast {
                        text toBe "last p-element"
                    }
                }
            }
        }
    }
    i think this should be possible right now by making * an infix operator?
    @Test
    fun `can parse html from String`() {
        htmlDocument("""
        <html>
            <body>
                <h1>welcome</h1>
                <div>
                    <p>first p-element</p>
                    <p class="foo">some p-element</p>
                    <p class="foo">last p-element</p>
                </div>
            </body>
        </html>""") {
            h1 {
                find 0 {
                text toBe "welcome"
            }
                p {
                    withClass = "foo"
                    find 1 {
                        text toBe "some p-element"
                        className  toBe "foo"
                    }
                }
                p {
                    find * {
                        text toContain "p-element"
                    }
                    findLast {
                        text toBe "last p-element"
                    }
                }
            }
        }
    }
    what would be possible due to the proposal of having unaryTimes operator to overload:
    @Test
    fun `can parse html from String`() {
        htmlDocument("""
        <html>
            <body>
                <h1>welcome</h1>
                <div>
                    <p>first p-element</p>
                    <p class="foo">some p-element</p>
                    <p class="foo">last p-element</p>
                </div>
            </body>
        </html>""") {
            h1 {
                0 { // already possible by invoke operator
                    text toBe "welcome"
                }
                p {
                    withClass = "foo"
                    1 {
                        text toBe "some p-element"
                        className  toBe "foo"
                    }
                }
                p {
                    * { // would need unaryTimes
                    text toContain "p-element"
                }
                    findLast {
                        text toBe "last p-element"
                    }
                }
            }
        }
    }
    j
    n
    +2
    • 5
    • 13
  • s

    spand

    04/23/2021, 7:54 AM
    I posted in general with no response so I assume its missing. I think it could be useful to be able to remove the nullability of a generic type. Sort of the opposite of 
    T?
     . Here I invented the 
    T!!
     type operator for it. Should be clear from the example here why it could be useful.
    interface LoadingCache<K : Any, V> {
        fun get(key: K): V // <-- If it can return null then it must be specified by type V
    
        // If load returns null then entries are missing hence it doesnt make sense to have here : Map<K,V?>
        fun getAll(keys: Iterable<K>): Map<K, V!!> {
            return keys.mapNotNull { k -> get(k)?.let { k to it } }.toMap()
        }
    }
    Thoughts ?
    t
    r
    +2
    • 5
    • 27
  • m

    mikehearn

    05/12/2021, 2:53 PM
    Hello. I'm curious why convenient array/list syntax [] is still restricted to annotation context only and why being able to use it everywhere doesn't seem to attract much interest (e.g. not on roadmap). Collection literals are a very common thing and this is one of the rare places where Kotlin is a lot more verbose than other languages.
    j
    r
    +9
    • 12
    • 45
  • m

    Marc Knaup

    06/03/2021, 6:16 PM
    Random idea: `test class`/`test object` (or alike) for testing that only optionally implements
    abstract
    functions and properties. If an unimplemented one is called it throws a
    NotImplementedError
    . Ex. unit test for `FooCreator`:
    interface FooRepository {
       fun add(foo: Foo)
       fun get(id: String): Foo?
       fun delete(id: String)
    }
    
    var actual: Foo? = null
    val creator = FooCreator(repository = test object : FooRepository {
       override fun add(foo: Foo) {
          assertNull(actual)
          actual = foo
       }
    })
    
    creator.create(id = "bar")
    assertEquals(actual, Foo(id = "bar"))
    Alternatively full-fledged mocking of abstract funs/props and setters to set/unset each implementation.
    e
    s
    +3
    • 6
    • 11
  • u

    ushort

    06/19/2021, 3:19 PM
    Not sure if something like this would be possible, but seems like possibly nice idea. Would let you only access foo within it's scope versus having to declare outside or reusing.
    if (val foo = someClass.someProperty == 1) {
                // can access foo here
            }
    d
    • 2
    • 2
Powered by Linen
Title
u

ushort

06/19/2021, 3:19 PM
Not sure if something like this would be possible, but seems like possibly nice idea. Would let you only access foo within it's scope versus having to declare outside or reusing.
if (val foo = someClass.someProperty == 1) {
            // can access foo here
        }
d

dmitriy.novozhilov

06/19/2021, 3:37 PM
Your syntax is very hard to read. Intuitively
val foo = someClass.someProperty == 1
reads as
val foo = (someClass.someProperty == 1)
, not
(val foo = someClass.someProperty) == 1
(like
val
declaration in
when
) If you really don't want to intoduce
foo
to outer scope you can use some scope function
someClass.someProperty.let { foo -> 
    if (foo == 1) { ... }
}
or just replace
if
with
when
when (val foo = someClass.someProperty) {
    1 -> ...
}
u

ushort

06/19/2021, 3:40 PM
Ah fair enough didn't think about it as assigning the condition, can see how that's easily misunderstood.
View count: 2