2. Functions (2)

Seoyoung Lee·2022년 7월 10일
0
post-thumbnail
post-custom-banner

Modifiable Parameters

파라미터는 함수 본문 안에 있는 지역 변수이다. 기본적으로 let 으로 선언되기 때문에 함수 안에서 다른 값을 할당할 수 없다.

대신 함수 안에서 var 키워드로 파라미터 이름과 같은 변수를 선언할 수 있다. 이렇게 선언한 변수의 값을 바꾸는 것은 파라미터의 복사본의 값을 바꾸는 것과 같다. 원래 파라미터가 가지는 값은 변하지 않는다.

인자로 전달된 원래 변수의 값을 바꾸려면 다음과 같은 조건이 필요하다.

  • 파라미터의 타입 앞에 inout 이라는 키워드를 붙인다.
  • 함수를 호출할 때 인자로 전달할 변수는 반드시 var 로 선언되어야 한다.
  • 변수가 아닌 주소를 인자로 전달해야 한다. & 키워드를 이용해 주소를 전달할 수 있다.
// inout 키워드 사용 예시
func removeCharacter(_ c: Character, from s: inout String) -> Int {
	var howMany = 0
	while let ix = s.firstIndex(of:c) {
		s.remove(at:ix)
		howMany += 1
	}
	return howMany
}

var s = "hello"
let result = removeCharacter("1", from: &s)

// s == "heo"
// result == 2

Calling Objective-C with Modifiable Parameters

Cocoa API는 C와 Objective-C로 작성되었기 때문에 Modifiable parameter를 쓸 때 inout 대신 UnsafeMutablePointer 라는 키워드를 사용한다.

그러나 함수를 호출하는 입장에서는 스위프트에서와 동일하게 var 변수의 주소를 전달하기만 하면 된다.

Called by Objective-C with Modifiable Parameters

가끔 Cocoa가 우리가 작성한 함수를 UnsafeMutablePointer 와 함께 호출하고, 그 값을 변경하고 싶을 때가 있다. 이때 우리는 스위프트가 아닌 Objective-C에게 말을 거는 것이기 때문에 inout 이 아닌 UnsafeMutablePointer 를 사용해야 한다.

// pointee 프로퍼티 사용에 주목
func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>) {
	view.pointee = self.button2
	rect.pointee = self.button2.bounds
}

(이 부분은 아직 Objective-C를 몰라서 이해가 잘 가지 않는다. 나중에 공부하고 다시 보는 걸로..)

Reference Type Modifiable Parameters

파라미터로 class 의 인스턴스가 올 경우에만 inout 을 사용하지 않고 파라미터의 값을 바꿀 수 있다. 인스턴스 멤버의 값을 바꿔도 파라미터로 온 인스턴스 자체는 변하지 않는다. 클래스 인스턴스는 mutuable(변경 가능)하다는 특징을 가진다.

정확하게 말하면 클래스는 reference type이고 다른 오브젝트 타입들은 value type이다. 따라서 struct의 인스턴스를 인자로 전달하면 인스턴스의 복사본이 전달된다. 반면 클래스의 인스턴스는 클래스 인스턴스의 레퍼런스가 전달된다.

Function in Function

함수는 어디서든 선언될 수 있다. 심지어 함수의 본문 안에서도 선언될 수 있다.

함수의 본문 안에서 선언된 함수(local function)은 선언된 후 같은 스코프 내에서 호출될 수 있다. 하지만 다른 곳에서는 보이지 않는다.

이는 함수의 정교한 구조를 설계할 때 유용하다. 예를 들어 함수 A만 함수 B를 호출한다면 함수 A 안에 함수 B를 포함할 수 있다.

Recursion

함수는 자기 자신을 호출할 수 있다. 이를 재귀(recursion)이라고 한다.

Function as Value

스위프트에서 함수는 일급 시민(first-class citizen)이다. 이는 함수가 값(value)이 사용되는 어느 곳에서든 사용될 수 있다는 것을 의미한다.

  • 함수가 값으로 사용되는 예시
    • 함수를 변수에 할당
    • 함수 호출시 인자에 함수 전달
    • 함수의 결과값으로 함수 반환

스위프트는 타입을 엄격하게 구분하기 때문에 함수를 값으로 사용하는 경우에는 함수가 반드시 타입을 가져야 한다. 이때 함수의 타입은 함수의 시그니처이다.

함수를 값으로 사용하는 주된 목적은 이 함수가 무엇인지 정확히 알지 않아도 나중에 함수를 값으로 사용할 수 있도록 하는 것이다.

// function f's signature: () -> ()
func doThis(_ f:() -> ()) {
	f()
}

// declare a function of the proper type(() -> ())
func whatToDo() {
	print("I did it")
}

// pass as argument a function reference
doThis(whatToDo)

Cocoa API에서는 런타임 또는 나중에 호출될 함수를 전달하는 상황이 많다. 심지어 두 개의 함수를 인자로 전달하는 경우도 많다.(ex. UIView.animate(withDuration:animations:completion) )

Cocoa 문서는 주로 전달되는 함수를 handler 라고 표현하고 이를 block 으로 참조한다. 이는 Objective-C 구문이다.

💡 Type alias로 함수 타입 명확하게 표현하기

스위프트의 typealias 를 이용하면 함수 타입에 이름을 지정해줄 수 있다. 이를 사용하면 함수 타입을 더욱 명확하게 표현할 수 있다.

profile
나의 내일은 파래 🐳
post-custom-banner

0개의 댓글