Mar 16, 2021, TIL (Today I Learned) - 매개변수, 클로저

Inwoo Hwang·2021년 8월 26일
0
post-thumbnail

학습내용

매개변수라는 단어가 싫지만 헷갈리기에 작성하는 글

매개변수란?

  • 매개변수 또는 parameter란 변수를 함수와 같은 동작을 하는 기능의 인풋으로 제공되는 데이터를 가리키기 위해 사용된다.

  • 이렇게 인풋으로 제공되는 데이터를 우리는 전달인자(argument)라고 부른다.

Swift의 함수에서는 name : type 과 같은 형태로 매개변수를 받을 수 있다.

전달인자 레이블은 밖에서 보이는 이 매개변수의 별명이라고 볼수 있다.

T1 이상혁 선수가 게임을 하면 우리는 게임 화면에서 SKT T1 Faker 라는 이름을 가진 캐릭터를 볼 수 있고 비슷한 맥락으로 함수에 집어넣은 매개변수를 다른 곳에서 사용할 때 우리는 프로그래머가 정해 놓은 전달인자 레이블을 매개변수 를 이름 대신 보는 것이다.

매개변수 기본 값

매개변수에 기본값을 설정하여 전달 값을 넘겨 주지 않아도 동작할 수 있도록 만드는 것

func hihiroo( me: String, friends: String, mother: String: "엄마")
mother매개변수가 기본값 "엄마를 " 갖는다

*기본값이 없는 매개변수를 기본값이 있는 매개변수 앞에 두는 것이 좋다.

가변 매개변수

매개변수로 몇 개의 전달인자가 들어올지 모를 때 사용한다.

func hihiroo( me: String, friends: String, parents: String ...)

요런식으로 ... 을 활용하여 가변 매개변수를 사용한다.

입출력 매개변수

보통 함수의 전달인자로 값을 전달할 때는 값으 복사 해서 전달한다!

값이 아닌 참조 를 전달하려면 입출력 매개변수를 사용한다.

참조를 전달인자로 보내면 함수 내부에서 참조하여 받은 데이터의 원래 값을 변경한다.

  • 애플에서는 객체지향 프로그래밍 패러다임을 사용하므로 유용할 수 있지만..
  • 이는 함수 외부의 값에 어떤 영향을 줄 지 모르기에 함수형 프로그래밍 패러다임에서는 지양하는 패턴이다.

입출력 매개변수의 전달 순서는 다음과 같다.

  1. 함수를 호출할 때, 전달인자의 값을 복사한다.
  2. 해당 전달인자의 값을 변경하면 1에서 복사한 것을 함수 내부에서 변경한다.
  3. 함수를 반환하는 시점에서 2에서 변경된 값을 원래의 매개변수에 할당한다.
var numbers: [Int] = [1, 2, 3]

func 참조되지않은전달인자(_ arr: [Int]) {
  var 복사된배열: [Int] = arr
  복사된배열[0] = 1
}

func 참조된전달인자(_ arr: inout [Int]) {
  arr[0] = 2
}

참조되지않은전달인자(numbers)
print(numbers[0]) // 1
// 단지 복사만 했기 때문에 numbers속 숫자들에 영향을 미치지 않았다.
// 따라서 0번째 숫자는 그대로 1이 유지된다

참조된전달인자(&numbers) // 참조를 표현하기 위해 &를 붙여준다.
print(numbers[0]) // 2
// 참조를 통해 numbers 배열의 값이 변화되었다.
// 기존에 0번째 숫자는 1이었지만 참조된전달인자함수를 사용하여 해당 배열의 0번째 숫자는 2가 되었다.

*입출력 매개변수는 매개변수 기본값을 가질 수 없다.

*또한 가변 매개변수로 사용될 수 없다.

*그리고 상수는 immutable 즉 변경될 수 없기에 입출력 매개변수의 전달인자로 사용될 수 없다.

클로저란? 클로저를 왜 사용하지?

클로저(Closure)란?

- 클로저는 사용자의 코드 안에서 전달되어 사용할 수 있는 로직을 가진 중괄호“{}”로 구분된 코드의 블럭이며, 일급 시민 입니다.

- 매개변수로 전달할 수 잇고, 변수/상수에 저장할 수 있는 것들을 일급시민이라고 한다

- 참조 타입이다.

- 함수는 클로저의 한 형태로, 이름이 있는 클로저이다.

출처: 오늘의 Swift 상식 (Closure). 클로저(Closure)란? | by 장국진 | Medium

클로저는 세 가지 형태가 있다.

  • 이름이 있으면서 어떤 값도 획득하지 않는 전역함수의 형태
  • 이름이 있으면서 다른 함수 내부의 값을 획득할 수 있는 중첩된 함수의 형태
  • 이름이 없고 주변 문맥에 따라 값을 획득할 수 있는 축약 문법으로 작성한 형태

내가 바라본 클로저는 뭔가 더 원시적이고 거친 인상을 받은 함수이다. 이름이 없어도 되고 있어도 되고 여러가지 형태로 존재할 수 있기에 이해하기 어려우면서도 매우 흥미로운 주제라고 생각하였다.

기본 클로저를 활용하면 메서드의 전달인자로 클로저를 직접 전달할 수 있다.

let reversed: [String] = names.sorted(by: {(first: String, second: String) -> Bool in return first > second})

sorted() 함수에 backwards()라는 함수의 이름만 지워진 뒤 기능이 통째로 sorted 함수의 인자로써 들어가 있다.

클로저 사용 예시:

func cook(method: () -> Void) {
    print("요리를 시작합니다")
    method()
    print("요리가 끝났습니다.")
}

cook(method: { print("튀깁니다.")})

cook(method: {print("부칩니다.")})

cook() 함수 인자값으로 method: () -> Void 라는 아무 값도 반환하지 않는 클로저가 들어가 있다. cook() 함수를 실행하면서 해당 함수의 parameter에 들어가있는 클로저의 코드 또한 실행할 수 있다. 아래 예시를 보면 조금 더 쉽게 이해할 수 있다.

func cook(음식: String, method: () -> Void) {
    print("\(음식) 요리를 시작합니다")
    method()
    print("\(음식) 요리가 끝났습니다.")
}

cook(음식: "감자튀김", method: { print("튀깁니다.")})

cook(음식: "김치전", method: {print("부칩니다.")})
감자튀김 요리를 시작합니다
튀깁니다.
감자튀김 요리가 끝났습니다.
김치전 요리를 시작합니다
부칩니다.
김치전 요리가 끝났습니다.
Program ended with exit code: 0

클로저는...

  • 인자이름을 생략해도 되고
  • 타입을 생략할 수도 있고
  • 반환타입을 생략할수도 있고
  • 연산자만 남길 수도 있고 (연산자 메소드)
  • 함수의 뒤에 포현할 수도 있다 (후행 클로저)
    • 이럴 경우 인자를 감싸는 소괄호 "( )" 또한 생략햘 수 있다.

다양한형태의 클로저는 아래 블로그에서 확인이 가능하다 ↓

클로저 | yagom’s Swift Basic

profile
james, the enthusiastic developer

0개의 댓글