Skip to content

Commit 67240c4

Browse files
committed
Examples 19-24
1 parent 17a4b61 commit 67240c4

File tree

7 files changed

+936
-192
lines changed

7 files changed

+936
-192
lines changed

contents/[19]functions/index.md

Lines changed: 138 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,159 @@ description: ""
44
order: 19
55
---
66

7+
Functions are self-contained pieces of code that perform a specific task. You give each function a name that describes what it does, and you use this name to "call" the function whenever you need it to do its job. This makes your code clearer, shorter, and more organized.
78

8-
foo
9+
```swift
10+
func greet() {
11+
print("Hello World!")
12+
}
13+
14+
greet()
15+
```
16+
17+
Functions can accept parameters, which are values you pass into the function to customize its behavior. By defining parameters, you allow your function to work with different inputs each time it is called:
18+
19+
```swift
20+
func greet(
21+
name: String
22+
) {
23+
print("Hello, \(name)!")
24+
}
25+
greet(name: "Tibor")
26+
greet(name: "Kitti")
27+
```
28+
29+
You can customize how you use functions and make them easier to understand by adding custom **argument labels**. These labels appear before the parameter name and are separated by a space. They help make your function calls more readable and user-friendly:
30+
31+
```swift
32+
func greet(
33+
to name: String
34+
) {
35+
print("Hello, \(name)!")
36+
}
37+
38+
greet(to: "Tibor")
39+
```
40+
41+
If you do not want to use a label at all, place an underscore `_` before the parameter name. This allows you to call the function using just the parentheses and the argument, without any label. The function's behavior stays the same, so you can choose to show or hide argument labels based on what makes your code clearer and easier to read:
42+
43+
```swift
44+
func greet(
45+
_ name: String
46+
) {
47+
print("Hello, \(name)!")
48+
}
49+
// calling the function
50+
greet("Tibor")
51+
```
52+
53+
When using default parameter values, you can omit that argument from the function call. If you do, the function will automatically use the default value you provided:
54+
55+
```swift
56+
func greet(
57+
to name: String = "Guest"
58+
) {
59+
print("Hello, \(name)!")
60+
}
61+
62+
greet()
63+
greet(to: "Tibi")
64+
```
65+
66+
Functions can also have more than one parameter:
67+
68+
```swift
69+
func sumNumbers(
70+
_ a: Int,
71+
_ b: Int
72+
) {
73+
let sum = a + b
74+
print("Sum: ", sum)
75+
}
76+
// function call with two arguments: 42 and 69
77+
sumNumbers(42, 69)
78+
```
79+
80+
A variadic parameter in Swift lets a function accept zero or more values of a specific type, so you can pass any number of arguments you need. To define a variadic parameter, add `...` after the parameter's type:
81+
82+
```swift
83+
func sumNumbers(
84+
_ numbers: Int...
85+
) {
86+
var sum = 0
87+
for number in numbers {
88+
sum += number
89+
}
90+
print("Sum: ", sum)
91+
}
92+
93+
sumNumbers()
94+
sumNumbers(42)
95+
sumNumbers(42, 69)
96+
sumNumbers(42, 69, 4, 2, 6, 9)
97+
```
98+
99+
Parameter overloading allows you to define multiple functions with the same name, as long as they have different parameter types or a different number of parameters. This is also known as function overloading:
9100

10101
```swift
11-
let x = 5
12-
let y = 5
13-
var z = 0
102+
// function with Int type parameter
103+
func displayValue(value: Int) {
104+
print("Integer value:", value)
105+
}
14106

15-
z = x + y // addition
16-
print(z) // => 10
107+
// function with String type parameter
108+
func displayValue(value: String) {
109+
print("String value:", value)
110+
}
17111

18-
z = x - y // subtraction
19-
print(z) // => 0
112+
// function call with String type parameter
113+
displayValue(value: "Swift")
20114

21-
z = x * y // multiplication
22-
print(z) // => 25
115+
// function call with Int type parameter
116+
displayValue(value: 2)
117+
```
23118

24-
z = x / y // division
25-
print(z) // => 1
119+
Swift will automatically choose the correct function to call based on the type and number of arguments you provide. It uses both the number and types of parameters to determine which version of the function to execute.
26120

121+
A function return type specifies the type of value a function gives back after it finishes executing. The return value is the actual result that the function produces:
27122

28-
var x = 10
123+
```swift
124+
func square(number: Int) -> Int {
125+
let result = number * number
126+
return result
127+
}
29128

30-
x += 2 // addition
31-
print(x) // => 12
129+
let result = square(number: 4)
130+
print(result)
32131

33-
x -= 2 // subtraction
34-
print(x) // => 10
132+
let doubled = result * 2
133+
print(doubled)
134+
```
35135

36-
x *= 2 // multiplication
37-
print(x) // => 20
136+
For functions that have only a single expression, you can leave out the `return` keyword and simply write the expression itself:
38137

39-
x /= 2 // division
40-
print(x) // => 10
138+
```swift
139+
func square(number: Int) -> Int {
140+
number * number
141+
}
41142
```
42143

43-
bar
144+
A function can also return a tuple, allowing you to return multiple values at once. Tuples group several values into a single compound value, which can be useful when you want to provide more than one result from a function:
44145

