Daniele Segato
10/06/2020, 5:07 PMSomething.Builder()
.apply {
foo("mandatory argument*)
val barArg = grabBarArg()
if (barArg != null) {
bar(barArg)
} else {
// do nothing, leave the default
}
}
.build()
With the default parameters we don't have the option of leaving the default like that;
Something (
foo = "mandatory argument",
bar = grabBarArg() ?: _
)
I think it would be helpful to have a way of explicitly saying "use default" like passing a Nothing
? Or in some other similar way?
When I'm this situation if i have control on the class i create a secondary constructor, but it could be helpful, i think, to have a way to provide the default from the caller.
It might also improve kotlin / java interoperability.ephemient
10/06/2020, 5:23 PMDaniele Segato
10/06/2020, 6:35 PMFleshgrinder
10/06/2020, 7:26 PMephemient
10/06/2020, 7:38 PMFleshgrinder
10/06/2020, 7:49 PMOptional
as always in this situation. But don't get my concern wrong here. I think that this is a great feature request but only if the default is determined at runtime and not part of the ABI.Fleshgrinder
10/06/2020, 7:51 PMclass C(a: String?) { val a = a :? "default" }
that causes resolution issues throughout the rest of any init code.Fleshgrinder
10/06/2020, 8:48 PMephemient
10/06/2020, 8:51 PMFleshgrinder
10/06/2020, 9:25 PM:?
so it only works with null not meaning "use the default". Same as with the null based default that works today explained above. The proposal from the ticket is also using :?
so it's the same again. Only stating this because you explicitly asked "what if null is a valid value" 'cause none of the proposals can adress that.Fleshgrinder
10/06/2020, 9:27 PMDaniele Segato
10/06/2020, 9:29 PM?:
It could be and if
/ else
with any condition. The proposal I wrote here and, incidentally, at that link, suggest using _
to indicate "use the default value".Fleshgrinder
10/07/2020, 7:11 AMfun f(a: String, b: String = "default", c: String) {}
(which is a seriously weird signature) we get something similar to the following:
public final class MainKt {
public static final void f(@NotNull String a, @NotNull String b, @NotNull String c) {
Intrinsics.checkParameterIsNotNull(a, "a");
Intrinsics.checkParameterIsNotNull(b, "b");
Intrinsics.checkParameterIsNotNull(c, "c");
}
// $FF: synthetic method
public static void f$default(String var0, String var1, String var2, int var3, Object var4) {
if ((var3 & 2) != 0) {
var1 = "default";
}
f(var0, var1, var2);
}
}
So it should actually always be resolved at runtime if we do f("x", _, "y")
we would have f$default("x", null, 2, "y")
and thus "default"
for b
. But if our library is changed to have "foo"
as the new default we would get "foo"
and no issues with ABI. 😎Marc Knaup
10/07/2020, 9:35 AMf$default("x", null, "y" 2, null)
.
The last parameter of type Any
is reserved for future use.Marc Knaup
10/07/2020, 9:42 AM_
is that it’s pretty useless when used directly.
f("x", _, "y")
is the same as f(a="x", c="y")
.
The typical scenarios involve conditionals, e.g.
f(
a = "x"
b = if (foo) bar else _,
c = "y"
)
The question is then what the type of if (foo) bar else _
is. That’s non-trivial I think 😕
Another option may be an intrinsic or special syntax that can only be used in exactly that location with exactly one boolean condition. That way we can avoid adding another type.
E.g.
f(
a = "x",
b = argumentIf(foo) { bar },
c = "y"
)
Marc Knaup
10/07/2020, 10:28 AMf(
a = "x",
b = if (foo) bar,
c = "y"
)
ephemient
10/07/2020, 5:08 PMif (foo) bar else _
could be T?!
(just kidding, I don't want that to really be introduced)Fleshgrinder
10/07/2020, 5:37 PMephemient
10/07/2020, 5:41 PMval maybe = if (foo) bar else _
f(maybe)
then it would have to be a separate typeephemient
10/07/2020, 5:42 PMMarc Knaup
10/07/2020, 6:12 PM?
, Optional
, Either
, a hasValue: Boolean
, etc.
Introducing a new type just for this rare case of calling functions explicitly with default arguments isn’t really worth that, is it?Fleshgrinder
10/07/2020, 8:08 PM