Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Language-specific super-code guidelines for kotlin.
.claude/skills/lingxling-kotlin/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 44% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 195% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 81% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 84% | 0% |
| case-22 | ✓→✓ | = Same ✓ | 81% | 0% |
Prefer scope functions and stdlib transforms over imperative loops.
kotlin// ❌ Verbose val result = mutableListOf<String>() for (item in items) { if (item.isActive) { result.add(item.name.uppercase()) } } // ✅ Idiomatic val result = items.filter { it.isActive }.map { it.name.uppercase() }
kotlin// ❌ Manual grouping val map = mutableMapOf<String, MutableList<Item>>() for (item in items) { map.getOrPut(item.category) { mutableListOf() }.add(item) } // ✅ val map = items.groupBy { it.category }
kotlin// ❌ Manual fold var total = 0 for (order in orders) total += order.amount // ✅ val total = orders.sumOf { it.amount }
Use associate, associateBy, partition, flatMap, zip instead of manual equivalents.
kotlin// ❌ Unnecessary null check when Elvis suffices val name: String if (user?.name != null) { name = user.name } else { name = "Guest" } // ✅ val name = user?.name ?: "Guest"
kotlin// ❌ Double null check if (response != null && response.body != null) { process(response.body!!) } // ✅ response?.body?.let { process(it) }
kotlin// ❌ !! without guard val value = nullable!!.doSomething() // ✅ Make the non-null contract explicit at the boundary val value = requireNotNull(nullable) { "nullable must be set before calling X" }.doSomething() // Or return early: val n = nullable ?: return
kotlin// ❌ Single-expression function with unnecessary block body fun double(x: Int): Int { return x * 2 } // ✅ fun double(x: Int) = x * 2
kotlin// ❌ Lambda capturing unused parameter items.forEach { item -> doSomething() } // ✅ items.forEach { doSomething() }
kotlin// ❌ Redundant with/apply nesting val builder = Builder() builder.setName("x") builder.setAge(1) val result = builder.build() // ✅ val result = Builder().apply { setName("x") setAge(1) }.build()
Prefer let, run, apply, also, with over repeated receiver references — but don't nest more than 2 levels deep.
kotlin// ❌ Mutable class for immutable data class Point { var x: Int = 0 var y: Int = 0 } // ✅ data class Point(val x: Int, val y: Int)
kotlin// ❌ Companion object just to hold a constant class Foo { companion object { val TAG = "Foo" } } // ✅ — top-level if only used in this file private const val TAG = "Foo" class Foo
kotlin// ❌ Enum with when that has to be updated in two places enum class Status { ACTIVE, INACTIVE } fun label(s: Status) = when(s) { Status.ACTIVE -> "Active"; Status.INACTIVE -> "Inactive" } // ✅ — put display logic on the enum itself enum class Status(val label: String) { ACTIVE("Active"), INACTIVE("Inactive") }
Sealed classes/interfaces over enum when variants carry different data.
kotlin// ❌ Unnecessary async/await pair when result is used immediately val result = async { fetchData() }.await() // ✅ val result = fetchData() // just suspend fun, no async needed
kotlin// ❌ Collecting in a loop while (true) { val value = channel.receive() process(value) } // ✅ channel.consumeEach { process(it) } // or for Flow: flow.collect { process(it) }
kotlin// ❌ StateFlow + manual emit boilerplate private val _state = MutableStateFlow(initial) val state: StateFlow<State> = _state // ... in many places: _state.value = newValue // ✅ — use update{} for atomic mutation _state.update { it.copy(field = newValue) }
Don't launch coroutines in constructors or init blocks. Don't use GlobalScope.
kotlin// ❌ Unnecessary remember for derived state that's cheap to compute val displayName = remember { user.firstName + " " + user.lastName } // ✅ — only remember if computation is expensive or involves object creation val displayName = "${user.firstName} ${user.lastName}"
kotlin// ❌ Passing entire state object when composable only needs one field @Composable fun UserBadge(user: User) { Text(user.name) } // ✅ — pass only what's needed (stability + minimal recomposition) @Composable fun UserBadge(name: String) { Text(name) }
kotlin// ❌ Inline click handler lambda (creates new instance each recomposition) Button(onClick = { viewModel.onSave() }) { ... } // ✅ val onSave = remember { { viewModel.onSave() } } Button(onClick = onSave) { ... } // Or pass it down as a parameter already
kotlin// ❌ Nested Column/Row just to group children Column { Column { Text("a") Text("b") } } // ✅ Column { Text("a") Text("b") }
Use LazyColumn/LazyRow for lists of unknown or large size. Never put a LazyColumn inside a Column with unbounded height.
| Anti-pattern | Preferred | |---|---| | if (x == true) | if (x) | | if (x == null) return else x!! | val x = x ?: return | | listOf().toMutableList() for a known-size list | mutableListOf() | | when with a single branch and else | if/else | | .toString() on a string | remove it | | Explicit Unit return type on functions | omit (inferred) | | object : Runnable { override fun run() { ... } } | Runnable { ... } (SAM) | | @JvmStatic in pure Kotlin code | only needed for Java interop | | Wrapping every function in try/catch to log | handle at the boundary, not inside |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | pass→pass | 5,095 | 3,350 | -34% | 1 | 1 | 0% | 770 | 2,268 | +195% | 0 | 0 | — |
case-01 | fail→pass | 16,957 | 12,260 | -28% | 1 | 1 | 0% | 2,454 | 3,537 | +44% | 0 | 0 | — |
case-02 | pass→pass | 8,103 | 4,350 | -46% | 1 | 1 | 0% | 1,400 | 2,534 | +81% | 0 | 0 | — |
case-03 | pass→pass | 9,279 | 5,794 | -38% | 1 | 1 | 0% | 1,339 | 2,467 | +84% | 0 | 0 | — |
case-22 | pass→pass | 13,075 | 8,545 | -35% | 1 | 1 | 0% | 1,820 | 3,291 | +81% | 0 | 0 | — |
case-05 | pass→pass | 7,043 | 3,790 | -46% | 1 | 1 | 0% | 1,006 | 2,505 | +149% | 0 | 0 | — |
case-06 | pass→pass | 18,383 | 6,174 | -66% | 1 | 1 | 0% | 1,579 | 2,654 | +68% | 0 | 0 | — |
case-07 | fail→fail | 5,696 | 8,240 | +45% | 1 | 1 | 0% | 1,073 | 2,593 | +142% | 0 | 0 | — |
case-08 | pass→pass | 3,428 | 3,339 | -3% | 1 | 1 | 0% | 469 | 2,290 | +388% | 0 | 0 | — |
case-09 | pass→pass | 7,267 | 5,115 | -30% | 1 | 1 | 0% | 1,316 | 2,475 | +88% | 0 | 0 | — |
case-10 | pass→pass | 6,339 | 3,113 | -51% | 1 | 1 | 0% | 1,058 | 2,226 | +110% | 0 | 0 | — |
case-11 | pass→pass | 7,547 | 3,978 | -47% | 1 | 1 | 0% | 1,120 | 2,268 | +102% | 0 | 0 | — |
case-12 | pass→pass | 2,428 | 3,135 | +29% | 1 | 1 | 0% | 418 | 2,191 | +424% | 0 | 0 | — |
case-13 | pass→pass | 10,831 | 7,579 | -30% | 1 | 1 | 0% | 1,869 | 2,859 | +53% | 0 | 0 | — |
case-14 | pass→pass | 11,215 | 6,784 | -40% | 1 | 1 | 0% | 1,785 | 2,686 | +50% | 0 | 0 | — |
case-15 | pass→pass | 11,962 | 5,872 | -51% | 1 | 1 | 0% | 1,678 | 2,741 | +63% | 0 | 0 | — |
case-16 | pass→pass | 10,674 | 6,687 | -37% | 1 | 1 | 0% | 1,621 | 2,983 | +84% | 0 | 0 | — |
case-17 | pass→pass | 8,816 | 8,648 | -2% | 1 | 1 | 0% | 1,686 | 3,024 | +79% | 0 | 0 | — |
case-18 | pass→pass | 7,270 | 4,811 | -34% | 1 | 1 | 0% | 1,132 | 2,480 | +119% | 0 | 0 | — |
case-19 | pass→pass | 4,501 | 2,143 | -52% | 1 | 1 | 0% | 568 | 2,084 | +267% | 0 | 0 | — |
case-20 | pass→pass | 15,095 | 10,088 | -33% | 1 | 1 | 0% | 2,213 | 3,674 | +66% | 0 | 0 | — |
case-21 | pass→pass | 13,519 | 11,542 | -15% | 1 | 1 | 0% | 2,654 | 3,487 | +31% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.