45-
```sh
46-
swift main.swift
146+
```swift
147+
func minMax(
148+
numbers: [Int]
149+
) -> (min: Int, max: Int) {
150+
let minValue = numbers.min() ?? 0
151+
let maxValue = numbers.max() ?? 0
152+
return (min: minValue, max: maxValue)
153+
}
154+
155+
let result = minMax(numbers: [3, 7, 2, 9])
156+
print(result.min)
157+
print(result.max)
47158
```
48159

49-
baz
160+
In this example, the `minMax` function returns both the minimum and maximum values from an array as a tuple.
161+
162+

contents/[20]closures/index.md

Lines changed: 122 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,143 @@ description: ""
44
order: 20
55
---
66

7+
A closure in Swift is a block of code that you can store in a variable, pass around in your program, and run whenever you need. You can think of closures as function-like values — they work very much like functions, but they do not always need a name.
78

8-
foo
9+
```swift
10+
let greet = {
11+
print("Hello, world")
12+
}
13+
greet()
14+
```
15+
16+
Closures can also have parameters. You also need to define the type of the parameters, just like you'd do when defining the parameters of a function. The syntax is just slightly different:
17+
18+
```swift
19+
let greet = { (name: String) in
20+
print("Hello, \(name)")
21+
}
22+
23+
greet("Tibi")
24+
```
25+
26+
Closures can also return values:
27+
28+
```swift
29+
let sum = { (num1: Int, num2: Int) -> Int in
30+
return num1 + num2
31+
}
32+
33+
let res = sum(2, 3)
34+
print(res) // 5
35+
```
36+
37+
Here is an example of a function and a closure, both performing the same task:
38+
39+
```swift
40+
func sum(num1: Int, num2: Int) -> Int {
41+
number + number
42+
}
43+
44+
let add = { (num1: Int, num2: Int) -> Int in
45+
num1 + num2
46+
}
47+
```
48+
49+
It is possible to move out the closure type information from the definition and explicitly tell the type of the `add` constant instead. The following example is the exact same as the previous one, but we've moved the type information to the left:
50+
51+
```swift
52+
let add: ((Int, Int) -> Int) = { num1, num2 in
53+
num1 + num2
54+
}
55+
```
56+
57+
If you have a function with the same signature (exact same parameter types and return types), you can use that function as a closure:
958

1059
```swift
11-
let x = 5
12-
let y = 5
13-
var z = 0
60+
func add(a: Int, b: Int) -> Int {
61+
a + b
62+
}
1463

15-
z = x + y // addition
16-
print(z) // => 10
64+
let sum: (Int, Int) -> Int = add
65+
sum(2, 3) // 5
66+
```
1767

18-
z = x - y // subtraction
19-
print(z) // => 0
68+
By assigning a function to a variable like sum, you _treat behavior_ as _data_. This means you can change what sum actually does at runtime:
2069

21-
z = x * y // multiplication
22-
print(z) // => 25
70+
```swift
71+
func add(a: Int, b: Int) -> Int { a + b }
72+
func multiply(a: Int, b: Int) -> Int { a * b }
2373

24-
z = x / y // division
25-
print(z) // => 1
74+
var operation: (Int, Int) -> Int = add
75+
print(operation(3, 4))
2676

77+
operation = multiply
78+
print(operation(3, 4))
79+
```
2780

28-
var x = 10
81+
By the way, in Swift, every identifier must be unique within its scope. That means you can't define a variable and a function with the same name in the same place—Swift won't know which one you mean. You get a compiler error.
2982

30-
x += 2 // addition
31-
print(x) // => 12
3283

33-
x -= 2 // subtraction
34-
print(x) // => 10
84+
A function parameter can be a closure, in the example below it takes two integers and returns an integer after performing a specific operation on them:
3585

36-
x *= 2 // multiplication
37-
print(x) // => 20
86+
```swift
87+
func performOperation(
88+
_ a: Int,
89+
_ b: Int,
90+
_ op: ((Int, Int) -> Int)
91+
) {
92+
print(op(a, b))
93+
}
94+
95+
performOperation(3, 1, { a, b in a + b })
96+
performOperation(3, 1, { a, b in a - b })
97+
```
3898

39-
x /= 2 // division
40-
print(x) // => 10
99+
Once you feel more comfortable with closures, you can switch to writing shorter, more concise versions that are easier to read and maintain. Here are some examples to show how you can make closures more concise as you get comfortable with the syntax:
100+
101+
```swift
102+
// longest form, explicit types and return keyword
103+
performOperation(3, 1, { (a: Int, b: Int) -> Int in return a + b })
104+
// no explicit types
105+
performOperation(3, 1, { a, b in return a + b })
106+
// no explicit return keyword
107+
performOperation(3, 1, { a, b in a + b })
108+
// most simple, shorthand argument names called "trailing closure syntax:
109+
performOperation(3, 2, { $0 * $1 })
41110
```
42111

43-
bar
112+
When a function's last parameter is a closure, you can use trailing closure syntax to make the function call simpler and easier to read:
44113

45-
```sh
46-
swift main.swift
114+
```swift
115+
performOperation(3, 2) { $0 * $1 } // 6
47116
```
48117

49-
baz
118+
You can also use multiple trailing closure syntax when a function has more than one closure parameter:
119+
120+
```swift
121+
func getPointFromClosures(
122+
x: () -> Int,
123+
y: () -> Int
124+
) -> (x: Int, y: Int) {
125+
(x(), y())
126+
}
127+
128+
let point = getPointFromClosures { 42 } y: { 69 }
129+
130+
print(point.x, point.y)
131+
```
132+
133+
Because operators are also functions in Swift, you can use them as closure parameters just like you would with regular functions:
134+
135+
```swift
136+
func mul(_ a: Int, b: Int) -> Int {
137+
a * b
138+
}
139+
performOperation(3, 2, mul)
140+
141+
performOperation(3, 2, +)
142+
performOperation(3, 2, *)
143+
```
144+
145+
By using operators as closure parameters, your Swift code can become simpler and easier to follow, especially in cases where you want to perform standard operations in a flexible way.
146+

0 commit comments

Comments
 (0)