Guys, is there any chance that top-level propertie...
# language-proposals
g
Guys, is there any chance that top-level properties’ initialization could be deferred, just like in case of local variables?? Apple’s Swift works this way, and I find it very convenient and consistent, compared to what we have in Kotlin (there’s
lateinit
, but it only works with `var`s and non-primitive types). What I mean is that ALL properties (val, var, objects, primitives) could be defined without the initial value. And in case of accessing non-initialized property we would get an error, e.g. “variable ‘x’ used before being initialized”
1
3
k
Perhaps you’re looking for
Delegates.notNull
? By the way, this isn’t really a language proposal
b
Wait, it doesn't work this way?! Also this is totally a language proposal, @kingsley, just not a syntax one
g
@kingsley hi 🙂 of course it is (a proposal). if implemented, this would basically change the way properties work
k
What? You want runtime exceptions for things like this?
g
@benleggiero no it doesn’t work this way 😞
😞 1
@karelpeeters yup, I think I would prefer them and much cleaner syntax, in favour of
lateinit var
/
var
+ providing dumb default values / not being able to use `val`s in many cases - hell that I encounter right now 😕
k
Might as well throw null safety away then. The point of
lateinit
that it is for exceptional circumstances and it screams "unsafe".
k
Yes.
lateinit
only works with non-nullable, non-primitive types. But you didn’t say
Delegates.notNull
doesn’t solve your problem.
ALL properties (val, var, objects, primitives) could be defined without the initial value. And in case of accessing non-initialized property we would get an error, e.g. “variable ‘x’ used before being initialized
g
@kingsley Delegates.notNull also works only with non-primitives AFAIK (autoboxing is implicit) + it introduces overhead of creating a delegate + the syntax is cumbersome
+ it doesn’t work with non-nullable types
..compared to Swift’s consistent syntax:
Copy code
let a: String
let b: String?
var c: Bool
var d: Bool?
k
Can you maybe give an example use case? As far as I understand you implicitly want
lateinit
on every property (which I strongly disagree with) and you want it to work on nullable types too.
g
@karelpeeters it doesn’t interfere with null-safety at all. and since it’s already battle tested in Swift, I think there’s a good chance it’s a good idea
yup, it would basically be implicit
lateinit
and 100% consistent across every possible property - with no exceptions
k
Isn’t this back to java? You can accidentally dereference a potentially uninitialized property at runtime, and everything blows up. I agree with @karelpeeters. I would avoid such implicitness
k
How does it not interfere with null safety? It basically means that everything can be null at any time, just with immediate `NullPointerException`s.
2
g
My use case is basically Android, where you’re basically forced to use either
lateinit
or
var ...? = null
+
!!
all over the place. Also the usage of
val
is very limited because of this.
k
For android the plugin lets you literally
import
views, avoiding this problem. Otherwise it's a good case to use
lateinit
on.
g
… but
lateinit
prohibits the use of
val
, primitives and custom getters and setters… thus forces us to create various workarounds… again, compared to Swift’s consistent aproach
i
If val would be without an initializer, how to initialize it later?
g
To be honest, this is one of the things that surprises our Swift developers. When they need to introduce new property, they just do it. And in Kotlin you’d love to make a
val
, but you can’t (becasue it’s not passed in the constructor). So you choose one of the non-perfect alternatives: lateinit var or var …? = null or a delegate…
@ilya.gorbunov just like in case of local variables. you can assign it only once. after that you get a “val cannot be reassigned” error
k
But that's different, because there compile time analysis can prove it is assigned exactly once.
g
yup, it would have to be in runtime - just like lateinit
g
Sounds like a bad idea for me. Lose compile type safety without clear advantage val properties already work like local variables, compiler have to guarantee that property (or variable) will be initialized on property declaration or constructor, in this case you can postpone initialization
My use case is basically Android, where you’re basically forced to use either
lateinit
or
var ...? = null
+
!!
all over the place.
Maybe you could share most common use cases of that. We almost never use !! and lateinit only for dependency injection of Android components
a
I’m also curious as to what the use case is. I use
lateinit
for things that may depend on the context in Android, and for nullable content, I’d just set the default to null since I need to handle that anyways. You may also note that within a method, you can do something like
val a: Int
and initialize it later, so long as it’s initialized once only and before it is used
b
I, for the record, think it's dumb to have all these global variables initialized at mysterious, unintuitive times, rather than at first access. Maybe they could all be implicitly delegated to
lazy
? Maybe they could be implicitly wrapped in individual transparent classes? I don't think you need to ditch safety to have lazy loading of top-level properties
2
v
Delegates seem like a perfect fit for this. Autoboxing is very really an issue for class properties.
l
Autoboxing is an issue for arrays and significant frequency primitive conversion to boxed type version since it implies allocation
v
@louiscad so? Do you often inject int values into classes, and then put them into arrays? Can't even imagine what that would be for
l
@voddan That's not what I meant, I meant
Array<Int>
takes up more memory than
IntArray
(since there's an array of references, plus all the boxed `Int`s), and that unboxed to boxed
Int
conversion also had an allocation cost, which you don't want in code run at a potentially significant frequency
😕 1