Swift로 코딩하다 보면 함수 하나 짜는 것도 은근히 헷갈린다.
특히 리턴은 꼭 적어야 하나? 파라미터 앞에 언더바(_)는 왜 붙이는 걸까? 함수 안에 또 함수를 넣어도 되나? 같은 의문이 계속 생긴다.
그래서 오늘은 함수 관련해서 헷갈릴만한 포인트를 쫙 정리해봤다.
나중에 블로그 다시 보면서 기억도 되살릴 겸 써놓는 기록이다.
Swift에서 리턴이 없으면 그냥 Void다.
정확히 말하면 Void == () 빈 튜플이다.
func sayHello(name: String) {
print("Hello, \(name)!")
}
이 함수는 아무것도 안 돌려준다. 그냥 출력만 하고 끝.
그럼 여기서 궁금한 게 하나 생긴다.
리턴이 있어야 좋은 함수일까?
결론은 그때마다 다르다.
값을 밖으로 전달할 필요가 있으면 -> 타입을 명시하고 return을 써주면 된다.
func plusTwo(value: Int) -> Int {
return value + 2
}
이건 명확히 Int를 돌려주는 함수. 이렇게 어떤 타입을 리턴받는지 확인하기 좋다.
Swift에서는 한 줄짜리 계산식이면 return을 생략할 수 있다.
func plus(_ a: Int, _ b: Int) -> Int {
a + b
}
이런 식으로 간단한 함수는 깔끔하게 쓸 수 있다.
그런데 여러 줄이 된다면 무조건 return을 명시해야 한다.
func plus(_ a: Int, _ b: Int) -> Int {
let result = a + b
return result
}
한 줄이면 생략, 두 줄 이상이면 return 꼭 써줘야 된다.
그런데.... 이런 식으로 리턴은 했는데 타입을 안 썼다?
func wrongReturn(value: Int) {
return value + 2 // ❌ 오류
}
에러가 난다. 왜냐면 Void 함수는 값을 돌려줄 수 없기 때문.
리턴할 거면 타입도 꼭 같이 써야 한다.
@discardableResult라는 게 있다.
이건 뭐냐면, 리턴값을 무시해도 경고 안 뜨게 해주는 키워드다.
쉽게 말해서 리턴값이 있지만, 쓰이지 않았다는 경고를 무시하기 위한 어노테이션이라고 보면된다.
@discardableResult
func logAction(_ message: String) -> Bool {
print("LOG: \(message)")
return true
}
Swift에서는 안정성과 명확성을 중요시하기 때문에 리턴을 무시할 때도 명시적으로 작성해줘야 된단다...
_func add(_ a: Int, _ b: Int) -> Int {
a + b
}
이런 식으로 _를 붙이면 호출할 때 외부 파라미터 이름을 생략할 수 있다.
add(3, 5) // 깔끔하게 호출 가능
반면, 이건 좀 다르다
func addNumbers(a: Int, b: Int) -> Int {
a + b
}
addNumbers(a: 3, b: 5) // 외부 이름 붙여야 함
즉, _는 외부 이름 생략하겠다는 선언이다.
Swift는 중첩 함수(nested function)도 가능하다.
func complicatedStuff(with value: Int) -> Int {
func subLogic(value: Int) -> Int {
value + 2
}
return subLogic(value: value + 3)
}
여기서 subLogic은 complicatedStuff 안에서만 쓸 수 있다.
이걸 잘 쓰면 복잡한 로직을 깔끔하게 나눌 수 있다.
설명해줄 때 클로저랑 비슷하다는데.... 클로저는 다음 시간에 가르쳐준단다. 기다려보자.
with, by, from은 왜 붙이는 거지?func fetchUserData(
with id: Int,
by your: String,
from me: String) { ... }
이런식으로 쓰는 것은 js, pyhon, java에서는 못보던 형태일 것이다.
with, by, from 등은 그냥 외부 파라미터 이름일 뿐이다.
반대로 id, your, me는 내부 파라미터 이름이다.
코드 외부에서 파라미터 넣을 때는 with, by, from를 사용해 주지만,
fetchUserData(with: 123) // 외부에서 파라미터 넣을 경우
내부에서 사용할 때는 id, your, me를 사용해준다.
func fetchUserData(
with id: Int,
by your: String,
from me: String) -> Int {
retrun "\(your)" + "\(me)" // 내부에서 파라미터를 사용할 경우
}
생략하고 싶으면 _를 쓰면 된다.