Swift - 함수

임성빈·2022년 3월 8일
0

Swift

목록 보기
6/26
post-thumbnail
post-custom-banner

정의와 호출

함수를 선언할 때는 가장 앞에 func 키워드를 붙이고 (person: String) 파라미터와 형 그리고 -> String 형태로 반환형을 정의한다.

func greet(person: String) -> String {
	let greeting = "Hello, " + person + "!"
    return greeting
}

정의한 함수에 인자값을 넣어 호출한 예시

print(greet(person: "John"))
// "Hello, John!"

위 함수에서 메시지를 결합하는 부분과 반환하는 부분을 합쳐서 더 짧게 만들 수 있다.

func greetAgain(person: String) -> String {
	return "Hello again, " + person + "!"
}
print(greetAgain(person: "John")
// "Hello again, John!"

함수 파라미터와 반환값

파라미터가 없는 함수

func sayHelloWorld() -> String {
	return "hello, world"
}
print(sayHelloWorld())
// "hello, world"

복수의 파라미터를 사용하는 함수

func greet(person: String, alreadyGreeted: Bool) -> String {
	if alreadyGreeted {
    	return greetAgain(person: person)
    } else {
    	return greet(person: person)
    }
}
print(greet(person: "Tom", alreadyGreeted: true))
// "Hello again, Tom!"

반환값이 없는 함수

func greet(person: String) {
	print("Hello, \(person)!")
}
greet(person: "Hwe")
// "Hello, Hwe!"

주의
엄밀히 말하면 위 함수는 반환값을 선언하지 않았지만 반환값이 정의 되지 않는 함수 Void라는 특별한 형을 반환한다. Void는 간단히 ()를 사용한 빈 튜플이다.

함수의 반환값은 아래와 같이 호출 될 때 무시될 수 있다.

func printAndCount(string: String) -> Int {
	print(string
	return string.count
}

func printWithoutCounting(string: String) {
	let _ = printAndCount(string: String)
}

printAndCount(string: "hello, world")
// "hello, world" and returns a value of 12

prinWithoutCounting(string: "hello, world")
// "hello, world"

복수의 값을 반환하는 함수

튜플을 함수의 반환값으로 사용할 수 있다.

func minMax(array: [Int]) -> (min: Int, max: Int) {
	var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
    	if value < currentMin {
        	currentMin = value
        } else if value > currentMax {
        	currentMac = value
        }
    }
    return (currentMin, currentMax)
}

반환값의 인자를 반환값을 접근하는 접근자로 사용할 수 있다.

let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) 
print("min is \(bounds.min) and max is \(bounds.max)")
// "min is -6 and max is 109"

옵셔널 튜플 반환형

위의 반환값과 달리 값에 ? 물음표가 붙는다.
(min: Int, max: Int)?

func minMax(array: [Int]) -> (min: Int, max: Int)? {
	if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
    	if value < currentMin {
        	currentMin = value
        } else if value > currentMax {
        	currentMax = vlaue
        }
    }
    return (currentMin, currentMax)
}

실제 반환값에 접근하기 위해서는 if let 과 같은 옵셔널 체인을 사용하거나 강제 unwrapping을 해야 한다.

아래는 옵셔널 체인을 사용한 예시

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
	print("min is \(bounds.min) and max is \(bounds.max)"
}
// "min is -6 and max is 109"

함수 인자 라벨과 파라미터 이름

함수 호출시 적적한 파라미터 이름을 지정해 함수 내부와 함수 호출시 사용할 수 있다.

func someFunction(argumentLabel parameterName: Int) {
	// 함수 안에서 parameterName으로 argumentLabel의 인자값을 참조
}

인자 라벨을 지정해서 함수 내부에서는 hometown으로 값을 제어하고 함수 호출시 인자값으로 from을 사용한 예시

