일부 영어 억양에서는 "two for"를 빠르게 말하면 "two fer"처럼 들려요. Two-for-one은 하나를 사면 하나를 무료로 더 준다는 뜻을 나타내는 표현이에요. 그래서 "two-fer"라는 말은 흔히 하나를 사면 하나를 더 주는 혜택을 의미해요.
쿠키 두 개를 하나 가격으로 살 수 있는 휴일 특별 행사를 하는 빵집을 상상해 봐요 ("two-fer one!"). 이 혜택을 받아들이고, (아주 관대하게도) 남은 쿠키 하나를 줄에 서 있는 다른 사람에게 주기로 해요.
여분의 쿠키를 나눠 줄 때 무슨 말을 할지 정하는 것이 이번 과제예요.
그 사람의 이름을 안다면(예를 들어 이름이 Do-yun이라면) 이렇게 말해요:
One for Do-yun, one for me.
이름을 모른다면 대신 _you_라고 말해요.
One for you, one for me.
몇 가지 예를 볼까요?
| 이름 | 대화 |
|---|---|
| Alice | One for Alice, one for me. |
| Bohdan | One for Bohdan, one for me. |
| One for you, one for me. | |
| Zaphod | One for Zaphod, one for me. |
Odin은 기본 인자를 지원해요. 기본 인자는 서로 연관되어 있지만 조금씩 다른 API가 필요한 상황에서, 프로시저를 여러 가지 매개변수 조합으로 호출할 수 있게 해주는 유용한 기능이에요.
기본 인자가 없다면, API에 필요한 프로시저의 수가 폭발적으로 늘어날 수 있어요. Java처럼 기본 인자를 지원하지 않는 언어는 같은 효과를 내기 위해 메서드 오버로딩에 의존하거나(코드는 더 많아져요), 아주 많은 인자를 가진 프로시저를 제공해야 해요.
greeting 프로시저를 예로 들어볼까요? 여기서는 언어와, 이름을 대문자로 쓸지, 그리고 인사말 끝에 느낌표를 붙일지를 지정할 수 있으면 해요.
분석해 보니 가장 많은 사용자가 언어로 영어를 지정하고, 이름을 대문자로 쓰지 않으며, 끝에 느낌표를 원하지 않았어요. 두 번째로 많은 사용자는 인사말 끝에 느낌표를 붙였고요.
모든 인자를 가진 프로시저 하나를 만들 수도 있어요:
greeting :: proc(name: string, language: Language, do_uppercase: bool, add_exclamation: bool) {
...
}
그러면 모든 사용자가 모든 인자에 대한 문서를 읽고 항상 값을 채워야 해요.
기본 인자가 없다면, 다음과 같이 매개변수 조합이 다른 여러 프로시저를 정의할 수도 있어요:
greeting_common :: proc(name: string) {...}
greeting_with_exclamation :: proc(name: string) {...}
greeting_general :: proc(name: string, language: Language, do_uppercase: bool, add_exclamation: bool) {...}
// Odin supports overloading but it has to be explicitly defined
greeting :: proc {
greeting_common,
greeting_with_exclamation,
greeting_general,
}
Odin처럼 기본 인자를 지원하는 언어라면, 가장 적게 쓰이는 인자에 적절한 기본값을 지정하면 돼요. 호출하는 쪽에서는 기본 인자를 생략해서 프로시저가 지정된 기본값을 사용하게 하거나, 값을 덮어쓸 수 있어요.
greeting :: proc(name: string, language: Language = Language.English, do_uppercase : bool = false, add_exclamation: bool = false) {...}
// Note: because Odin supports type inference, we can simplify the interface.
greeting :: proc(name: string, language:= Language.English, do_uppercase := false, add_exclamation:= false) {...}
모든 인자를 기본값으로 두고 프로시저를 호출할 수도 있어요:
greeting("John Doe")
호출자에게 중요한 인자는 덮어쓸 수 있어요:
greeting("John Doe", Language.Spanish)
필요한 인자가 위 예시처럼 위치 순서대로라면 이름을 붙일 필요가 없어요. 하지만 일부 인자를 건너뛰어야 한다면, 건너뛴 첫 번째 인자 이후의 인자에는 이름을 붙여야 해요.
greeting("John Doe", add_exclamation=true)
이 연습 문제에서는 반환하는 문자열을 할당하도록 만들어진 프로시저를 구현해요. 문자열을 해제하는 것은 프로시저를 호출한 쪽의 책임이에요.
// The procedure will be called like that:
str := two_fer("Alice")
// ...
// and eventually the caller will delete the string
delete(str)
Odin 공식 문서의 default arguments와 Odin의 named arguments도 참고해 보면 좋아요.