Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions concepts/higher-order-functions/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"authors": [
"kahgoh"
],
"contributors": [],
"blurb": "Functions are first class citizens in Kotlin and can be assigned to variables or passed to other functions."
}
101 changes: 101 additions & 0 deletions concepts/higher-order-functions/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# About Higher Order Functions

Functions in Kotlin are first class citizens.
This means they can be stored in variables, passed as arguments and even returned by other functions.
For example, assigning a function to the variable `addOne`:

```kotlin
val addOne = fun (num : Int) : Int {
return num + 1
}
```

A function can also return another function:

```kotlin
fun makeAddOne() : (Int) -> Int {
return fun(num : Int) : Int {
return num + 1
}
}
```

Once assigned, the function can be called through the variable as if it was just another function:
```kotlin
addOne(3)
// => 4
```

## Declaring function types

A variable or parameter type can be declared using the syntax `(parameter types) -> return type`.
For example, declaring a variable:

```kotlin
val addOne : (Int) -> Int = fun (num : Int) : Int {
return num + 1
}
```

And for a function parameter:

```kotlin
fun perform(operation : (Int) -> Int) {
operation(3)
}
```

## Lambda expressions

A lambda expression is a shorter way of defining a function.
They are written in the form `{ parameters -> body }`.
The expression returns the last value from the last statement in the body.
For example:

```kotlin
// Assigning to a variable
val addOne = { num : Int -> num + 1}

// In a function call
perform({ num : Int -> num + 1 })
```

Kotlin can infer types when there is enough information.
For example, the above examples can also be written as:

```kotlin
// Assigning to a variable
val addOne : (Int) -> Int = { num -> num + 1 }

// Or ...
val addOne = { num : Int -> num + 1 }

// Using in a function
perform({ num -> num + 1 })
```

## `it` for single parameter lambdas

When the expression has just one parameter, the parameter can be omitted.
Kotlin will then make a parameter called `it` available in the body.
For example:

```kotlin
val addOne : (Int) -> Int = { it + 1 }
```

## Passing trailing lambdas

When the last argument to a function is a lambda, the lambda expression is written directly _after_ the parentheses.
For example:

```kotlin
// Function that takes a function as last argument
fun calculateFrom(from : Int, operation : (Int) -> Int) : Int {
return operation(from)
}

// Call the calculateFrom function
calculateFrom(2) { it * 3 }
// => 6
```
101 changes: 101 additions & 0 deletions concepts/higher-order-functions/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# About Higher Order Functions

Functions in Kotlin are first class citizens.
This means they can be stored in variables, passed as arguments and even returned by other functions.
For example, assigning a function to the variable `addOne`:

```kotlin
val addOne = fun (num : Int) : Int {
return num + 1
}
```

A function can also return another function:

```kotlin
fun makeAddOne() : (Int) -> Int {
return fun(num : Int) : Int {
return num + 1
}
}
```

Once assigned, the function can be called through the variable as if it was just another function:
```kotlin
addOne(3)
// => 4
```

## Declaring function types

A variable or parameter type can be declared using the syntax `(parameter types) -> return type`.
For example, declaring a variable:

```kotlin
val addOne : (Int) -> Int = fun (num : Int) : Int {
return num + 1
}
```

And for a function parameter:

```kotlin
fun perform(operation : (Int) -> Int) {
operation(3)
}
```

## Lambda expressions

A lambda expression is a shorter way of defining a function.
They are written in the form `{ parameters -> body }`.
The expression returns the last value from the last statement in the body.
For example:

```kotlin
// Assigning to a variable
val addOne = { num : Int -> num + 1}

// In a function call
perform({ num : Int -> num + 1 })
```

Kotlin can infer types when there is enough information.
For example, the above examples can also be written as:

```kotlin
// Assigning to a variable
val addOne : (Int) -> Int = { num -> num + 1 }

// Or ...
val addOne = { num : Int -> num + 1 }

// Using in a function
perform({ num -> num + 1 })
```

