함수와 메서드는 기본적으로 같다. 상황이나 위치에 따라 다른 용어로 부른다.
구조체, 클래스, 열거형 등 특정 타입에 연관되어 사용하는 함수를 메서드
모듈 전체에서 전역적으로 사용할 수 있는 함수를 함수
즉, 함수가 위치하거나 사용되는 범위 등에 따라 호칭이 달라질 뿐이다.
함수에서는 소괄호를 생략할 수 없다.
재정의(오버라이드)와 중복정이(오버로드)를 모두 지원한다.
따라서 매개변수의 타입이 다르면 같은 이름의 함수를 여러 개 만들 수 있고, 매개변수의 개수가 달라도 같은 이름의 함수를 만들 수 있다.
ex) 기본 형태의 함수 정의와 사용
func hello(name: String) -> String {
return "Hello \(name)!"
}
let helloJoy: String = hello(name: "Joy")
print(helloJoy)
func introduce(name: String) -> String{
"my name is" + name // = return "my name is" + name
}
let introduceJoy: String = introduce(name: "Joy")
print(introduceJoy)
매개변수는 함수를 정의할 때 외부로부터 받아들이는 전달 값의 이름을 의미한다. 전달인자(Argument) 혹은 인자는 함수를 실제로 호출할 때 전달하는 값을 의미한다.
func helloWorld() -> String {
return "Hello World!"
}
print(helloWorld())
ex) 매개변수가 여러 개인 함수의 정의와 사용
func sayHello(myName: String, yourname: String) -> String{
return "Hello \(yourname) I',m \(myName)"
}
print(sayHello(myName: "Joy", yourname: "may"))
ex) 매개변수의 이름과 전달인자 레이블을 가지는 함수 정의와 사용
func sayHello(from myName:String, to name: String) -> String {
return "Hello \(name)! I'm \(myName)"
}
print(sayHello(from: "Joy", to: "may"))
ex) 전달인자 레이블이 없는 함수 정의와 사용
func sayHello(_ name:String, _ times:Int) -> String{
var result: String = ""
for _ in 0 ..< times{
result += "Hello \(name)!" + " "
}
return result
}
print(sayHello("Joy", 3))
ex) 전달인자 레이블 변경으로 통한 함수 중복 정의
func sayHello(to name:String, _ times:Int) -> String{
var result: String = ""
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: "Chope", 2))
print(sayHello(to: "Chope", repeatCount: 2))
ex) 매개변수 기본값이 있는 함수의 정의와 사용
func sayHello(_ name:String, _ times:Int = 3) -> String{
var result: String = ""
for _ in 0 ..< times{
result += "Hello \(name)!" + " "
}
return result
}
print(sayHello("Joy", 2))
print(sayHello("Joy"))
//Hello Joy! Hello Joy!
//Hello Joy! Hello Joy! Hello Joy!
ex) 가변 매개변수를 가지는 함수의 정의와 사용
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: "Joy", friends: "A", "B", "C"))
//Hello A! Hello B! Hello C! I'm Joy!
print(sayHelloToFriends(me: "Joy"))
//I'm Joy!
ex) inout 매개변수의 활용
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])
//2
//1
리턴 값이 없는 함수
ex) 반환 값이 없는 함수의 정의와 사용
func sayHelloWorld(){
print("Hello, world!")
}
sayHelloWorld() // Hello, World!
func sayHello(from myName: String, to name: String){
print("\(myName) \(name)")
}
sayHello(from: "Joy", to: "may")//Joy, may
func sayGoodbye() -> Void{
print("Bye")
}
sayGoodbye()// Bye
함수는 일급 객체이므로 데이터 타입으로 사용할 수 있다.
ex) 함수를 데이터 타입으로 나타내는 방법
func sayHello(name: String, times: Int) -> String{
// sayHello함수의 타입은 (String, Int) -> String 이다.
let exString:String = ""
return exString
}
func sayHelloFriends(me: String, names: String...) -> String{
//sayHelloFriends 함수의 타입은(String, String) -> String이다.
let exString:String = ""
return exString
}
func sayHelloWorld(){
//sayHelloWorld의 타입
//(Void) -> Void
//() -> Void
//() -> ()
}
ex) 함수 타입의 사용
typealias CalculateTwoints = (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: CalculateTwoints = addTwoInts
print(mathFunction(2,3))//5
mathFunction = multiplyTwoInts
print(mathFunction(2,3))//6
ex) 전달인자로 함수를 전달받는 함수
typealias CalculateTwoints = (Int, Int) -> Int
func addTwoInts(_ a: Int, _ b: Int) -> Int{
return a + b
}
func printMathResult(_ mathFunction: CalculateTwoints, _ a: Int, _ b: Int) {
print(mathFunction(a,b))
}
printMathResult(addTwoInts, 2, 3) // 5
ex) 특정 조건에 따라 적절한 함수를 반환해주는 함수
typealias CalculateTwoints = (Int, Int) -> Int
func addTwoInts(_ a: Int, _ b: Int) -> Int{
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int{
return a * b
}
func printMathResult(_ mathFunction: CalculateTwoints, _ a: Int, _ b: Int) {
print(mathFunction(a,b))
}
printMathResult(addTwoInts, 2, 3)
func chooseMathFunction(_ toAdd: Bool) -> CalculateTwoints{
return toAdd ? addTwoInts : multiplyTwoInts
}
printMathResult(chooseMathFunction(true), 2, 3) //5
✓ 전달인자 레이블과 함수 타입
전달인자 레이블은 함수 타입의 구성요소가 아니므로 함수 타입을 작성할 때는 전달인자 레이블을 쓸 수 없다.
let someFunction: (lhs: Int, rhs:Int) -> Int //error
let someFunction: (Int, Int) -> Int //OK
let someFunction: ( lhs: Int, rhs: Int) -> Int //OK
ex)원점으로 이동하기 위한 함수
typealias MoveFunc = (Int) -> Int
func goRight(_ currentPosition: Int) -> Int{
return currentPosition + 1
}
func goLeft(_ currentPosition: Int) -> Int{
return currentPosition - 1
}
func funtionMove(_ shouldGoLeft: Bool) -> MoveFunc{
return shouldGoLeft ? goLeft : goRight
}
var position: Int = 3
let moveToZero: MoveFunc = funtionMove(position>0)
print("원점으로 가보쟈")
while position != 0 {
print("\(position)...")
position = moveToZero(position)
}
print("원점 도착")
ex) 중첩함수의 사용
typealias MoveFunc = (Int) -> Int
func funtionMove(_ 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 = -5
let moveToZero: MoveFunc = funtionMove(position>0)
print("원점으로 가보쟈")
while position != 0 {
print("\(position)...")
position = moveToZero(position)
}
print("원점 도착")
종료되지 않는다는 의미는 정상적으로 끝나지 않는 함수라는 뜻이다.
이를 비반환 함수(Nonreturning function) 또는 비반환 메서드(Nonreturning method)라고 한다.
비반환 함수(메서드)는 정상적으로 끝날 수 없는 함수이다.
비반환 함수 안에는 오류를 던진다던가 중대한 시스템 오류를 보고하는 등의 일을 하고 프로세스를 종료한다.
비반환 함수는 어디에서든 호출이 가능하고 guard구문의 else 블록에서도 호출할 수 있다.
비반환 메서드는 재정의는 할 수 있지만 비반환 타입이라는 것은 변경할 수 없다.
비반환 함수(메서드)는 반환 타입을 Never라고 명시해주면 된다.
ex) 비반환 함수의 정의와 사용
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) //All is well
someFunction(isAllIsWell: false) // 마을에 도둑이 들었습니다. 출력 후 프로세스 종료 후 오류 보고
의도적으로 함수의 반환 값을 사용하지 않을 경우 컴파일러가 함수의 결과 값을 사용하지 않았다는 경고를 보내는 것을 @discardableResult를 선언하여 막을 수 있다.
ex) @discardableResult 선언 속성 사용
func say(_ something: String) -> String {
print(something)
return something
}
@discardableResult func discardableResultSay(_ something: String) -> String {
print(something)
return something
}
say("hello")
//반환값을 사용하지 않았으므로 경고가 표시될 수 있다.
discardableResultSay("hello")
//반환값을 사용하지 않는다고 미리 알렸기 때문에 경고 표시 되지 않는다.