I have a snippet of Kotlin code where the first and the secondary constructor differs minutely, see below
class InstructionPrototype constructor(
val iname: String,
val opcode: Int,
val mnemonicExample: String,
val numericExample: Int,
val description: String,
val format: Format,
val pattern: Pattern,
var type: Type? = null,
var rt: Int? = null,
var funct: Int? = null,
var conditions: Array<(n: Int) -> String?>? = null) {
constructor(
iname: String,
opcode: Int,
mnemonicExample: String,
numericExample: Int,
description: String,
format: Format,
pattern: Pattern,
type: Type?,
rt: Int?,
funct: Int?,
condition: (n: Int) -> String?
): this(iname, opcode, mnemonicExample, numericExample, description,
format, pattern, type, rt, funct, arrayOf(condition)) {
}
is it possible to reduce the verbosity of this through some language construct? I was thinking about algebraic data types but that did not feel like a good fit - it came across as "hacky".
Variable number of arguments (vararg
) seems to fit your use case very well, but only if you can abandon null
as the default value for conditions
since vararg
cannot be nullable (e.g. use emptyArray()
):
class InstructionPrototype constructor(
val iname: String,
val opcode: Int,
val mnemonicExample: String,
val numericExample: Int,
val description: String,
val format: Format,
val pattern: Pattern,
var type: Type? = null,
var rt: Int? = null,
var funct: Int? = null,
vararg var conditions: (n: Int) -> String? = emptyArray())
At use site, you can pass single (n: Int) -> String?
, and it will be packed into an array, and, in addition to passing several functions separated by comma, you can use the spread operator to pass an array:
f(vararg a: String) { }
f("a")
f("a", "b", "c")
val array = arrayOf("a", "b", "c")
f(*array) // any array of the correct type can be passed as vararg
Also, several parameters before conditions
also have default values, and there's no other way to skip them and pass conditions
than use named arguments and the spread operator:
fun f(x: Int = 5, vararg s: String) { }
f(5, "a", "b", "c") // correct
f(s = "a") // correct
f(s = "a", "b", "c") // error
f(s = *arrayOf("a", "b", "c") // correct