## `it` for single parameter lambdas

When the expression has just one parameter, the parameter can be omitted.
Kotlin will then make a parameter called `it` available in the body.
For example:

```kotlin
val addOne : (Int) -> Int = { it + 1 }
```

## Passing trailing lambdas

When the last argument to a function is a lambda, the lambda expression is written directly _after_ the parentheses.
For example:

```kotlin
// Function that takes a function as last argument
fun calculateFrom(from : Int, operation : (Int) -> Int) : Int {
return operation(from)
}

// Call the calculateFrom function
calculateFrom(2) { it * 3 }
// => 6
```
10 changes: 10 additions & 0 deletions concepts/higher-order-functions/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"url": "https://kotlinlang.org/docs/functions.html",
"description": "Kotlin Functions documentation"
},
{
"url": "https://kotlinlang.org/docs/lambdas.html",
"description": "Kotlin Lambdas documentation"
}
]
17 changes: 15 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@
"basics"
],
"status": "wip"
},
{
"slug": "secret-agent",
"name": "secret-agent",
"uuid": "96553db0-5b98-4dcd-8a1c-882e42c3751a",
"concepts": [
"higher-order-functions"
],
"prerequisites": [
"numbers",
"strings"
],
"status": "wip"
}
],
"practice": [
Expand Down Expand Up @@ -1196,15 +1209,15 @@
"practices": [],
"prerequisites": [],
"difficulty": 6,
"status": "deprecated",
"topics": [
"conditionals",
"games",
"integers",
"lists",
"matrices",
"strings"
],
"status": "deprecated"
]
},
{
"slug": "rail-fence-cipher",
Expand Down
64 changes: 64 additions & 0 deletions exercises/concept/secret-agent/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Instructions

Hello, Agent Double-Null0111.

Your mission, should you choose to accept it, is to write a pair of tools to help you infiltrate UMBRA (United Minions Being Really Awful) headquarters and retrieve the plans for their latest really awful scheme.
There are three tools you will need to carry out this mission.

## 1. Generate an id number

Each minion has a unique identifier that changes each day and depends on the number of secrets they hold and the number of hours they sleep.
You will need to write a function that takes the day (as an `Int`) and creates an identifier generating function for the day.
The identifier is calculated by:

1. Multiply the number of secrets held by the number of hours they sleep
2. Add the day (represented as an `Int`) to the result

```kotlin
val idGenerator = makeIdGenerator(4)
idGenerator(3, 6)
// => 22

idGenerator(11, 5)
// => 59
```

## 2. Protect the recovered secret plans with a secret password

Once you have the secret plans, you will need to protect it so that only those who know the password can recover them.
In order to do this, you will need to implement the function `protectSecret(secret: String, password: String) : (String) -> String`.
This function will return another function that takes possible password strings as input.
If the entered password is correct the new function returns the hidden secret, but if the password is incorrect, the function returns "Sorry. No hidden secrets here."

```kotlin
val secretFunction = protectSecret("Steal the world's supply of french fries!", "5up3r53cr37")

secretFunction("Open sesame")
// Returns "Sorry. No hidden secrets here."

secretFunction("5up3r53cr37")
// Returns "Steal the world's supply of french fries!"
```

## 3. Find the secret password

The UMBRA base has a number of rooms guarded by a security guard who will ask you for the secret password.
The secret password depends on the room'sS number.
Unfortunately, we have know only half of the algorithm for working out the password.
The other half can be found by asking one of the minions.

Implement the `getPassword` function that takes in the room number and the minion's function and returns the secret password.
The secret number is obtained by calling the minion's function with another function representing the algorithm known by us.
Our part of the algorithm:

1. Takes two numbers and adds them together
2. Multiplies the result by the room id

```kotlin
val minionFunction = { yourFunc : (Int, Int) -> Int ->
"Password=${yourFunc(1, 3)}"
}

getPassword(5, minionFunction)
// Returns "Password=20"
```
Loading
Loading