249 lines
4.1 KiB
Plaintext
249 lines
4.1 KiB
Plaintext
h4. Define a package
|
|
|
|
{jet}
|
|
package my.demo // One per file
|
|
|
|
import std.io.*
|
|
|
|
// ...
|
|
{jet}
|
|
|
|
See [Packages].
|
|
|
|
h4. Define a function
|
|
|
|
{jet}
|
|
// Return type mandatory
|
|
fun sum(a : Int, b : Int) : Int {
|
|
return a + b
|
|
}
|
|
{jet}
|
|
|
|
or
|
|
|
|
{jet}
|
|
// Return type may be inferred
|
|
fun sum(a : Int, b : Int) = a + b
|
|
{jet}
|
|
|
|
When no meaningful value returned:
|
|
{jet}
|
|
fun printSum(a : Int, b : Int) : Unit {
|
|
print(a + b)
|
|
}
|
|
{jet}
|
|
|
|
or
|
|
|
|
{jet}
|
|
// Return type is optional when Unit is intended
|
|
fun printSum(a : Int, b : Int) {
|
|
print(a + b)
|
|
}
|
|
{jet}
|
|
|
|
See [Functions].
|
|
See [Hello, world!].
|
|
|
|
h4. Define a local variable
|
|
|
|
Assign-once (read-only) local variable:
|
|
{jet}
|
|
val a : Int = 1
|
|
val b = 1 // Type is inferred
|
|
val c : Int // Type required when no initializer provided
|
|
c = 1 // definite assignment
|
|
{jet}
|
|
|
|
Note that [semicolons are optional|Grammar#Semicolons].
|
|
|
|
Mutable variable:
|
|
{jet}
|
|
var x = 5 // Type inferred
|
|
x += 1
|
|
{jet}
|
|
|
|
See also [Properties And Fields].
|
|
|
|
h4. Use a string template
|
|
|
|
{jet}
|
|
fun main(args : Array<String>) {
|
|
if (args.size == 0) return
|
|
|
|
print("First argument: ${args[0]}")
|
|
}
|
|
{jet}
|
|
|
|
See [String templates|Strings#Templates].
|
|
See [Arrays|Basic types#Arrays].
|
|
|
|
h4. Use a conditional expression
|
|
|
|
{jet}
|
|
fun max(a : Int, b : Int) : Int {
|
|
if (a > b)
|
|
return a
|
|
else
|
|
return b
|
|
}
|
|
{jet}
|
|
|
|
or
|
|
{jet}
|
|
// 'if' is an expression
|
|
fun max(a : Int, b : Int) = if (a > b) a else b
|
|
{jet}
|
|
|
|
See [{{if}} expressions|Control structures#If].
|
|
|
|
h5. Null-checks
|
|
|
|
A reference must be explicitly marked as _nullable_ to be able hold a {{null}}:
|
|
{jet}
|
|
package multiplier
|
|
|
|
// Return null if str does not hold a number
|
|
fun parseInt(str : String) : Int? {
|
|
// ...
|
|
}
|
|
|
|
fun main(args : Array<String>) {
|
|
if (args.size < 2) {
|
|
print("No number supplied");
|
|
}
|
|
val x = parseInt(args[0])
|
|
val y = parseInt(args[1])
|
|
|
|
// We cannot say 'x * y' now because they may hold nulls
|
|
|
|
if (x != null && y != null) {
|
|
print(x * y) // Now we can
|
|
}
|
|
}
|
|
{jet}
|
|
|
|
or
|
|
|
|
{jet}
|
|
// ...
|
|
if (x == null) {
|
|
print("Wrong number format in '${args[0]}'")
|
|
return
|
|
}
|
|
if (y == null) {
|
|
print("Wrong number format in '${args[1]}'")
|
|
return
|
|
}
|
|
print(x * y) // Now we know that x and y are not nulls
|
|
{jet}
|
|
|
|
See [Null-safety].
|
|
|
|
h5. {{is}}-checks and automatic casts
|
|
|
|
The *is* operator checks if an expression is an instance of a type (and [more|Pattern matching]). If we *is*-checked an immutable local variable or property, there's no need to cast it explicitly to the *is*-checked type:
|
|
{jet}
|
|
fun getStringLength(obj : Any) : Int? {
|
|
if (obj is String)
|
|
return obj.length // no cast to String is needed
|
|
return null
|
|
}
|
|
{jet}
|
|
|
|
or
|
|
|
|
{jet}
|
|
fun getStringLength(obj : Any) : Int? {
|
|
if (obj !is String)
|
|
return null
|
|
return obj.length // no cast to String is needed
|
|
}
|
|
{jet}
|
|
|
|
See [Classes and Inheritance].
|
|
See [Type casts].
|
|
|
|
h4. Use a {{for}}-loop
|
|
|
|
{jet}
|
|
fun main(args : Array<String>) {
|
|
for (arg in args)
|
|
print(arg)
|
|
|
|
// or
|
|
|
|
for (i in args.indices)
|
|
print(args[i])
|
|
}
|
|
{jet}
|
|
|
|
See [{{for}}-loops|Control structures#For].
|
|
|
|
h4. Use a {{while}}-loop
|
|
|
|
{jet}
|
|
fun main(args : Array<String>) {
|
|
var i = 0
|
|
while (i < args.size)
|
|
print(args[i++])
|
|
}
|
|
{jet}
|
|
|
|
See [{{while}}-loop|Control structures#While].
|
|
|
|
h4. Use pattern-matching
|
|
|
|
{jet}
|
|
fun cases(obj : Any) {
|
|
when (obj) {
|
|
1 -> print("One")
|
|
"Hello" -> print("Greeting")
|
|
is Long -> print("Long")
|
|
!is String -> print("Not a string"
|
|
else -> print("Unknown")
|
|
}
|
|
}
|
|
{jet}
|
|
|
|
See [Pattern matching].
|
|
|
|
h4. Use ranges and {{in}}
|
|
|
|
Check if a number lies within a range:
|
|
{jet}
|
|
if (x in 1..y-1)
|
|
print("OK")
|
|
{jet}
|
|
|
|
Check if a number is out of range:
|
|
{jet}
|
|
if (x !in 0..array.lastIndex)
|
|
print("Out")
|
|
{jet}
|
|
|
|
Check if a collection contains an object:
|
|
{jet}
|
|
if (obj in collection) // collection.contains(obj) is called
|
|
print("Yes")
|
|
{jet}
|
|
|
|
Iterate over a range:
|
|
{jet}
|
|
for (x in 1..5)
|
|
print(x)
|
|
{jet}
|
|
|
|
See [Ranges].
|
|
|
|
h4. Use function literals to filter and map collections
|
|
|
|
{jet}
|
|
names filter {it.startsWith("A")} sortby {it} map {it.toUpperCase()} foreach {print(it)}
|
|
{jet}
|
|
|
|
See [Higher-order functions|Functions#Higher-order functions] and [Function literals].
|
|
|
|
h3. What's next
|
|
|
|
* [Address book example|Address book] |