From f03d098e8ec2a3e0b5f577a46f91b73ffbdab8b3 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 30 Oct 2025 10:43:18 +0100 Subject: [PATCH 01/12] first pass --- docs/topics/functions.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index 37bef4a828d..a2c626da80b 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -19,13 +19,14 @@ val result = double(2) Calling member functions uses dot notation: ```kotlin -Stream().read() // create instance of class Stream and call read() +// Creates instance of the Stream class and calls read() +Stream().read() ``` ### Parameters -Function parameters are defined using Pascal notation - *name*: *type*. Parameters are separated using commas, and each -parameter must be explicitly typed: +Function parameters are defined using Pascal notation: `name: Type`. +Parameters are separated using commas, and each parameter must be explicitly typed: ```kotlin fun powerOf(number: Int, exponent: Int): Int { /*...*/ } @@ -40,9 +41,14 @@ fun powerOf( ) { /*...*/ } ``` +This helps with refactorings and code maintenance: +you can move parameters within the declaration without worrying about which is going to be the last one. + +TODO should this be optional parameters? probably not ### Parameters with default values Function parameters can have default values, which are used when you skip the corresponding argument. +A default value is set by appending `=` to the type. This reduces the number of overloads: ```kotlin @@ -55,8 +61,6 @@ fun read( Such parameters are also referred to as _optional parameters_. -A default value is set by appending `=` to the type. - Overriding methods always use the base method's default parameter values. When overriding a method that has default parameter values, the default parameter values must be omitted from the signature: @@ -82,6 +86,7 @@ fun foo( foo(baz = 1) // The default value bar = 0 is used ``` +TODO this doesn't seem to do much with the subject of default values. If the last parameter after all parameters with default values has a functional type, then you can pass the corresponding [lambda](lambdas.md#lambda-expression-syntax) argument either as a named argument or [outside the parentheses](lambdas.md#passing-trailing-lambdas): @@ -97,6 +102,7 @@ foo(qux = { println("hello") }) // Uses both default values bar = 0 and baz = 1 foo { println("hello") } // Uses both default values bar = 0 and baz = 1 ``` +TODO should named arguments be before default values? Should arguments be parameters? ### Named arguments You can name one or more of a function's arguments when calling it. This can be helpful when a function has many @@ -171,12 +177,14 @@ fun printHello(name: String?): Unit { } ``` +TODO this can be folded into above surely The `Unit` return type declaration is also optional. The above code is equivalent to: ```kotlin fun printHello(name: String?) { ... } ``` +TODO since this refers to explicit return types, should probably be below them. ### Single-expression functions When the function body consists of a single expression, the curly braces can be omitted and the body specified after an `=` symbol: @@ -275,7 +283,7 @@ infix fun Int.shl(x: Int): Int { ... } {style="note"} Note that infix functions always require both the receiver and the parameter to be specified. When you're -calling a method on the current receiver using the infix notation, use `this` explicitly. This is required to ensure +calling a method on the current receiver using the infix notation, use `this` explicitly. This ensures unambiguous parsing. ```kotlin @@ -292,8 +300,9 @@ class MyStringCollection { ## Function scope +TODO is comparison to other languages even necessary here Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function, -which you are required to do in languages such as Java, C#, and Scala ([top level definition is available since Scala 3](https://docs.scala-lang.org/scala3/book/taste-toplevel-definitions.html#inner-main)). In addition +which you are required to do in languages such as Java and C#. In addition to top level functions, Kotlin functions can also be declared locally as member functions and extension functions. ### Local functions @@ -369,7 +378,7 @@ tailrec fun findFixPoint(x: Double = 1.0): Double = if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x)) ``` -This code calculates the `fixpoint` of cosine, which is a mathematical constant. It simply calls `Math.cos` repeatedly +This code calculates the fixed point of cosine (a mathematical constant). It simply calls `Math.cos` repeatedly starting at `1.0` until the result no longer changes, yielding a result of `0.7390851332151611` for the specified `eps` precision. The resulting code is equivalent to this more traditional style: @@ -389,6 +398,7 @@ private fun findFixPoint(): Double { To be eligible for the `tailrec` modifier, a function must call itself as the last operation it performs. You cannot use tail recursion when there is more code after the recursive call, within `try`/`catch`/`finally` blocks, or on open functions. Currently, tail recursion is supported by Kotlin for the JVM and Kotlin/Native. +TODO what else is there but JVM and Native? **See also**: * [Inline functions](inline-functions.md) From 1f0f9a52ca244f26901be2f70f8e4886ca8e48e6 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Fri, 7 Nov 2025 18:47:27 +0100 Subject: [PATCH 02/12] second pass --- docs/topics/functions.md | 146 ++++++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 55 deletions(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index a2c626da80b..5feedaef237 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -44,12 +44,13 @@ fun powerOf( This helps with refactorings and code maintenance: you can move parameters within the declaration without worrying about which is going to be the last one. -TODO should this be optional parameters? probably not -### Parameters with default values +### Parameters with default values (optional parameters) Function parameters can have default values, which are used when you skip the corresponding argument. -A default value is set by appending `=` to the type. -This reduces the number of overloads: +This reduces the number of necessary overloads. +Parameters with default values are also referred to as _optional parameters_. + +A default value is set by appending `=` to the parameter declaration: ```kotlin fun read( @@ -59,50 +60,85 @@ fun read( ) { /*...*/ } ``` -Such parameters are also referred to as _optional parameters_. +If a parameter with default value precedes a parameter with no default value, the default value can only be used by calling +the function with [named arguments](#named-arguments): + +```kotlin +fun foo( + foo: Int = 0, + bar: Int, +) { /*...*/ } -Overriding methods always use the base method's default parameter values. +foo(bar = 1) // Uses the default value foo = 0 +foo(1) // Error: No value passed for parameter 'bar' +``` + +[Overriding methods](inheritance.md#overriding-methods) always use the base method's default parameter values. When overriding a method that has default parameter values, the default parameter values must be omitted from the signature: ```kotlin open class A { - open fun foo(i: Int = 10) { /*...*/ } + open fun foo(i: Int = 10, j: Int = 0) { /*...*/ } } class B : A() { - override fun foo(i: Int) { /*...*/ } // No default value is allowed. + // It's not allowed to specify default values here + // but this function also uses 10 for 'i' and 0 for 'j' + // by default. + override fun foo(i: Int, j: Int) { /*...*/ } } ``` -If a parameter with default value precedes a parameter with no default value, the default value can only be used by calling -the function with [named arguments](#named-arguments): +#### Non-constant expressions as default values + +You can assign to a parameter a default value that is not constant an expression, as in a function call, or a calculation that uses +values of other arguments, like the `len` parameter in the example above: ```kotlin -fun foo( - bar: Int = 0, - baz: Int, +fun read( + b: ByteArray, + off: Int = 0, + len: Int = b.size, +) { /*...*/ } +``` + +Parameters referring to other parameters' values must be declared later in the order (in this example, `len` must be declared after `b`). + +In general default value of a parameter can be any expression — but such expressions are only calculated when +the function is called **without** the parameter and a default value needs to be assigned. +For example, this function prints out a line when it is called without the `print` parameter: + +```kotlin +fun read( + b: Int, + print: Unit? = println("No argument passed for 'print'.") ) { /*...*/ } -foo(baz = 1) // The default value bar = 0 is used +fun main() { + read (1) +} ``` -TODO this doesn't seem to do much with the subject of default values. -If the last parameter after all parameters with default values has a functional type, +If the last parameter in a function declaration has a functional type, then you can pass the corresponding [lambda](lambdas.md#lambda-expression-syntax) argument either as a named argument or [outside the parentheses](lambdas.md#passing-trailing-lambdas): ```kotlin fun foo( - bar: Int = 0, - baz: Int = 1, + foo: Int = 0, + bar: Int = 1, qux: () -> Unit, ) { /*...*/ } -foo(1) { println("hello") } // Uses the default value baz = 1 -foo(qux = { println("hello") }) // Uses both default values bar = 0 and baz = 1 -foo { println("hello") } // Uses both default values bar = 0 and baz = 1 +// Uses the default value bar = 1 +foo(1) { println("hello") } + +// Uses both default values foo = 0 and bar = 1 +foo(qux = { println("hello") }) + +// Uses both default values foo = 0 and bar = 1 +foo { println("hello") } ``` -TODO should named arguments be before default values? Should arguments be parameters? ### Named arguments You can name one or more of a function's arguments when calling it. This can be helpful when a function has many @@ -148,15 +184,16 @@ skipped argument, you must name all subsequent arguments: reformat("This is a short String!", upperCaseFirstLetter = false, wordSeparator = '_') ``` -You can pass a [variable number of arguments (`vararg`)](#variable-number-of-arguments-varargs) with names using the -_spread_ operator (prefix the array with `*`): +You can pass a [variable number of arguments](#variable-number-of-arguments-varargs) (`vararg`) naming the correspoding array: ```kotlin fun foo(vararg strings: String) { /*...*/ } -foo(strings = *arrayOf("a", "b", "c")) +foo(strings = arrayOf("a", "b", "c")) ``` + + > When calling Java functions on the JVM, you can't use the named argument syntax because Java bytecode does not > always preserve the names of function parameters. > @@ -164,8 +201,11 @@ foo(strings = *arrayOf("a", "b", "c")) ### Unit-returning functions -If a function does not return a useful value, its return type is `Unit`. `Unit` is a type with only one value - `Unit`. -This value does not have to be returned explicitly: +If a function does not return a useful value, its return type is `Unit` (corresponds to the `void` type in Java). + +`Unit` is a type with only one value - `Unit`. +You don't have to declare this return type, or return `Unit` explicitly. +Therefore, this verbose declaration: ```kotlin fun printHello(name: String?): Unit { @@ -173,30 +213,14 @@ fun printHello(name: String?): Unit { println("Hello $name") else println("Hi there!") - // `return Unit` or `return` is optional + return Unit } ``` -TODO this can be folded into above surely -The `Unit` return type declaration is also optional. The above code is equivalent to: +is equivalent to: ```kotlin -fun printHello(name: String?) { ... } -``` - -TODO since this refers to explicit return types, should probably be below them. -### Single-expression functions - -When the function body consists of a single expression, the curly braces can be omitted and the body specified after an `=` symbol: - -```kotlin -fun double(x: Int): Int = x * 2 -``` - -Explicitly declaring the return type is [optional](#explicit-return-types) when this can be inferred by the compiler: - -```kotlin -fun double(x: Int) = x * 2 +fun printHello(name: String?) { /*...*/ } ``` ### Explicit return types @@ -249,6 +273,20 @@ val a = intArrayOf(1, 2, 3) // IntArray is a primitive type array val list = asList(-1, 0, *a.toTypedArray(), 4) ``` +### Single-expression functions + +When the function body consists of a single expression, the curly braces can be omitted and the body specified after an `=` symbol: + +```kotlin +fun double(x: Int): Int = x * 2 +``` + +Explicitly declaring the return type is [optional](#explicit-return-types) when this can be inferred by the compiler: + +```kotlin +fun double(x: Int) = x * 2 +``` + ### Infix notation Functions marked with the `infix` keyword can also be called using the infix notation (omitting the dot and the parentheses @@ -300,10 +338,8 @@ class MyStringCollection { ## Function scope -TODO is comparison to other languages even necessary here -Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function, -which you are required to do in languages such as Java and C#. In addition -to top level functions, Kotlin functions can also be declared locally as member functions and extension functions. +Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function. +Functions can also be declared locally as _member functions_ and _extension functions_. ### Local functions @@ -375,10 +411,10 @@ the recursion, leaving behind a fast and efficient loop based version instead: val eps = 1E-10 // "good enough", could be 10^-15 tailrec fun findFixPoint(x: Double = 1.0): Double = - if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x)) + if (abs(x - cos(x)) < eps) x else findFixPoint(cos(x)) ``` -This code calculates the fixed point of cosine (a mathematical constant). It simply calls `Math.cos` repeatedly +This code calculates the fixed point of cosine (a mathematical constant). It simply calls `cos()` repeatedly starting at `1.0` until the result no longer changes, yielding a result of `0.7390851332151611` for the specified `eps` precision. The resulting code is equivalent to this more traditional style: @@ -388,9 +424,9 @@ val eps = 1E-10 // "good enough", could be 10^-15 private fun findFixPoint(): Double { var x = 1.0 while (true) { - val y = Math.cos(x) - if (Math.abs(x - y) < eps) return x - x = Math.cos(x) + val y = cos(x) + if (abs(x - y) < eps) return x + x = cos(x) } } ``` From 7ab5d60335f73a1ff6066c4c6075fdbd4252ea33 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Fri, 7 Nov 2025 19:05:53 +0100 Subject: [PATCH 03/12] fix: broken anchor --- docs/topics/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index 5feedaef237..fd4de210703 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -295,7 +295,7 @@ for the call). Infix functions must meet the following requirements: * They must be member functions or [extension functions](extensions.md). * They must have a single parameter. * The parameter must not [accept variable number of arguments](#variable-number-of-arguments-varargs) and must have -no [default value](#parameters-with-default-values). +no [default value](#parameters-with-default-values-optional-parameters). ```kotlin infix fun Int.shl(x: Int): Int { ... } From 06a5a2fbe2efcc79a2dc1707e2c5b18df972d995 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 13 Nov 2025 10:51:19 +0100 Subject: [PATCH 04/12] update: runnable sample --- docs/topics/functions.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index fd4de210703..cb371ffc110 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -64,6 +64,8 @@ If a parameter with default value precedes a parameter with no default value, th the function with [named arguments](#named-arguments): ```kotlin +fun main () { +//sampleStart fun foo( foo: Int = 0, bar: Int, @@ -71,7 +73,10 @@ fun foo( foo(bar = 1) // Uses the default value foo = 0 foo(1) // Error: No value passed for parameter 'bar' +//sampleEnd +} ``` +{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} [Overriding methods](inheritance.md#overriding-methods) always use the base method's default parameter values. When overriding a method that has default parameter values, the default parameter values must be omitted from the signature: From 9d34ceaccba13072b133504ef1b91a6ae36b793e Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 13 Nov 2025 11:48:45 +0100 Subject: [PATCH 05/12] update: more clarifications --- docs/topics/functions.md | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index cb371ffc110..4962f067793 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -32,6 +32,14 @@ Parameters are separated using commas, and each parameter must be explicitly typ fun powerOf(number: Int, exponent: Int): Int { /*...*/ } ``` +Inside the body of a function, received parameters are read-only (implicitly `val`): + +```kotlin +fun powerOf (number: Int, exponent: Int): Int { + number = 2 // Error: 'val' cannot be reassigned. +} +``` + You can use a [trailing comma](coding-conventions.md#trailing-commas) when you declare function parameters: ```kotlin @@ -44,6 +52,9 @@ fun powerOf( This helps with refactorings and code maintenance: you can move parameters within the declaration without worrying about which is going to be the last one. +Kotlin functions can receive other functions as parameters — and be passed as arguments. +For details, see [](lambdas.md). + ### Parameters with default values (optional parameters) Function parameters can have default values, which are used when you skip the corresponding argument. @@ -64,8 +75,6 @@ If a parameter with default value precedes a parameter with no default value, th the function with [named arguments](#named-arguments): ```kotlin -fun main () { -//sampleStart fun foo( foo: Int = 0, bar: Int, @@ -73,10 +82,7 @@ fun foo( foo(bar = 1) // Uses the default value foo = 0 foo(1) // Error: No value passed for parameter 'bar' -//sampleEnd -} ``` -{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} [Overriding methods](inheritance.md#overriding-methods) always use the base method's default parameter values. When overriding a method that has default parameter values, the default parameter values must be omitted from the signature: @@ -96,7 +102,7 @@ class B : A() { #### Non-constant expressions as default values -You can assign to a parameter a default value that is not constant an expression, as in a function call, or a calculation that uses +You can assign to a parameter a default value that is not constant, as in a function call, or a calculation that uses values of other arguments, like the `len` parameter in the example above: ```kotlin @@ -107,20 +113,23 @@ fun read( ) { /*...*/ } ``` -Parameters referring to other parameters' values must be declared later in the order (in this example, `len` must be declared after `b`). +Parameters referring to other parameters' values must be declared later in the order +(in this example, `len` must be declared after `b`). -In general default value of a parameter can be any expression — but such expressions are only calculated when -the function is called **without** the parameter and a default value needs to be assigned. -For example, this function prints out a line when it is called without the `print` parameter: +In general default value of a parameter can be any expression. +But such expressions are only calculated when the function is called **without** the corresponding parameter +and a default value needs to be assigned. +For example, this function prints out a line only when it is called without the `print` parameter: ```kotlin fun read( b: Int, print: Unit? = println("No argument passed for 'print'.") -) { /*...*/ } +) { println(b) } fun main() { - read (1) + read (1) // BothFirst "No argument passed for 'print'.", then "1" is printed + read (1, null) // Only the "1" is printed } ``` @@ -343,7 +352,8 @@ class MyStringCollection { ## Function scope -Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function. +Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function +(unlike Java, for example). Functions can also be declared locally as _member functions_ and _extension functions_. ### Local functions @@ -438,8 +448,6 @@ private fun findFixPoint(): Double { To be eligible for the `tailrec` modifier, a function must call itself as the last operation it performs. You cannot use tail recursion when there is more code after the recursive call, within `try`/`catch`/`finally` blocks, or on open functions. -Currently, tail recursion is supported by Kotlin for the JVM and Kotlin/Native. -TODO what else is there but JVM and Native? **See also**: * [Inline functions](inline-functions.md) From b2d4aa63c3ca25cf12f9a495c1f20fcf75e9c706 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 13 Nov 2025 12:02:14 +0100 Subject: [PATCH 06/12] fix: anchor --- docs/topics/jvm/comparison-to-java.md | 2 +- docs/topics/jvm/java-to-kotlin-nullability-guide.md | 2 +- docs/topics/keyword-reference.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/topics/jvm/comparison-to-java.md b/docs/topics/jvm/comparison-to-java.md index 029e54119f5..e4a964593de 100644 --- a/docs/topics/jvm/comparison-to-java.md +++ b/docs/topics/jvm/comparison-to-java.md @@ -45,7 +45,7 @@ Kotlin fixes a series of issues that Java suffers from: * [Data classes](data-classes.md) * [Coroutines](coroutines-overview.md) * [Top-level functions](functions.md) -* [Parameters with default values](functions.md#parameters-with-default-values) +* [Parameters with default values](functions.md#parameters-with-default-values-optional-parameters) * [Named parameters](functions.md#named-arguments) * [Infix functions](functions.md#infix-notation) * [Expect and actual declarations](https://kotlinlang.org/docs/multiplatform/multiplatform-expect-actual.html) diff --git a/docs/topics/jvm/java-to-kotlin-nullability-guide.md b/docs/topics/jvm/java-to-kotlin-nullability-guide.md index 024d1bbc932..e2fbc6e9308 100644 --- a/docs/topics/jvm/java-to-kotlin-nullability-guide.md +++ b/docs/topics/jvm/java-to-kotlin-nullability-guide.md @@ -218,7 +218,7 @@ findOrder()?.customer?.let(::processCustomer) ## Default values instead of null -Checking for `null` is often used in combination with [setting the default value](functions.md#parameters-with-default-values) +Checking for `null` is often used in combination with [setting the default value](functions.md#parameters-with-default-values-optional-parameters) in case the null check is successful. The Java code with a null check: diff --git a/docs/topics/keyword-reference.md b/docs/topics/keyword-reference.md index 7bb6a92d9f7..0aff20d29c6 100644 --- a/docs/topics/keyword-reference.md +++ b/docs/topics/keyword-reference.md @@ -135,7 +135,7 @@ Kotlin supports the following operators and special symbols: - `*` is also used to [pass an array to a vararg parameter](functions.md#variable-number-of-arguments-varargs). * `=` - assignment operator. - - is used to specify [default values for parameters](functions.md#parameters-with-default-values). + - is used to specify [default values for parameters](functions.md#parameters-with-default-values-optional-parameters). * `+=`, `-=`, `*=`, `/=`, `%=` - [augmented assignment operators](operator-overloading.md#augmented-assignments). * `++`, `--` - [increment and decrement operators](operator-overloading.md#increments-and-decrements). * `&&`, `||`, `!` - logical 'and', 'or', 'not' operators (for bitwise operations, use the corresponding [infix functions](numbers.md#operations-on-numbers) instead). From 113e675d2ea40d52284d991f5287860d31fe5f2d Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 13 Nov 2025 12:03:38 +0100 Subject: [PATCH 07/12] fix: imports to clarify --- docs/topics/functions.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index 4962f067793..5346bfa1ca5 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -423,6 +423,9 @@ When a function is marked with the `tailrec` modifier and meets the required for the recursion, leaving behind a fast and efficient loop based version instead: ```kotlin +import kotlin.math.cos +import kotlin.math.abs + val eps = 1E-10 // "good enough", could be 10^-15 tailrec fun findFixPoint(x: Double = 1.0): Double = @@ -434,6 +437,9 @@ starting at `1.0` until the result no longer changes, yielding a result of `0.73 `eps` precision. The resulting code is equivalent to this more traditional style: ```kotlin +import kotlin.math.cos +import kotlin.math.abs + val eps = 1E-10 // "good enough", could be 10^-15 private fun findFixPoint(): Double { From 07914db5b5873faea0125073fc69801f3e0e1543 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 13 Nov 2025 12:04:14 +0100 Subject: [PATCH 08/12] fix: comment the ellipsis --- docs/topics/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index 5346bfa1ca5..c1e01c8e220 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -312,7 +312,7 @@ for the call). Infix functions must meet the following requirements: no [default value](#parameters-with-default-values-optional-parameters). ```kotlin -infix fun Int.shl(x: Int): Int { ... } +infix fun Int.shl(x: Int): Int { /*...*/ } // calling the function using the infix notation 1 shl 2 From 077977a7421e078a07140d3031a617fe7083cfa6 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Thu, 13 Nov 2025 14:07:09 +0100 Subject: [PATCH 09/12] fix: SME review --- docs/topics/functions.md | 85 ++++++++++++------- docs/topics/jvm/comparison-to-java.md | 2 +- .../jvm/java-to-kotlin-nullability-guide.md | 2 +- docs/topics/keyword-reference.md | 2 +- 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index c1e01c8e220..6d259dbed31 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -55,7 +55,7 @@ you can move parameters within the declaration without worrying about which is g Kotlin functions can receive other functions as parameters — and be passed as arguments. For details, see [](lambdas.md). -### Parameters with default values (optional parameters) +### Parameters with default values (optional parameters) {id="parameters-with-default-values"} Function parameters can have default values, which are used when you skip the corresponding argument. This reduces the number of necessary overloads. @@ -71,8 +71,8 @@ fun read( ) { /*...*/ } ``` -If a parameter with default value precedes a parameter with no default value, the default value can only be used by calling -the function with [named arguments](#named-arguments): +When you declare a parameter with a default value before a parameter without a default value, +you can only use the default value by [naming arguments](#named-arguments): ```kotlin fun foo( @@ -84,6 +84,18 @@ foo(bar = 1) // Uses the default value foo = 0 foo(1) // Error: No value passed for parameter 'bar' ``` +[Trailing lambdas](lambdas.md#passing-trailing-lambdas) are an exception to this rule, +since the last parameter must correspond to the passed function: + +```kotlin +fun foo( + foo: Int = 0, + bar: () -> Unit, +) { bar() } + +foo() { println ("bar") } // Uses the default value for 'foo' and prints "bar" +``` + [Overriding methods](inheritance.md#overriding-methods) always use the base method's default parameter values. When overriding a method that has default parameter values, the default parameter values must be omitted from the signature: @@ -213,16 +225,41 @@ foo(strings = arrayOf("a", "b", "c")) > {style="note"} -### Unit-returning functions +### Explicit return types + +Functions with a block body must always specify return types explicitly, unless it's intended for them to return `Unit`, +[in which case specifying the return type is optional](#unit-returning-functions). -If a function does not return a useful value, its return type is `Unit` (corresponds to the `void` type in Java). +Kotlin does not infer return types for functions with block bodies because such functions may have complex control flow +in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler). +But the return type is inferred, unless specified, for [single-expression functions](#single-expression-functions). + +### Single-expression functions + +When the function body consists of a single expression, the curly braces can be omitted and the body specified after an `=` symbol: + +```kotlin +fun double(x: Int): Int = x * 2 +``` + +Explicitly declaring the return type is [optional](#explicit-return-types) when this can be inferred by the compiler: + +```kotlin +fun double(x: Int) = x * 2 +``` + +### Unit-returning functions +If a function has a block body and does not return a useful value, its return type is assumed to be `Unit` (corresponds to the `void` type in Java). `Unit` is a type with only one value - `Unit`. -You don't have to declare this return type, or return `Unit` explicitly. + +You don't have to specify `Unit` as a return type, except for functional type parameters, +and you never have to return `Unit` explicitly. + Therefore, this verbose declaration: ```kotlin -fun printHello(name: String?): Unit { +fun printHello(name: String?, aux: () -> Unit): Unit { if (name != null) println("Hello $name") else @@ -231,20 +268,18 @@ fun printHello(name: String?): Unit { } ``` -is equivalent to: +can be shortened to: ```kotlin -fun printHello(name: String?) { /*...*/ } +// The declaration of 'aux' still needs an explicit return type +fun printHello(name: String?, aux: () -> Unit) { + if (name != null) + println("Hello $name") + else + println("Hi there!") +} ``` -### Explicit return types - -Functions with block body must always specify return types explicitly, unless it's intended for them to return `Unit`, -[in which case specifying the return type is optional](#unit-returning-functions). - -Kotlin does not infer return types for functions with block bodies because such functions may have complex control flow -in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler). - ### Variable number of arguments (varargs) You can mark a parameter of a function (usually the last one) with the `vararg` modifier: @@ -287,20 +322,6 @@ val a = intArrayOf(1, 2, 3) // IntArray is a primitive type array val list = asList(-1, 0, *a.toTypedArray(), 4) ``` -### Single-expression functions - -When the function body consists of a single expression, the curly braces can be omitted and the body specified after an `=` symbol: - -```kotlin -fun double(x: Int): Int = x * 2 -``` - -Explicitly declaring the return type is [optional](#explicit-return-types) when this can be inferred by the compiler: - -```kotlin -fun double(x: Int) = x * 2 -``` - ### Infix notation Functions marked with the `infix` keyword can also be called using the infix notation (omitting the dot and the parentheses @@ -309,7 +330,7 @@ for the call). Infix functions must meet the following requirements: * They must be member functions or [extension functions](extensions.md). * They must have a single parameter. * The parameter must not [accept variable number of arguments](#variable-number-of-arguments-varargs) and must have -no [default value](#parameters-with-default-values-optional-parameters). +no [default value](#parameters-with-default-values). ```kotlin infix fun Int.shl(x: Int): Int { /*...*/ } diff --git a/docs/topics/jvm/comparison-to-java.md b/docs/topics/jvm/comparison-to-java.md index e4a964593de..029e54119f5 100644 --- a/docs/topics/jvm/comparison-to-java.md +++ b/docs/topics/jvm/comparison-to-java.md @@ -45,7 +45,7 @@ Kotlin fixes a series of issues that Java suffers from: * [Data classes](data-classes.md) * [Coroutines](coroutines-overview.md) * [Top-level functions](functions.md) -* [Parameters with default values](functions.md#parameters-with-default-values-optional-parameters) +* [Parameters with default values](functions.md#parameters-with-default-values) * [Named parameters](functions.md#named-arguments) * [Infix functions](functions.md#infix-notation) * [Expect and actual declarations](https://kotlinlang.org/docs/multiplatform/multiplatform-expect-actual.html) diff --git a/docs/topics/jvm/java-to-kotlin-nullability-guide.md b/docs/topics/jvm/java-to-kotlin-nullability-guide.md index e2fbc6e9308..024d1bbc932 100644 --- a/docs/topics/jvm/java-to-kotlin-nullability-guide.md +++ b/docs/topics/jvm/java-to-kotlin-nullability-guide.md @@ -218,7 +218,7 @@ findOrder()?.customer?.let(::processCustomer) ## Default values instead of null -Checking for `null` is often used in combination with [setting the default value](functions.md#parameters-with-default-values-optional-parameters) +Checking for `null` is often used in combination with [setting the default value](functions.md#parameters-with-default-values) in case the null check is successful. The Java code with a null check: diff --git a/docs/topics/keyword-reference.md b/docs/topics/keyword-reference.md index 0aff20d29c6..7bb6a92d9f7 100644 --- a/docs/topics/keyword-reference.md +++ b/docs/topics/keyword-reference.md @@ -135,7 +135,7 @@ Kotlin supports the following operators and special symbols: - `*` is also used to [pass an array to a vararg parameter](functions.md#variable-number-of-arguments-varargs). * `=` - assignment operator. - - is used to specify [default values for parameters](functions.md#parameters-with-default-values-optional-parameters). + - is used to specify [default values for parameters](functions.md#parameters-with-default-values). * `+=`, `-=`, `*=`, `/=`, `%=` - [augmented assignment operators](operator-overloading.md#augmented-assignments). * `++`, `--` - [increment and decrement operators](operator-overloading.md#increments-and-decrements). * `&&`, `||`, `!` - logical 'and', 'or', 'not' operators (for bitwise operations, use the corresponding [infix functions](numbers.md#operations-on-numbers) instead). From 8f3462a31608fafd1c9efc7c69fed7f8122b533b Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Tue, 2 Dec 2025 01:31:55 +0100 Subject: [PATCH 10/12] fix: less passive voice + some more runnable samples --- docs/topics/functions.md | 221 ++++++++++++++++++++++++--------------- 1 file changed, 134 insertions(+), 87 deletions(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index 6d259dbed31..e2ce2c96402 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -1,8 +1,12 @@ [//]: # (title: Functions) -Kotlin functions are declared using the `fun` keyword: +To declare a function in Kotlin, use the `fun` keyword, specify the parameters in brackets +and indicate the return type if necessary: ```kotlin +// 'double' is the name of the function, +// 'x' is a parameter of the Int type, +// and the expected return value is of the Int type, too fun double(x: Int): Int { return 2 * x } @@ -10,29 +14,29 @@ fun double(x: Int): Int { ## Function usage -Functions are called using the standard approach: +To call a function, use the brackets notation for arguments: ```kotlin val result = double(2) ``` -Calling member functions uses dot notation: +To call a member function, use the dot notation: ```kotlin -// Creates instance of the Stream class and calls read() +// Creates an instance of the Stream class and calls read() Stream().read() ``` ### Parameters -Function parameters are defined using Pascal notation: `name: Type`. -Parameters are separated using commas, and each parameter must be explicitly typed: +Declare function parameters using Pascal notation: `name: Type`. +You must separate parameters using commas and type each parameter explicitly: ```kotlin fun powerOf(number: Int, exponent: Int): Int { /*...*/ } ``` -Inside the body of a function, received parameters are read-only (implicitly `val`): +Inside the body of a function, received arguments are read-only (implicitly declared as `val`): ```kotlin fun powerOf (number: Int, exponent: Int): Int { @@ -40,7 +44,7 @@ fun powerOf (number: Int, exponent: Int): Int { } ``` -You can use a [trailing comma](coding-conventions.md#trailing-commas) when you declare function parameters: +You can use a [trailing comma](coding-conventions.md#trailing-commas) when declaring function parameters: ```kotlin fun powerOf( @@ -49,24 +53,31 @@ fun powerOf( ) { /*...*/ } ``` -This helps with refactorings and code maintenance: +Trailing commas help with refactorings and code maintenance: you can move parameters within the declaration without worrying about which is going to be the last one. -Kotlin functions can receive other functions as parameters — and be passed as arguments. -For details, see [](lambdas.md). +> Kotlin functions can receive other functions as parameters — and be passed as arguments. +> For details, see [](lambdas.md). +> +{style="note"} ### Parameters with default values (optional parameters) {id="parameters-with-default-values"} -Function parameters can have default values, which are used when you skip the corresponding argument. -This reduces the number of necessary overloads. +You can specify default values for function parameters, to be used when the corresponding argument is skipped +in a function call. +This reduces the number of necessary overloads as you don't need to declare different versions of a function +simply to allow skipping a parameter that has a reasonable default. Parameters with default values are also referred to as _optional parameters_. -A default value is set by appending `=` to the parameter declaration: +Set a default value by appending `=` to the parameter declaration: ```kotlin fun read( b: ByteArray, + // The default value of 'off' is 0 off: Int = 0, + // The default value of 'len' is calculated + // as the size of the 'b' array len: Int = b.size, ) { /*...*/ } ``` @@ -80,9 +91,15 @@ fun foo( bar: Int, ) { /*...*/ } -foo(bar = 1) // Uses the default value foo = 0 -foo(1) // Error: No value passed for parameter 'bar' +fun main () { + // Uses the default value foo = 0 + foo(bar = 1) + + // Error: No value passed for parameter 'bar' + foo(1) +} ``` +{kotlin-runnable="true" kotlin-min-compiler-version="1.3" validate="false"} [Trailing lambdas](lambdas.md#passing-trailing-lambdas) are an exception to this rule, since the last parameter must correspond to the passed function: @@ -91,13 +108,19 @@ since the last parameter must correspond to the passed function: fun foo( foo: Int = 0, bar: () -> Unit, -) { bar() } +) +{ println(foo) + bar() } -foo() { println ("bar") } // Uses the default value for 'foo' and prints "bar" +fun main () { + // Prints the default value 0 for 'foo', then prints "bar" + foo() { println ("bar") } +} ``` +{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} [Overriding methods](inheritance.md#overriding-methods) always use the base method's default parameter values. -When overriding a method that has default parameter values, the default parameter values must be omitted from the signature: +When overriding a method that has default parameter values, you must omit the default parameter values from the signature: ```kotlin open class A { @@ -125,53 +148,64 @@ fun read( ) { /*...*/ } ``` -Parameters referring to other parameters' values must be declared later in the order +Parameters that refer to values of other parameters must be declared later in the order (in this example, `len` must be declared after `b`). -In general default value of a parameter can be any expression. -But such expressions are only calculated when the function is called **without** the corresponding parameter -and a default value needs to be assigned. +In general, you can assign any expression as the default value of a parameter. +But default values are only calculated when the function is called **without** the corresponding parameter +and a default value actually needs to be assigned. For example, this function prints out a line only when it is called without the `print` parameter: ```kotlin +fun main() { +//sampleStart fun read( b: Int, - print: Unit? = println("No argument passed for 'print'.") + print: Unit? = println("No argument passed for 'print'") ) { println(b) } -fun main() { - read (1) // BothFirst "No argument passed for 'print'.", then "1" is printed - read (1, null) // Only the "1" is printed +// Prints "No argument passed for 'print'", then "1" +read (1) +// Prints only "1" +read (1, null) +//sampleEnd } ``` +{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} If the last parameter in a function declaration has a functional type, -then you can pass the corresponding [lambda](lambdas.md#lambda-expression-syntax) argument either as a named argument or [outside the parentheses](lambdas.md#passing-trailing-lambdas): +you can pass the corresponding [lambda](lambdas.md#lambda-expression-syntax) argument either as a named argument or [outside the parentheses](lambdas.md#passing-trailing-lambdas): ```kotlin +fun main() { +//sampleStart fun foo( foo: Int = 0, bar: Int = 1, qux: () -> Unit, -) { /*...*/ } +) { println (foo) + println (bar) + qux() } -// Uses the default value bar = 1 -foo(1) { println("hello") } +// Passes foo = 1 and ses the default value bar = 1 +foo(1) { println("hello") } -// Uses both default values foo = 0 and bar = 1 +// Uses both default values, foo = 0 and bar = 1 foo(qux = { println("hello") }) -// Uses both default values foo = 0 and bar = 1 -foo { println("hello") } +// Equivalent to the previous call, uses both default values +foo { println("hello") } +//sampleEnd +} ``` +{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} ### Named arguments -You can name one or more of a function's arguments when calling it. This can be helpful when a function has many -arguments and it's difficult to associate a value with an argument, especially if it's a boolean or `null` value. +You can name one or more of a function's arguments when calling it. This can be helpful when a function call has many +argument and it's difficult to associate a value with an argument, especially if it's a boolean or `null` value. -When you use named arguments in a function call, you can freely change the order that they are listed in. If you want to -use their default values, you can just leave these arguments out altogether. +When you use named arguments in a function call, you can freely change the order that they are listed in. Consider the `reformat()` function, which has 4 arguments with default values. @@ -185,12 +219,12 @@ fun reformat( ) { /*...*/ } ``` -When calling this function, you don't have to name all its arguments: +When calling this function, you can name some of the arguments: ```kotlin reformat( "String!", - false, + normalizeCase = false, upperCaseFirstLetter = false, divideByCamelHumps = true, '_' @@ -203,8 +237,8 @@ You can skip all the ones with default values: reformat("This is a long String!") ``` -You are also able to skip specific arguments with default values, rather than omitting them all. However, after the first -skipped argument, you must name all subsequent arguments: +You can also skip _some_ arguments with default values, rather than omitting them all. +However, after the first skipped argument, you must name all subsequent arguments: ```kotlin reformat("This is a short String!", upperCaseFirstLetter = false, wordSeparator = '_') @@ -231,18 +265,18 @@ Functions with a block body must always specify return types explicitly, unless [in which case specifying the return type is optional](#unit-returning-functions). Kotlin does not infer return types for functions with block bodies because such functions may have complex control flow -in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler). +in the body, and the return type will not be obvious to the reader (and sometimes even for the compiler). But the return type is inferred, unless specified, for [single-expression functions](#single-expression-functions). ### Single-expression functions -When the function body consists of a single expression, the curly braces can be omitted and the body specified after an `=` symbol: +When the function body consists of a single expression, you can omit the curly braces and specify the body after an `=` symbol: ```kotlin fun double(x: Int): Int = x * 2 ``` -Explicitly declaring the return type is [optional](#explicit-return-types) when this can be inferred by the compiler: +You don't have to [explicitly declare](#explicit-return-types) the return type when it can be inferred by the compiler: ```kotlin fun double(x: Int) = x * 2 @@ -250,8 +284,9 @@ fun double(x: Int) = x * 2 ### Unit-returning functions -If a function has a block body and does not return a useful value, its return type is assumed to be `Unit` (corresponds to the `void` type in Java). -`Unit` is a type with only one value - `Unit`. +If a function has a block body and does not return a useful value, compiler assumes the return type to be `Unit` +(corresponds to the `void` type in Java). +`Unit` is a type with only one value, `Unit`. You don't have to specify `Unit` as a return type, except for functional type parameters, and you never have to return `Unit` explicitly. @@ -271,7 +306,8 @@ fun printHello(name: String?, aux: () -> Unit): Unit { can be shortened to: ```kotlin -// The declaration of 'aux' still needs an explicit return type +// The declaration of the functional type parameter ('aux') still +// needs an explicit return type fun printHello(name: String?, aux: () -> Unit) { if (name != null) println("Hello $name") @@ -282,7 +318,9 @@ fun printHello(name: String?, aux: () -> Unit) { ### Variable number of arguments (varargs) -You can mark a parameter of a function (usually the last one) with the `vararg` modifier: +To pass a variable number of arguments to a function, you can mark one of its parameters +(usually the last one) with the `vararg` modifier. +Inside a function, you can use a `vararg`-parameter of type `T` as an array of `T`: ```kotlin fun asList(vararg ts: T): List { @@ -293,55 +331,57 @@ fun asList(vararg ts: T): List { } ``` -In this case, you can pass a variable number of arguments to the function: +Then you can pass a variable number of arguments to the function: ```kotlin val list = asList(1, 2, 3) ``` -Inside a function, a `vararg`-parameter of type `T` is visible as an array of `T`, as in the example above, where the `ts` -variable has type `Array`. +Only one parameter can be marked as `vararg`. +If you declare a `vararg` parameter not as the last one in the list, values for subsequent parameters must be passed +using the named argument syntax, or, if a parameter has the function type, by passing a lambda outside the parentheses. -Only one parameter can be marked as `vararg`. If a `vararg` parameter is not the last one in the list, values for the -subsequent parameters must be passed using named argument syntax, or, if the parameter has a function type, by passing -a lambda outside the parentheses. - -When you call a `vararg`-function, you can pass arguments individually, for example `asList(1, 2, 3)`. If you already have -an array and want to pass its contents to the function, use the spread operator (prefix the array with `*`): +When you call a `vararg`-function, you can pass arguments individually, as in the example of `asList(1, 2, 3)`. +If you already have an array and want to pass its contents to the function in place (or as a part) of a `vararg` parameter, +use the spread operator (prefix the name of the array with `*`): ```kotlin val a = arrayOf(1, 2, 3) +// The function receives the array [-1, 0, 1, 2, 3, 4] val list = asList(-1, 0, *a, 4) ``` If you want to pass a [primitive type array](arrays.md#primitive-type-arrays) -into `vararg`, you need to convert it to a regular (typed) array using the `toTypedArray()` function: +as `vararg`, you need to convert it to a regular (typed) array using the `toTypedArray()` function: ```kotlin -val a = intArrayOf(1, 2, 3) // IntArray is a primitive type array +// 'a' is an IntArray, which is a primitive type array +val a = intArrayOf(1, 2, 3) val list = asList(-1, 0, *a.toTypedArray(), 4) ``` ### Infix notation -Functions marked with the `infix` keyword can also be called using the infix notation (omitting the dot and the parentheses -for the call). Infix functions must meet the following requirements: - -* They must be member functions or [extension functions](extensions.md). -* They must have a single parameter. -* The parameter must not [accept variable number of arguments](#variable-number-of-arguments-varargs) and must have -no [default value](#parameters-with-default-values). +You can declare functions to be called without parentheses and the dot using the `infix` keyword. +This can be useful to clear up simple function calls in your code. ```kotlin infix fun Int.shl(x: Int): Int { /*...*/ } -// calling the function using the infix notation -1 shl 2 - -// is the same as +// Calls the function using the general notation 1.shl(2) + +// Calls the function using the infix notation +1 shl 2 ``` +Infix functions must meet the following requirements: + +* They must be member functions of a class or [extension functions](extensions.md). +* They must have a single parameter. +* The parameter must not [accept variable number of arguments](#variable-number-of-arguments-varargs) (`vararg`) and must have + no [default value](#parameters-with-default-values). + > Infix function calls have lower precedence than arithmetic operators, type casts, and the `rangeTo` operator. > The following expressions are equivalent: > * `1 shl 2 + 3` is equivalent to `1 shl (2 + 3)` @@ -355,9 +395,9 @@ infix fun Int.shl(x: Int): Int { /*...*/ } > {style="note"} -Note that infix functions always require both the receiver and the parameter to be specified. When you're -calling a method on the current receiver using the infix notation, use `this` explicitly. This ensures -unambiguous parsing. +Note that infix functions always require both the receiver and the parameter to be specified. +When you call a method on the current receiver using the infix notation, use `this` explicitly. +This ensures unambiguous parsing. ```kotlin class MyStringCollection { @@ -366,14 +406,15 @@ class MyStringCollection { fun build() { this add "abc" // Correct add("abc") // Correct - //add "abc" // Incorrect: the receiver must be specified + add "abc" // Incorrect: the receiver must be specified } } ``` +{validate="false"} ## Function scope -Kotlin functions can be declared at the top level in a file, meaning you do not need to create a class to hold a function +You can declare Kotlin functions at the top level in a file, meaning you do not need to create a class to hold a function (unlike Java, for example). Functions can also be declared locally as _member functions_ and _extension functions_. @@ -393,7 +434,8 @@ fun dfs(graph: Graph) { } ``` -A local function can access local variables of outer functions (the closure). In the case above, `visited` can be a local variable: +A local function can access local variables of outer functions (the closure). +In the case above, `visited` can be a local variable: ```kotlin fun dfs(graph: Graph) { @@ -418,17 +460,18 @@ class Sample { } ``` -Member functions are called with dot notation: +To call member functions, use the dot notation: ```kotlin -Sample().foo() // creates instance of class Sample and calls foo +// Creates an instance of the `Sample' class and calls 'foo()' +Sample().foo() ``` For more information on classes and overriding members see [Classes](classes.md) and [Inheritance](classes.md#inheritance). ## Generic functions -Functions can have generic parameters, which are specified using angle brackets before the function name: +You can specify generic parameters for a function by using angle brackets before the function name: ```kotlin fun singletonList(item: T): List { /*...*/ } @@ -447,21 +490,24 @@ the recursion, leaving behind a fast and efficient loop based version instead: import kotlin.math.cos import kotlin.math.abs -val eps = 1E-10 // "good enough", could be 10^-15 +// An arbitrary "good enough" precision +val eps = 1E-10 tailrec fun findFixPoint(x: Double = 1.0): Double = if (abs(x - cos(x)) < eps) x else findFixPoint(cos(x)) ``` -This code calculates the fixed point of cosine (a mathematical constant). It simply calls `cos()` repeatedly -starting at `1.0` until the result no longer changes, yielding a result of `0.7390851332151611` for the specified -`eps` precision. The resulting code is equivalent to this more traditional style: +This code calculates the fixed point of cosine (a mathematical constant). +The function calls `cos()` repeatedly starting at `1.0` until the result no longer changes, +yielding a result of `0.7390851332151611` for the specified `eps` precision. +The code is equivalent to this more traditional style: ```kotlin import kotlin.math.cos import kotlin.math.abs -val eps = 1E-10 // "good enough", could be 10^-15 +// An arbitrary "good enough" precision +val eps = 1E-10 private fun findFixPoint(): Double { var x = 1.0 @@ -473,8 +519,9 @@ private fun findFixPoint(): Double { } ``` -To be eligible for the `tailrec` modifier, a function must call itself as the last operation it performs. You cannot use -tail recursion when there is more code after the recursive call, within `try`/`catch`/`finally` blocks, or on open functions. +To be eligible for the `tailrec` modifier, a function must call itself as the last operation it performs. +You cannot use tail recursion when there is more code after the recursive call, +within `try`/`catch`/`finally` blocks, or on [open functions](inheritance.md). **See also**: * [Inline functions](inline-functions.md) From c51c535896e248683afbc40471321cfe00985747 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Tue, 2 Dec 2025 11:00:38 +0100 Subject: [PATCH 11/12] fix: test commit --- docs/topics/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index e2ce2c96402..95b1509e058 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -99,7 +99,7 @@ fun main () { foo(1) } ``` -{kotlin-runnable="true" kotlin-min-compiler-version="1.3" validate="false"} +{kotlin-runnable="true" kotlin-min-compiler-version="1.3" validate="false" id="default-before-ordinary"} [Trailing lambdas](lambdas.md#passing-trailing-lambdas) are an exception to this rule, since the last parameter must correspond to the passed function: From cd751146b7ca02f5f9e1557493de2d1843c6e8b2 Mon Sep 17 00:00:00 2001 From: Aleksey Zamulla Date: Tue, 2 Dec 2025 12:14:02 +0100 Subject: [PATCH 12/12] fix: ids for runnable samples --- docs/topics/functions.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/topics/functions.md b/docs/topics/functions.md index 95b1509e058..d1b10994281 100644 --- a/docs/topics/functions.md +++ b/docs/topics/functions.md @@ -105,6 +105,8 @@ fun main () { since the last parameter must correspond to the passed function: ```kotlin +fun main () { +//sampleStart fun foo( foo: Int = 0, bar: () -> Unit, @@ -112,12 +114,13 @@ fun foo( { println(foo) bar() } -fun main () { - // Prints the default value 0 for 'foo', then prints "bar" - foo() { println ("bar") } + +// Prints the default value 0 for 'foo', then prints "bar" +foo() { println ("bar") } +//sampleEnd } ``` -{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} +{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="default-before-trailing-lambda"} [Overriding methods](inheritance.md#overriding-methods) always use the base method's default parameter values. When overriding a method that has default parameter values, you must omit the default parameter values from the signature: @@ -171,7 +174,7 @@ read (1, null) //sampleEnd } ``` -{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} +{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="non-constant-default"} If the last parameter in a function declaration has a functional type, you can pass the corresponding [lambda](lambdas.md#lambda-expression-syntax) argument either as a named argument or [outside the parentheses](lambdas.md#passing-trailing-lambdas): @@ -198,7 +201,7 @@ foo { println("hello") } //sampleEnd } ``` -{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} +{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="lambda-outside-parentheses"} ### Named arguments