func greet(person: String, from hometown: String) -> {
	return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Kim", from: "Seoul"))
// "Hello Kim! Gald you could visit Seoul."

인자 생략

파라미터 앞에 _를 붙여 함수 호출시 인자값을 생략할 수 있다.

func someFunction(_ Parameter1: Int, Parameter2: Int) {
	// 함수 안에서 Parameter1, Parameter2
    // 인자로 입력 받은 첫번째, 두번째 값을 참조
}
someFunction(1, Parameter2: 2)

기본 파라미터 값

함수의 파라미터 값에 기본값(: Int = 12)을 생략할 수 있다.
기본값이 설정 되어 있는 파라미터는 함수 호출시 생략할 수 있다.
기본값을 사용하지 않는 파라미터를 앞에 위치 시켜야 함수를 의미 있게 사용하기 쉽다.

func someFunc(parameterWithoutDefault: Int, parameterwithDefault: Int = 12) {
	// 함수 호출시 두번째 인자를 생략하면 함수 안에서
   	// parameterWithDefault값은 12가 기본값으로 사용
}
someFunc(parameterWithoutDefault: 3, parameterWithDefault: 6)
// parameterWithoutDefault == 3, parameterWithDefault == 6

someFunc(parameterWithoutDefault: 3)
// parameterWithoutDefault == 3, parameterWithDefault == 12

집합 파라미터

인자값으로 특정 type의 집합 값을 사용할 수 있다.

func arithmeticMean(_ numbers: Double...) -> {
	var total: Double = 0
    for number in numbers {
    	total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0

arithmeticMean(3, 8.5, 18.5)
// returns 10.0

인-아웃 파라미터

인자값을 직접 변경하는 파라미터이다.
선언을 위해 파라미터 앞에 inout이라는 키워드를 사용한다.

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

아래는 실제 사용 예시

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)"
// "someInt is now 107, and anotherInt is now 3"

두 변수의 실제값이 변경되었다.

주의
인-아웃 파라미터는 기본값을 갖을 수 없고, 집합 파라미터는 inout으로 선언될 수 없다. 인-아웃 파라미터를 사용하는 것은 함수의 반환값을 사용하지 않고 함수 scope 밖에 영향을 줄 수 있는 또 하나의 방법이다.


함수형

함수의 형은 파라미터형과 반환형으로 구성 돼 있다.
아래 두 함수는 Int 값 두 개를 입력받고 Int를 반환하는 함수이다.

func addTwoInts(_ a: Int, _ b: Int) -> {
	return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
	return a * b
}

아래는 입력 받는 파라미터와 반환값이 없는 함수이다.

func printHelloWorld() {
	print("hello, world")
}

함수형의 사용

아래와 같이 함수를 변수처럼 정의해서 사용할 수 있다.

var mathFunction: (Int, Int) -> Int = addTwoInts

변수 mathFunctionaddTwoInts 함수의 인자값과 반환값이 같으므로 이 함수가 변수로 할당 될 수 있다.

print("Result \(mathFunction(2, 3))")
// "Result 5"

multiplyTwoInts 함수도 mathFunction과 함수형이 같으므로 할당해 사용할 수 있다.

mathFunction = multiplyTwoInts
print("Result: mathFunction(2, 3)")
// "Result: 6"

변수나 상수에 함수를 할당할 때 직접 함수형을 선언하지 않아도 Swift의 타입추론을 통해 자동으로 함수를 할당할 수 있다.

let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int

파라미터형으로써의 함수형

파라미터에 함수형을 사용할 수 있다.

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int,_ b: Int) {
	print("Result: \(mathFunction)")
}
printMathResult(addTwoInts, 3, 5)
// "Result: 8"

반환형으로써의 함수형

함수를 반환하는 함수를 만들수도 있다.

func stepForward(_ input: Int) -> Int {
	return input + 1
}
func stepBackwaard(_ input: Int) -> Int {
	return input - 1
}

입력한 step에 하나를 더하거나 빼는 함수를 선언했다.
이 함수를 리턴값으로 사용할 수 있다.
아래 코드는 backwardtruefalse냐에 따라 위에서 선언한 적절한 함수를 반환하는 함수이다.

func chooseStpeFunction(backward: Bool) -> (Int) -> Int {
	return backward ? stepBackward : stepForward
}

위 함수를 사용한 예시

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero는 이제 stepBackward() 함수를 가르키고 있습니다.

moveNearerToZero를 호출할 때마다 stepBackward() 함수가 호출돼 입력값이 1씩 줄어들어 결국 0이 된다.

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

중첩 함수

지금까지 함수는 전역적으로 동작하도록 선언했다. 함수 중에는 다른 함수 안의 body에서 동작하는 함수가 있는데 이 함수를 중첩 함수라 한다. 중첩 함수는 함수 밖에서 감춰져 있고 함수의 body 내에서 접근 가능하다. 위의 chooseStepFunction을 중첩 함수를 이용해 아래처럼 다시 작성할 수 있다.

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero는 이제 중첩 돼 있는 stepForward() 함수를 가르킵니다.
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
profile
iOS 앱개발
post-custom-banner

0개의 댓글