https://kotlinlang.org logo
#feed
Title
# feed
j

jmfayard

09/15/2019, 5:25 PM
Small programming pearl for Kotliners: Discover the life-changing magic of tidying up code
with(ConfigObject) { ... }
https://dev.to/jmfayard/with-configobject-language-kotlin-issparkingjoy-ic4
t

Trevor

09/16/2019, 5:59 PM
Where's a use-case where
with(something) {...}
is more appropriate than
something.apply {...}
?
Both are interesting, I've only ever used
apply
cause I didn't know about
with
, so curious if there's a place where I should be using
with
specifically
j

jmfayard

09/16/2019, 6:02 PM
well… this is what I wrote an article about: a scope for putting all your constants, functions and extension functions. If you prefer apply I don’t mind
t

Trevor

09/16/2019, 6:09 PM
Oh no preference! They definitely look different, and somehow
with(someDbQuery) { setParameter(...) }
looks nicer, I've just always used
apply
cause I didn't know about
with
! Just curious if there is an idiomatic preference or if they're really just interchangeable
c

Casey Brooks

09/16/2019, 6:23 PM
There’s a semantic difference between
with
and
apply
.
apply
is used for configuring an object by setting it as the receiver.
with
is for “stepping into the scope” of an object to access its members while doing something else. You’d more commonly see
with
as a function expression, and
apply
tacked onto the return value of a function or expression
👍 1
t

Trevor

09/16/2019, 6:32 PM
ah gotcha, thanks!
s

suresh

09/16/2019, 9:16 PM
with
is for “stepping into the scope” of an object
I don’t get this part. Both
with
and
apply
do stepping into the scope and it’s clear from their function signature.
with(receiver: T, block: T.() -> R): R
T.apply(block: T.() -> Unit): T
IMHO, the main difference is, with
with()
function you can return any value (which is returned by the lambda) if it’s used in an expression but apply always returns
this
.
with(ConfigObject) { ... }
pattern can also be used with
apply
Copy code
object Config {
    const val NAME = "KOTLIN"
    fun String.isAJoy() = println("Language $NAME is awesome!")
}

fun main() {
    Config.apply {
       NAME.isAJoy()
    }
}
c

Casey Brooks

09/16/2019, 9:30 PM
Right, the signatures of both are nearly the same, but the semantic meaning of them is different, and they should not be treated as interchangeable.
with
implies that you are entering into a specific “scope”, for the purposes of doing stuff within that scope.
apply
is technically “stepping into a scope” because the object is set as the receiver, but the meaning behind it isn’t to enter a scope and do stuff within that scope. The meaning of
apply
is that you are succinctly applying values to the receiver object.
Copy code
class FactoryObject {
    var one: String = ""
    var two: String = ""
    var three: String = ""
}

// apply values to FactoryObject, and return that object. 
// Semantically, you're returning a value, and modifying 
// it right before returning it. Within the scope of
// FactoryObject, you're setting values, but not really
// "doing stuff"
fun createObject_Apply() = FactoryObject().apply {
    one = ""
    two = ""
    two = ""
}

// looks pretty much like the other, but it returns 
// Unit. You've "stepped into the scope" of FactoryObject,
// and inside there you're expected to _do_ stuff, not 
// _set_ stuff. Whatever you're doing is free to return
// any value it needs, just as if it were any other function
fun createObject_With() = with(FactoryObject()) {
    one = ""
    two = ""
    two = ""
}
3 Views