[Swift 기초] 함수
2022. 3. 11. 15:28ㆍSwift 기초 정리
728x90
//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎
1. 함수 기초
- 함수(function): 재사용을 목적으로 만드는 이름을 갖는 캡슐화된 코드 블록
- 함수는 매개변수(prameter)를 받을 수 있고 값을 반환할 수도 있으나, 필요에 따라서는 그렇게 하지 않을 수도 있다.
- 함수는 코드의 어디에도 선언될 수 있다.
//매개변수가 있고 리턴값이 있는 함수의 선언
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> 반환타입 {
/*함수 구현*/
return 반환값
}
//매개변수가 있고 리턴값이 없는 함수의 선언 - 반환타입(Void) 생략 가능
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> Void {
/*함수 구현*/
return //없어도 됨
}
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) {
/*함수 구현*/
}
//매개변수가 없고 리턴값이 있는 함수의 선언
func 함수이름() -> 반환타입 {
/*함수 구현*/
}
//매개변수와 리턴값이 없는 함수의 선언
func 함수이름() -> Void {
/*함수 구현*/
}
func 함수이름() { /*함수 구현*/ }
- 프로그램의 기본적인 구성요소 - 어떤 작업을 수행하는 문장의 그룹
- 가독성의 증대, 유지관리가 쉽다.
- C언어의 차이점은 C언어는 main()함수가 꼭 필요한데 swift는 그렇지 않다.
- swift 함수는 튜플타입 리턴을 허용한다.
1-1. 함수의 호출
- 함수 호출(function call): 함수를 사용하는 것, 그냥 호출하면 된다.
- 함수를 호출하면 그 함수의 코드 블록에 있는 코드를 실행하며
- 실행이 끝나면 제어가 복귀되어 프로그램의 함수 호출 다음에 있는 코드가 계속 실행
func saySomething(){ print("Summer is so hot") } saySomething() //함수의 코드는 그 함수가 호출되어야만 실행된다
- func 키워드를 사용해서 함수 선언을 시작하고, 바로 다음에 함수의 이름을 지정
- () 속이 빈 괄호, 함수에서 인자(argument)를 받는다면 괄호 안에 정의
- {} 중괄호, 중괄호 안에 포함된 코드 블록은 함수가 호출될 때 실행
1-2. 함수의 인자
- 함수에 정보를 전달하는 것 = 인자(argument) 또는 매개변수(parameter)를 전달하는 것
- 인자나 매개변수는 함수에서 처리할 정보를 참조하며, 변수의 형태로 전달
- 서로 다른 타입의 여러 인자들을 함수로 전달할 수 있기 때문에 함수를 선언할 때 미리 이름과 타입을 정의
func saySeason(season: String){ print("It's \(season) time") }
- 함수 내부에서 사용하기 위해 변수의 이름, 변수 타입을 정의
- saySeason() 함수는 String 변수를 매개변수로 받으며, 함수 내부의 코드 블록에서 그것을 “season”으로 참조한다.
- 매개변수가 2개 이상인 경우 반드시 전달인자 레이블을 붙여서 호출해야한다.
-
func greet(name: String, day: String) -> String{ return "Hello \\(name), today is \\(day)" } print(greet(name: "정우", day: "미세먼지 없는 날")) //Hello 정우, today is 미세먼지 없는 날
1-3. 값을 반환하는 함수
- 함수의 결과를 사용하고자 할 때는 반환 값(return value)를 갖는 함수를 생성해야 한다.
- 함수의 반환 값: 함수의 코드 블록에서 처리한 결과 값
func randomInt(min: Int, max: Int) -> Int{
return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}
- -> 반환할 값의 데이터 타입 함수에서 값을 반환한다는 것을 의미
- return 처리된 결과가 함수의 반환 값이라는 것을 알려줌
- 데이터를 함수에 전달하여 함수가 그것을 처리한 후 결과를 반환하는 매커니즘은 굉장히 강력하고 중요하다.
1-4. 다중 반환값
- 튜플을 사용하면 여러개의 값을 한꺼번에 리턴할 수 있다.
-
func getPersonInfo() -> (Int, String, Int){ return (25, "김정우", 183) } print(getPersonInfo()) //(25, "김정우", 183)
- swap함수 - 튜플 재조합
func swap(p1: String, p2: String) -> (String, String){ return (p2, p1) } var n1 = "잘생긴" var n2 = "정우" print("before swap: n1 = \(n1), n2 = \(n2)") (n1, n2) = swap(p1: n1, p2: n2) print("after swap: n1 = \(n1), n2 = \(n2)") //before swap: n1 = 잘생긴, n2 = 정우 //after swap: n1 = 정우, n2 = 잘생긴 //swift에서는 별도로 swap을 정의하지 않아도 충분히 swap할 수 있다. (n1, n2) = (n2, n1)
1-5. 함수 중복 정의
- 함수명이 같아도 매개변수가 다르면 중복해서 정의할 수 있다.
-
func getPersonInfo() -> (Int, String, Int){ return (25, "김정우", 183) } func getPersonInfo(name: String){ print(name) } getPersonInfo() //(25, "김정우", 183) getPersonInfo(name: "김정우") //김정우
- 함수명이 같을 때 리턴값만 다르면 중복해서 정의할 수 없다.
- Ambiguous use of '함수명’
func getPersonInfo() -> (Int, String, Int){ return (25, "김정우", 183) } func getPersonInfo() -> (Int, String){ return (25, "김정우") } getPersonInfo() //Ambiguous use of 'getPersonInfo()'
2. 함수 고급
2-1. 기본값을 갖는 매개변수
- 기본값을 갖는 매개변수는 매개변수 목록 중에 뒤쪽에 위치하는 것이 좋다.
- 매개변수 기본값을 가지는 매개변수는 생략할 수 있다.
2-2. 개수가 정해지지 않은 매개변수 함수: 가변 매개변수, 가변인자 함수
- 매개변수에 ...을 사용하면 개수가 정해지지 않은 파라미터를 받을 수 있다.
-
func sum(_ numbers: Int...) -> Int{ var sum = 0 for number in numbers{ sum += number } return sum } print(sum(1,2,3)) //6 print(sum(1,2,3,4,5)) //15
2-3. 함수타입 상수, 변수
- 함수타입(형)의 상수나 변수를 만들어 함수를 할당(assign)할 수 있다.
- 함수타입(형) 변수에 레이블을 사용할 경우 error
- Extraneous argument labels 'a:b:' in call
func addTwoInts(a: Int, b: Int) -> Int{ return a + b } //이 변수가 addTwoInts 함수를 참조하고 있다. var mathFunction: (Int, Int) -> Int mathFunction = addTwoInts //mathFunction(a:2, b:3) //Extraneous argument labels 'a:b:' in call print(mathFunction(2, 3)) //5
- 함수형을 매개변수로 사용할 수 있다.
func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int){ print("Result: \(mathFunction(a, b))") } printMathResult(mathFunction: addTwoInts, a: 3, b: 5) //Result: 8
2-4. 함수의 반환
- → (Int) → Int
- 리턴타입이 (타입형)을 매개변수로 받아서 타입형을 리턴하는 함수
-
func stepForward(input: Int) -> Int{ return input + 1 } func stepBackward(input: Int) -> Int{ return input - 1 } func chooseStepFunction(backwards: Bool) -> (Int) -> Int{ return backwards ? stepBackward : stepForward } print(chooseStepFunction(backwards: true)(10)) //9 print(chooseStepFunction(backwards: false)(10)) //11
2-5. 함수안에 함수: 중첩함수
- 중첩 함수(nested function): 다른 함수의 코드 블록 내부에 선언된 함수
- 부모 함수에 국한되어 사용될 캡슐화된 코드를 갖는 함수
- 부모 함수 내부에 선언
- 내부 함수가 리턴할 수 있다.
3. 함수안에 함수: 중첩함수
- 중첩 함수(nested function): 다른 함수의 코드 블록 내부에 선언된 함수
- 외부 함수에 국한되어 사용될 캡슐화된 코드를 갖는 함수(외부 함수 내부에 선언)
- 내부의 중첩된 함수는 외부함수에 선언된 변수를 사용할 수 있다.
- 내부 함수가 리턴할 수 있다.
func chooseStepFunction(backwards: Bool) -> (Int) -> Int{
func stepForward(input: Int) -> Int{
return input + 1}
func stepBackward(input : Int) -> Int{
return input - 1}
return backwards ? stepBackward: stepForward
}
print(chooseStepFunction(backwards: true)(10)) //9
print(chooseStepFunction(backwards: false)(10)) //11
- 중첩함수의 호출은 함수 내부에서만 가능하므로 내부적으로 은닉이 가능하다는 장점이 있다.
- 함수는 매개변수로 사용될 수 있고 리턴타입으로 사용할 수 있다.
3-1. 변수/상수의 범위와 함수
- 변수의 범위(scope): 프로그램의 어떤 부분에서 변수르 사용할 수 있는지를 나타낸다.
- 전역(global) 범위: 프로그램 어디서든 사용 가능하다. 모든 함수의 외부에 선언
var height = 1000 let width = 10.55 func myFunc() -> Double{ return Double(height) + width } myFunc() //1010.55 print(height) //1000
- 변수 score, 상수 width를 함수 내부와 외부 어디서든 사용할 수 있다.
- 지역(local) 범위: 지역 범위를 갖는 변수는 선언된 함수 내부에서만 엑세스할 수 있다.
var height = 1000 let width = 10.55 func myFunc(row: Double) -> Double{ var column = 10.0 //지역변수 선언 return Double(height) + width + column + row } print(row) //Cannot find 'row' in scope print(height) //Cannot find 'height' in scope
- 함수 내부에서 ‘height’ 변수를 생성했으므로 변수가 존재한다는 것을 알지만, 프로그램에서는 해당 변수를 액세스할 수 없다.
- 함수의 인자는 지역범위를 갖는다.
3-2. 외부함수와 내부함수
- 내부함수는 외부함수의 값을 읽어(캡쳐) 처리할 수 있다.
- 내부함수는 외부함수가 실행되는 순간 생성되고 종료되는 순간 소멸된다.
//funcA: 외부함수, funcB: 내부함수
func funcA() -> Int{
var a = 10
//중첩함수 funcB()는 외부함수 funcA()의 내부 변수 a를 읽고 수정할 수 있다.
func funcB(){
a = a + 10
}
funcB()
return a
}
print(funcA()) //20
print(funcA()) //20
3-2. 중첩함수 리턴, 중첩함수 변수의 참조 캡쳐
- 중첩함수를 반환하여 이 함수를 함수 외부에서 사용할 수 있다.
- -> ((Int) -> Int)
-
//makeInc1()함수는 addOne함수를 리턴 func makeInc1() -> ((Int) -> Int){ func addOne(number: Int) -> Int{ return number + 1 } return addOne } //반환된 값을 참조할 수 있는 변수 var increment = makeInc1() print(increment(7)) //8 print(increment(7)) //8
- -> () -> Int
-
func makeInc2(amount: Int) -> () -> Int{ var runningTotal = 10 func incrementor() -> Int{ runningTotal += amount return runningTotal } return incrementor } //호출할 때 마다 누적해서 증가: 내부함수(runningTotal)가 어딘가에 캡쳐되어 있다. //runningTotal 변수를 바깥 함수로부터 참조캡쳐하였기 때문 var incFive = makeInc2(amount: 5) print(incFive()) //15 print(incFive()) //20 //incFive와 incTen가 참조하고 있는 runningTotal은 서로 다른 메모리공간에서 참조(캡처)되어 있다. var incTen = makeInc2(10) print(incTen()) //20 print(incTen()) //30
- 내부함수 Incrementor()는 외부함수 makeInc2()가 호출될 때 생성되어 외부함수의 호출이 종료되면 소멸
- incFive, incTen이라는 외부참조변수가 incrementor()를 참조하여 생명이 유지되는 것을 확인할 수 있다.(위의 두 예제의 결과가 다른 이유)
- 외부에서 참조하는 변수나 상수가 있을 경우 내부함수는 참조되어 생명이 유지된다.
참고하였습니다. 감사합니다.
https://yagom.net/courses/swift-basic/lessons/함수/
https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1891?tab=curriculum
https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1894?tab=note
23.07.06 수정) Swift 쉽게, 더 쉽게
728x90
'Swift 기초 정리' 카테고리의 다른 글
[Swift 기초] 클로저 Closure (0) | 2022.03.14 |
---|---|
[Swift 기초] 제너릭 (0) | 2022.03.11 |
[Swift 기초] 제어구문-반복문 (0) | 2022.03.07 |
[Swift 기초] 제어구문 - 조건문(흐름제어) (0) | 2022.03.07 |
[Swift 기초] 컬렉션 타입 (0) | 2022.03.06 |