Hullaballoonatic
12/21/2019, 4:58 PMclass Polygon(val vertices: List<Point>) {
val height by lazy { vertices.maxBy(Point::y)!!.y - vertices.minBy(Point::y)!!.y }
val width by lazy { vertices.maxBy(Point::x)!!.x - vertices.minBy(Point::x)!!.x }
val edges by lazy { (points + points.first()).zipWithNext(::Line) }
val area by lazy { edges.sumByDouble { (cur, next) -> cur.x * next.y - cur.y * next.x } / 2 } // shoelace method
val centroid by lazy {
edges.reduce(Point.Origin) { acc, (cur, next) ->
acc + ((cur + next) * (cur.x * next.y - next.x * cur.y))
}
}
// etc
}
Afaik
Advantages:
• faster instantiation
• instance fields that are never accessed are never computed
Disadvantages:
• instance fields computed when first accessed, which may be a performance heavy time
General questions:
• Does lazy<T>
occupy more space than T
? Answered: yes, it creates an object and a lambda in memory
• Is there some kind of performance impact at initialization for lazy
that may make for a negligible difference in impact for many fields?
• Am I an idiot, and unless something is rarely accessed, I should just completely avoid using lazy
?tjohnn
12/21/2019, 11:42 PMfun <T> dataAsFlow(){
//ValueEventListener impl start
val type= object : GenericTypeIndicator<List<T>>() {}
val result = dataSnapshot.getValue(type)
// emit result
//ValueEventListener impl end
}
The problem is data is getting deserialized into List<HashMap<String, String>>
instead of List<T>
. It works well if I am using the real type, say, e.g List<Category>
instead of List<T>
Slackbot
12/22/2019, 2:50 PMSiva Ganesh
12/23/2019, 3:32 AMsmallufo
12/23/2019, 9:44 AMkotlin-serialization
, I have a problem serializing interface/implementation by modules , can someone take a look at my problem on SO ? https://stackoverflow.com/questions/59453009/serializer-for-interface-implementation , thanks.Robert Jaros
12/23/2019, 11:25 PMbuild.gradle.kts
file, so I could have the whole project configuration in one file and dependencies listed in the second?Doganmiketuran
12/24/2019, 1:23 PMHolger Steinhauer [Mod]
12/24/2019, 1:24 PMMarc Knaup
12/24/2019, 2:56 PMResult
-style classes? (and sealed
vs. inline
for distinguishing cases).
I imagine plenty of object allocations.Marc Knaup
12/24/2019, 3:26 PMNothing
, but not for example class functions? Is that a bug?
This is especially confusing if this
(unexpectedly?) resolves to Nothing
because there’s not even a warning 😅
error("foo").hasSurrogatePairAt(1)
Doganmiketuran
12/24/2019, 5:23 PMDoganmiketuran
12/24/2019, 5:26 PMCzar
12/24/2019, 6:13 PMthis should pass(TestData)[1]
, not the beautiful toString result of the TestData data class like it's shown in the guide: https://phauer.com/2018/best-practices-unit-testing-kotlin/#data-classes-for-parameterized-tests
Does anyone have an idea, why is junit not printing contets of TestData? I have implemented the test exactly as in the guide.bbaldino
12/24/2019, 9:21 PMval temp = someMember
someMember = null
temp.close()
i've got multiple threads accessing someMember
(via ?.
), want to make sure it isn't accessed in between calling close()
and assigning it to null.Doganmiketuran
12/24/2019, 9:44 PMb0R1NGx
12/24/2019, 10:23 PMghedeon
12/25/2019, 11:19 AMinterface IFoo<A>
class Foo: IFoo<String>
class Bar<A>: IFoo<A>
inline fun <reified T: IFoo<*>> createBar(){
val type = T::class.supertypes[0].arguments[0].type // the type is not lost, String is here
Bar<type>() // ?? how to use it here
}
createBar<Foo>()
I know that I can declare something like fun <A, T:IFoo<A> createBar()
, but it's kind of repeating myself and the A
is already known...Doganmiketuran
12/25/2019, 12:10 PMghedeon
12/26/2019, 12:55 PMclass Holder(override val containerView: View) : ViewHolder(containerView), LayoutContainer {
fun bind() {
my_view
}
}
2.
class Holder(override val containerView: View) : ViewHolder(containerView), LayoutContainer {
fun bind() {
containerView.my_view
}
}
Matthieu Stombellini
12/26/2019, 3:28 PMsteenooo
12/26/2019, 9:40 PMOrhan Tozan
12/26/2019, 11:48 PMDavid Martin
12/27/2019, 7:33 AMChirag Prajapati
12/27/2019, 9:49 AMCzar
12/27/2019, 11:40 AMtypealias Amount = BigDecimal
to mark amounts which have proper scaling and rounding. It serves well as a markier, but unfortunately doesn't help with compile time checking. I wonder if I can instead use inline classes. The problem is there is a lot of jackson mapping and JPA Hibernate mapping going on in the application. So I wonder
will inline classes "just work" with all this mappinng?Doganmiketuran
12/27/2019, 2:20 PMDavid Glasser
12/27/2019, 6:20 PMBoolean.something<T>(f: () -> T): T? = if (this) { f() } else null
?David Glasser
12/27/2019, 6:24 PMclass Foo<T> {
fun <U> function() { ... }
}
to compile-time constraint U
to be either T
or List<T>
(subclasses of T are OK too)?Czar
12/28/2019, 2:53 PMinterface Provider {
fun <P : X> provide(name: String, clazz: KClass<out P>): P?
}
inline fun <reified P : X> Provider.provide(name: String): P? =
provide(configName, P::class)
I want to discourage use of normal provide and enable easy migration, so I put @Deprecated
annotation on it like this:
@Deprecated(
message = "Direct usage of provide(name, clazz) is discouraged",
level = DeprecationLevel.WARNING,
replaceWith = ReplaceWith(
expression = "???",
imports = ["com.example.provider.provide"]
)
)
I can't get the replacement exception right.
Say I have this in code: myProvider.provide("asdf", MyData::class)
when expression is
1. provide(name)
→ the code is replaced with provide("asdf")
- receiver is lost
2. provide<clazz>(name)
→ the code is replaced with myProvider.provide<clazz>("asdf")
I understand, that substitutor is not smart enough to decode clazz
, but when I don't specify it resulting code is even more broken.
Is this a bug?
I want the replacement to be either myProvider.provide<MyData>("asdf")
or at least myProvider.provide("asdf")
Hullaballoonatic
12/28/2019, 8:13 PMHullaballoonatic
12/28/2019, 8:13 PMitnoles
12/28/2019, 8:18 PMnfrankel
12/28/2019, 8:19 PMHullaballoonatic
12/28/2019, 8:20 PMobject
?nfrankel
12/28/2019, 8:22 PMobject
it’s about users of itAdam Powell
12/28/2019, 8:22 PMobject
itself is stateful you can't provide a constant state to things that consume it, you're at the mercy of its current internal statenfrankel
12/28/2019, 8:22 PMHullaballoonatic
12/28/2019, 8:25 PMnfrankel
12/28/2019, 8:27 PMAdam Powell
12/28/2019, 8:42 PMnfrankel
12/28/2019, 8:49 PMAdam Powell
12/28/2019, 9:16 PMnfrankel
12/28/2019, 9:19 PMno, interfaces solve thatno i write about it in my post i’m too lazy to rewrite it here... it you’ re too lazy to read, that’s fine too 😉
Adam Powell
12/28/2019, 9:20 PMnfrankel
12/28/2019, 9:20 PMAdam Powell
12/28/2019, 9:22 PMnfrankel
12/28/2019, 9:22 PMAdam Powell
12/28/2019, 9:22 PMnfrankel
12/28/2019, 9:24 PMAdam Powell
12/28/2019, 9:25 PMnfrankel
12/28/2019, 9:25 PMAdam Powell
12/28/2019, 9:26 PMnfrankel
12/28/2019, 9:26 PMat that point it’s not really “injection,” it’s just, “providing arguments to functions”imho it is with a nuance, it’s providing arguments to constructors
Adam Powell
12/28/2019, 9:27 PMnfrankel
12/28/2019, 9:28 PMAdam Powell
12/28/2019, 9:32 PMnfrankel
12/28/2019, 9:46 PMAdam Powell
12/28/2019, 9:56 PMnfrankel
12/28/2019, 10:18 PMconstructors aren’t special in particular for inverting controlagreed
Adam Powell
12/28/2019, 10:26 PMflow {}
and similar. The receiver object (which might be an interface) is provided to a block of code supplied by the caller, and that block of code is supplied to the function. If that block is a suspending lambda, it allows the caller to supply a complex policy for behavior over time with a single block of sequential code. DI frameworks and constructor injection may result in a much harder to follow solution in such cases, and both can achieve testability.nfrankel
12/28/2019, 10:28 PMAdam Powell
12/28/2019, 10:38 PMmqttClient(
mqttDialer(hostname),
clientId = clientId,
keepalive = 300,
will = Message(statusTopic, "disconnected", retain = true)
) {
send(statusTopic, "connected", retain = true, qos = Qos.AtLeastOnce)
Managing a connection to an MQTT server is wrapped up into a single suspend function call. The "dialer" function called in the first parameter returns a factory that sets up a connection and returns a socket-like object with a pair of okio sink/source objects as properties. Easy to fake a server with for testing using plain okio Buffer
objects. The trailing lambda parameter is a suspending function with a receiver interface type that implements CoroutineScope
and also offers methods to send mqtt messages (shown) and to get `Flow`s for mqtt topic subscriptions (not shown). When the body block completes and any child coroutine jobs join, the connection is torn down and the function returns. Unrecoverable errors or cancellation throw. Any part of it can be broken down pretty easily for testing and testability, and the dependencies are either provided as regular parameters or they're captured as part of the lambda body from the surrounding lexical scope.nfrankel
12/29/2019, 10:26 AMAdam Powell
12/29/2019, 5:15 PMgo
statement and kotlin's launch
, channels, etc. When you have tools like suspend
to help represent scoped behavior over time, you don't need a graph full of objects and callbacks and strategies and factories in the same waynfrankel
12/29/2019, 5:25 PMI disagree with the use of the term, “DI” to describe any sort of providing a nontrivial policy object as a parameter to a functionit’s hard to change the semantics of a agreed-upon term i think you should come up with your own
Adam Powell
12/29/2019, 5:26 PMnfrankel
12/29/2019, 5:29 PMbut you’re not the only one to use it that waythat’s my point it’s agreed upon by many easier if you come up with a term that describes your meaning
Adam Powell
12/29/2019, 5:30 PMnfrankel
12/29/2019, 11:27 PM