Kotlin idioms
Write Kotlin that uses null safety, data classes, and coroutines as designed, with clean Java interop. Use when writing Kotlin or migrating Java code and habits to it.From its SKILL.md
npx -y skills add Amey-Thakur/AI-SKILLS --skill kotlin-idiomsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 25 days oldThe repository was created 25 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.4 KB, 768 tokens by cl100k_base, as published. Nobody here has run it
Kotlin idioms
Kotlin's value is making illegal states unrepresentable with less ceremony: non-null types by default, values as data classes, asynchrony as suspending functions. Java habits imported wholesale forfeit exactly that value.
Method
- Design types non-null first.
String?is a decision, not a default; push nullability to the edges and convert early (?: throw,requireNotNullwith a message). Use?.and?:for genuine absence; every!!is a latent NPE with your name on it: acceptable in tests, a review flag in production code. Platform types from Java are unchecked: annotate your Java (@Nullable/@NotNull) or wrap it at the boundary (see null-handling). - Model values as data classes and sealed hierarchies.
data classfor value carriers (copy() for updates, val everywhere: see immutability-defaults);sealed interfacepluswhenfor closed alternatives, letting the compiler enforce exhaustiveness (the exhaustive-switches discipline, built in). Prefer immutableList/Mapinterfaces in signatures andtoList()copies at boundaries; Kotlin's read-only views are not deep immutability (see java-collections). - Use scope functions sparingly and conventionally.
letfor null-guarded transforms,applyfor object configuration,alsofor side effects in a chain: one level deep. Nestedlets with shadowedits are write-only code; a local val and an if reads better (see cognitive-load). - Write coroutines with structured concurrency. Suspend
functions for async work; launch inside a scope tied to a
lifecycle (
coroutineScope, supervisor scopes for independent children), neverGlobalScope. Cancellation is cooperative: check it in loops, keepwithContext(Dispatchers.IO)around blocking calls, and treatCancellationExceptionas control flow to rethrow, not an error to log (the go-concurrency and python-asyncio contracts, Kotlin dialect). - Keep Java interop deliberate. Expose Kotlin APIs Java can
call cleanly (
@JvmStatic,@JvmOverloadswhere Java callers exist); default arguments replace builder/overload ladders for Kotlin consumers. Checked exceptions vanish in Kotlin: document throwing behavior (see rust-error-handling's audience thinking) since the compiler no longer forces callers to see it. - Prefer expressions and small functions. Single-expression
functions,
whenas an expression, early returns over nested conditionals (see guard-clauses); extension functions to give existing types domain verbs, kept in the domain's package rather than a global Utils file (see python-project-structure's grab-bag rule).
Boundaries
- Kotlin does not fix the JVM's rules: the memory model (see jvm-memory-model), GC behavior, and collections contracts apply unchanged under the nicer syntax.
- Operator overloading and DSL builders are library-author tools; application code inventing clever operators trades a day of writing for years of "what does this plus mean" (see naming-things).
- Coroutines interop with blocking frameworks needs explicit
bridges (
runBlockingat the very top only); sprinkling runBlocking inside services deadlocks thread pools.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.