함수
구조체, 클래스, 열거형 등 특정 타입에 연관되어 사용하는 함수를 메서드.
모듈 전체에서 전역적으로 사용할 수 있는 함수를 그냥 함수라고 합니다.
swift의 함수는 재정의(오버라이드)와 중복 정의(오버 로드)를 모두 지원합니다.
따라서 매개변수의 타입, 갯수에 따라 같은 이름의 함수를 여러 개 만들 수 있습니다.
func hello(name: String) -> String {
return "Hello \(name)!"
}
let helloJenny: String = hello(name: "Jenny")
print(helloJenny)
func introduce(name: String) -> String {
"제 이름은 " + name + "입니다."
}
let introduceJenny: String = introduce(name: "Jenny")
print(introduceJenny)
매개변수 이름과 전달인자 레이블
swift에서는 전달인자 레이블과 매개변수 이름을 따로 지정을 할 수 있습니다.
코드를 보면 어떻게 사용되는지 알 수 있습니다.
func 함수이름(전달인자 레이블 매개변수 이름: 매개변수 타입, 전달인자 레이블 매개변수 이름:
매개변수 타입...) -> 반환 타입 {
실행구문
return 반환 값
}
코드를 보면 _ (와일드카드)를 통해 다른언어처럼 매개변수를 받아올 수 있습니다.
for in문은 조건이 아니라 범위를 넣어야 함을 알 수 있습니다.
// 와일드 카드를 통해 다른언어 처럼 매개변수를 받아올 수 있습니다.
func sayHello(to name: String, _ times: Int) -> String {
var result: String = ""
// A.. < B 0부터 times 미만의 수를 묶어표현
// _를 사용하여 그냥 반복만 시키게 함
for _ in 0..<times {
result += "Hello \(name)!" + " "
}
return result
}
func sayHello(to name: String, repeatCount times: Int) -> String {
var result: String = ""
for _ in 0..<times {
result += "Hello \(name)!" + " "
}
return result
}
// 와일드 카드를 통해 다른언어 처럼 매개변수를 받아올 수 있습니다.
print(sayHello(to: "chopes", 2))
print(sayHello(to: "chopes", repeatCount: 2))
가변 매개변수와 입출력 매개변수
func sayHelloToFriends(me: String, friends names: String...) -> String {
var result: String = ""
for friend in names {
result += "Hello \(friend)!" + " "
}
result += "I'm " + me + "!"
return result
}
print(sayHelloToFriends(me: "kemi", friends: "Johansson", "Jay", "Wizplan"))
// Hello Johansson! Hello Jay! Hello Wizplan! I'm kemi!
print(sayHelloToFriends(me: "kemi"))
// I'm kemi!
함수에 매개변수를 넣어 값을 전달할 때 값을 복사해서 전달하게 되는데 참조값을 매개변수에 전달하면 어떻게 되는지 살펴봅시다.
var numbers: [Int] = [1, 2, 3]
func nonReferenceParameter(_ arr: [Int]) {
var copiedArr: [Int] = arr
copiedArr[1] = 1
}
func referenceParameter(_ arr: inout [Int]) {
arr[1] = 1
}
nonReferenceParameter(numbers)
print(numbers[1])
referenceParameter(&numbers)
print(numbers[1])
참조 변수를 넣는다고 해도 값복사로 동작하게 됩니다. 참조 변수 값으로 유지하기 위해선 함수 argument 타입 앞에 inout 을 작성하고 파라미터로 전달 할 때는 &을 앞에 붙여주면됩니다.
스위프트는 함수형 기법을 지향하기 때문에 참조변수를 유지하는것은 사이드 이펙트가 발생할 수 있기 때문에 좋지는 않습니다. 하지만 스위프트의 기반은 객체기반이기 때문에 프레임워크에서는 자주 나오는 표현입니다.
일급객체 함수
스위프트의 함수는 일급 객체이기 때문에 반환값으로 함수를 가질 수 있고 파라미터로도 함수를 가질 수 있습니다.
typealias CaculateTwoInts = (Int, Int) -> Int
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
var mathFunction: CaculateTwoInts = addTwoInts
print(mathFunction(2, 5)) // 7
mathFunction = multiplyTwoInts
print(mathFunction(2, 5)) // 10
중첩 함수
typealias MoveFunc = (Int) -> Int
func goRight(_ currentPosition: Int) -> Int {
return currentPosition + 1
}
func goLeft(_ currentPosition: Int) -> Int {
return currentPosition - 1
}
func functionForMove(_ shouldGoLeft: Bool) -> MoveFunc {
return shouldGoLeft ? goLeft : goRight
}
var position: Int = 3 // 현위치
// 현 위치가 0보다 크므로 전달되는 인자 값은 true가 됩니다.
// 현재는 goLeft함수가 들어가 있습니다.
let moveToZero: MoveFunc = functionForMove(position > 0)
print("원점으로 갑시다.")
while position != 0 {
print("\(position)...")
// goLeft(postion)과 동일..
position = moveToZero(position)
}
print("원점 도착")
중첩 함수 사용 시
typealias MoveFunc = (Int) -> Int
func functionForMove(_ shouldGoLeft: Bool) -> MoveFunc {
func goRight(_ currentPosition: Int) -> Int {
return currentPosition + 1
}
func goLeft(_ currentPosition: Int) -> Int {
return currentPosition - 1
}
return shouldGoLeft ? goLeft : goRight
}
var position: Int = -4 // 현위치
let moveToZero: MoveFunc = functionForMove(position > 0)
while (position != 0) {
print("\(position)...")
position = moveToZero(position)
}
print("원점 도착!")
7.4 종료되지 않는함수(비반환 함수 또는 비반환 메서드)
비반환 함수는 정상적으로 끝날 수 없는 함수입니다.
비반환 함수 안에서는 오류를 던진다든가, 중대한 시스템 오류를 보고하는 등의 일을 하고 프로세스를 종료해버리기 때문입니다.
비반환 메서드는 재정의는 할 수 있지만 비반환 타입이라는 것은 변경 할 수 없습니다.
반환 타입에 Never를 명시하여 사용 할 수 있습니다.
func crashAndBurn() -> Never {
fatalError("Something very, very bad happend!")
}
//crashAndBurn() // 프로세스 종료 후 보고
func someFunction(isAllIsWell: Bool) {
guard isAllIsWell else {
print("마을에 도둑이 들었습니다.")
crashAndBurn()
}
print("All is well")
}
someFunction(isAllIsWell: true)
someFunction(isAllIsWell: false)
반환 값을 무시할 수 있는 함수
func say(_ something: String) -> String {
print(something)
return something
}
@discardableResult func discardableResultSay(_ something: String) -> String {
print(something)
return something
}
// 반환 값을 사용하지 않았으므로 경고가 표시 될 수도 있다.
// 나는 뜨진 않았다.
say("hello")
// 반환 값을 사용하지 않을 수 있다고 명시하였기 때문에 경고 표시가 되지 않습니다.
discardableResultSay("hello")
일급 함수란 쉽게 말하면 함수를 객체로 받을 수도 있고, 함수를 리턴할 수 도 있는 함수입니다.
그리고 항상 입력값이 같으면 반환 값이 같은 특징을 보입니다. 이 소리는 외부에서 변경되는 값이 없다는 것이죠.
예를 들어 함수안에 글로벌 변수를 사용하게되면 글로벌 변수가 변경 될 때 마다 출력 값이 계속 바뀌겠죠.
공부를 하다보니 함수면 함수지 무슨 일급함수 같은게 있나 싶습니다.
var globalNum = 1
func plusFunction(number: Int) -> Int {
let result = globalNum + number
return result
}
plusFunction(number: 1) // 2
globalNum = 3
plusFunction(number: 1) // 4 -> 같은 1 입력값을 넣었음에도 4가 출력됨. 일급함수 아님
Swift의 이상했던 부분 중 하다가 함수가 전달인자 레이블과 매개변수 이름을 갖는 다는 것이였는데요.
왜 이렇게 했는지 조금 의문이 갑니다. to 나 with을 전달인자로 많이 받곤 하는데 제대로 된 강의나 블로그를 찾아봐야 할 것 같습니다.
'Swift > Swift 기본문법' 카테고리의 다른 글
Swift 기본 문법 - 11. 구조체와 클래스 (0) | 2022.01.30 |
---|---|
Swift 기본 문법 - 10. 옵셔널 (0) | 2022.01.18 |
Swift 기본 문법 - 8. 반복문 (0) | 2022.01.17 |
Swift 기본 문법 - 7. 흐름제어 (if, switch) (0) | 2022.01.16 |
Swift 기본 문법 - 6. 연산자 (0) | 2022.01.15 |