Potato
์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์žก๋‹ˆ๋‹ค?๐Ÿฅ” ^___^ ๐Ÿ˜บ github ๋ฐ”๋กœ๊ฐ€๊ธฐ ๐Ÿ‘‰๐Ÿป

Swift/Swift Documents

[Swift] ๊ณต์‹ ๋ฌธ์„œ ์ •๋ฆฌ (6) - Functions (ํ•จ์ˆ˜)

๊ฐ์ž ๐Ÿฅ” 2022. 2. 15. 12:21
๋ฐ˜์‘ํ˜•

 

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์ž์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ์Šค์œ„ํ”„ํŠธ ๊ณต์‹๋ฌธ์„œ chapter 6 ํ•จ์ˆ˜ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•œ ๊ฒƒ์„ ์—…๋กœ๋“œ ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

Swift Documetns chapter.06 Functions 

 

Functions — The Swift Programming Language (Swift 5.6)

Functions Functions are self-contained chunks of code that perform a specific task. You give a function a name that identifies what it does, and this name is used to “call” the function to perform its task when needed. Swift’s unified function syntax

docs.swift.org


Functions (ํ•จ์ˆ˜)

ํ•จ์ˆ˜๋ž€ ํŠน์ • ์ž„๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋…๋ฆฝ๋œ ์ฝ”๋“œ ์กฐ๊ฐ์ด๋‹ค. ํ•จ์ˆ˜์—๋Š” ๋ญ˜ ํ•˜๋Š”์ง€ ์‹๋ณ„ํ•  ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๋ฉฐ, ํ•„์š”ํ•  ๋•Œ ์ด ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž„๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•  ํ•จ์ˆ˜๋ฅผ ‘ํ˜ธ์ถœ'ํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.


Defining and Calling Func (ํ•จ์ˆ˜ ์ •์˜ ๋ฐ ํ˜ธ์ถœ)

ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ, func๋ผ๋Š” ํ‚ค์›Œ๋“œ๋กœ ์ •์˜ํ•œ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜(parameters)์™€ ๋ฐ˜ํ™˜ํƒ€์ž…(return type)์ด๋ผ๊ณ  ํ•˜๋Š” ์ถœ๋ ฅ์œผ๋กœ ๋˜๋Œ๋ ค์ค„ ๊ฐ’ ํƒ€์ž…์„ ์˜ต์…˜์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

func greet(person: String) -> String {
	let greeting = "hello, " + persong 
	return greeting
}

ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

print(greet(person: "potato"))

Function Parameters and Return Values

์Šค์œ„ํ”„ํŠธ๋Š” ํ•จ์ˆ˜ ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜๊ฐ’์€ ๊ทน๋„๋กœ ์œ ์—ฐํ•˜๋‹ค. “์ด๋ฆ„์—†๋Š” ๋‹จ์ผ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„ ๋‹จ์ˆœํ•œ ๋ณด์กฐ์šฉ ํ•จ์ˆ˜" ๋ถ€ํ„ฐ “์„œ๋กœ๋‹ค๋ฅธ ๋งค๊ฐœ๋ณ€์ˆ˜ ์˜ต์…˜์„ ๊ฐ€์ง„ ๋ณต์žกํ•œ ํ•จ์ˆ˜"๊นŒ์ง€ ์–ด๋–ค ๊ฒƒ์ด๋“  ์ •์˜ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

Functions without Parameters (๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ํ•จ์ˆ˜)

ํ•จ์ˆ˜์—์„œ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค. ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ๋˜‘๊ฐ™์€ String๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ํ•จ์ˆ˜๋ฅผ ์•„๋ž˜์— ์ •์˜ํ–ˆ๋‹ค.

func sayHelloWorld() -> String {
	return "hello, world"
}

print(sayHelloWorld())

 

Functions with Multiple Parameters (๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ธ ํ•จ์ˆ˜)

ํ•จ์ˆ˜๋Š” ๊ด„ํ˜ธ ์•ˆ์— ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

func greet(person: String, alreadyGreeted: Bool) -> String {
	if alreadyGreeted {
		return greetAgain(person: person)
	} else {
		return greet(person:person)
	}
}

print(greet(person:"Tim", alreadyGreeted: true))
// "Hello again, Tim!" ์„ ์ธ์‡„ํ•˜๊ฒŒ ๋จ

 

Functions Without Return Values (๋ฐ˜ํ™˜ ๊ฐ’์ด ์—†๋Š” ํ•จ์ˆ˜)

ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํƒ€์ž…์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜ํ™˜ ํ™”์‚ดํ‘œ (->) ๋‚˜ ๋ฐ˜ํ™˜ํƒ€์ž…์„ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ { ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

func greet(person: String) {
	print("hello, \\(person)!")
}
greet(person: "jisoo")

ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ ํ•  ๋•Œ, ๋ฐ˜ํ™˜๊ฐ’์„ ๋ฌด์‹œํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

func printAndCount(string: String) -> Int {
  print(string)
  return string.count
}
func printWithoutCounting(string: String) {
  let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// "hello, world" ๋ฅผ ์ธ์‡„ํ•˜๊ณ  12 ๋ผ๋Š” ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ
printWithoutCounting(string: "hello, world")
// "hello, world" ๋ฅผ ์ธ์‡„ํ•˜์ง€๋งŒ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Œ

 

Functions with Multiple Return Values (๋ฐ˜ํ™˜๊ฐ’์ด ์—ฌ๋Ÿฌ ๊ฐœ์ธ ํ•จ์ˆ˜)

ํŠœํ”Œ ํƒ€์ž…์„ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ํ•˜๋‚˜์˜ ๋ณตํ•ฉ ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

func minMax(array: [Int]) -> (min: Int, max: Int) {
  var currentMin = array[0]
  var currentMax = array[0]
  for value in array[1..<array.count] {
    if value < currentMin {
      currentMin = value
    } else if value > currentMax {
      currentMax = value
    }
  }
  return (currentMin, currentMax)
}

ํŠœํ”Œ์˜ ๊ฐ’์€ ํ•œใ… ์ˆ˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์—์„œ ์ด๋ฆ„์„ ๋ถ™์˜€๊ธฐ ๋•Œ๋ฌธ์—, dot syntax๋กœ ์ ‘๊ทผํ•ด์„œ ์ตœ์†Œ ๋ฐ ์ตœ๋Œ€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \\(bounds.min) and max is \\(bounds.max)")
// "min is -6 and max is 109" ๋ฅผ ์ธ์‡„ํ•จ

 

Optional Tuple Return Types (์˜ต์…”๋„ ํŠœํ”Œ ๋ฐ˜ํ™˜ ํƒ€์ž…)

ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ํŠœํ”Œ ํƒ€์ž…์—์„œ ์ „์ฒด ํŠœํ”Œ์˜ ‘๊ฐ’์ด ์—†์„'์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์˜ต์…”๋„ ํŠœํ”Œ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ํŠœํ”Œ์ด nil์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

func minMax(array: [Int]) -> (min: Int, max: Int)? {
  if array.isEmpty { return nil }
  var currentMin = array[0]
  var currentMax = array[0]
  for value in array[1..<array.count] {
    if value < currentMin {
      currentMin = value
    } else if value > currentMax {
      currentMax = value
    }
  }
  return (currentMin, currentMax)
}

 

Functions With an Implicit Return (์•”์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜)

์ „์ฒด ํ•จ์ˆ˜ ๋ณธ๋ฌธ์ด ๋‹จ์ผ ํ‘œํ˜„์‹์ธ ๊ฒฝ์šฐ, ํ•จ์ˆ˜๊ฐ€ ํ•ด๋‹น ํ‘œํ˜„์‹์„ ์•”์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

func greeting(for person: String) -> String {
  "Hello, " + person + "!"
}
print(greeting(for: "Dave"))
// "Hello, Dave!" ๋ฅผ ์ธ์‡„ํ•จ

func anotherGreeting(for person: String) -> String {
  return "Hello, " + person + "!"
}
print(anotherGreeting(for: "Dave"))
// "Hello, Dave!" ๋ฅผ ์ธ์‡„ํ•จ

Function Argument Labels and Parameter Names

ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋Š” ๊ฐ๊ฐ์˜ ์ธ์ž ์ด๋ฆ„ํ‘œ์™€ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์ด ์žˆ๋‹ค. ์ธ์ž์ด๋ฆ„ํ‘œ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ๊ฐ๊ฐ์˜ ์ธ์ž ์•ž์— ์ž์‹ ์˜ ์ธ์ž ์ด๋ฆ„ํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ž‘์„ฑํ•œ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๊ตฌํ˜„์—์„œ ์‚ฌ์šฉํ•œ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ์ž์‹ ์˜ ์ธ์ž ์ด๋ฆ„ํ‘œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ์ ์€ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ์œ ์ผํ•œ ์ด๋ฆ„์„ ๊ฐ€์ ธ์•ผํ•œ๋‹ค.

func someFunction (firstParameterName: Int, secondParameterName: Int) {
  // ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ, firstParameterName ๊ณผ secondParameterName ์€
  // ์ฒซ ๋ฒˆ์งธ ๋ฐ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜์˜ ์ธ์ž ๊ฐ’์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
}
someFunction(firstParameterName: 1, secondParameterName: 2)

 

Specifying Argument Labels (์ธ์ž ์ด๋ฆ„ํ‘œ ์ง€์ •ํ•˜๊ธฐ)

์ธ์ž์ด๋ฆ„ํ‘œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„ ์•ž์— ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ž‘์„ฑํ•œ๋‹ค. ์ธ์ž์ด๋ฆ„ํ‘œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ดํ•ด๊ฐ€ ์‰ฝ๊ณ  ์˜๋„๊ฐ€ ๋ช…ํ™•ํ•œ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜ ๋ฌธ์žฅ๊ฐ™์€ ๊ด€๋ก€์— ๋”ฐ๋ผ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถฃ ํ•  ์ˆ˜์žˆ๋‹ค.

func someFunction(argumentLabel parameterName: Int) {
	// ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ parameterName์€ ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ธ์ž ๊ฐ’์„ ์ฐธ์กฐํ•œ๋‹ค.
}

์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด์ž.

func greet(person: String, from hometown: String) -> String {
  return "Hello \\(person)! Glad you could visit from \\(hometown)."
}
print (greet(person: "Bill", from: "Cupertino"))
// "Hello Bill! Glad you could visit from Cupertino." ๋ฅผ ์ธ์‡„ํ•จ

 

Omitting Argument Labels (์ธ์ž ์ด๋ฆ„ํ‘œ ์ƒ๋žตํ•˜๊ธฐ)

๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ธ์ž ์ด๋ฆ„ํ‘œ๋ฅผ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋ช…์‹œ์ ์ธ ์ธ์ž ์ด๋ฆ„ํ‘œ ๋Œ€์‹  ๋ฐ‘์ค„(_)์„ ์ž‘์„ฑํ•œ๋‹ค.

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
  // ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ, firstParameterName ๊ณผ secondParameterName ์€
  // ์ฒซ ๋ฒˆ์งธ ๋ฐ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜์˜ ์ธ์ž ๊ฐ’์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
}
someFunction (1, secondParameterName: 2)

 

Default Parameter Values (๊ธฐ๋ณธ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’)

ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž… ๋’ค์— ๊ฐ’์„ ํ• ๋‹นํ•จ์œผ๋กœ์จ ์–ด๋–ค ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋“  ๊ธฐ๋ณธ๊ฐ’์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์ •์˜ํ•˜๋ฉด, ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

func someFunction (parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
  // ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋ฅผ ์ƒ๋žตํ•˜๋ฉด,
  // parameterWithDefault ๊ฐ’์ด ํ•จ์ˆ˜ ๋ณธ๋ฌธ ์•ˆ์—์„œ 12 ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
}
someFunction (parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault ๋Š” 6 ์ž„
someFunction (parameterWithoutDefault: 4) // parameterWithDefault ๋Š” 12 ์ž„

 

Variadic Parameters (๊ฐ€๋ณ€ ๋งค๊ฐœ๋ณ€์ˆ˜)

๊ฐ€๋ณ€๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํŠน์ • ํƒ€์ž…์˜ ๊ฐ’์„ 0๊ฐœ ์ด์ƒ ๋ฐ›์•„๋“ค์ธ๋‹ค. ๊ฐ€๋ณ€๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœํ•  ๋•Œ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋‹ค๊ฐ€ ๋‹ค์–‘ํ•œ ๊ฐœ์ˆ˜์˜ ์ž…๋ ฅ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ์„ ์ง€์ •ํ•˜๊ณ ์ž ์‚ฌ์šฉํ•œ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์ด๋ฆ„ ๋’ค์— ๋งˆ์นจํ‘œ ๋ฌธ์ž ์„ธ๊ฐœ (...) ๋ฅผ ์ง‘์–ด๋„ฃ์–ด์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

func arithmeticMean(_ numbers: Double...) -> Double {
  var total: Double = 0
  for number in numbers {
    total += number
  }
  return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// ์ด ๋‹ค์„ฏ ์ˆ˜๋“ค์˜ ์‚ฐ์ˆ  ํ‰๊ท ์ธ, 3.0 ์„ ๋ฐ˜ํ™˜ํ•จ
arithmeticMean(3, 8.25, 18.75)
// ์ด ์„ธ ์ˆ˜๋“ค์˜ ์‚ฐ์ˆ  ํ‰๊ท ์ธ, 10.0 ์„ ๋ฐ˜ํ™˜ํ•จ

 

In-Out Parameters (์ž…-์ถœ๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜)

๊ธฐ๋ณธ์ ์œผ๋กœ ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ƒ์ˆ˜์ด๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜ ๋ณธ๋ฌธ์•ˆ์—์„œ ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ฐ”๊พธ๋ ค๊ณ  ํ•˜๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ์‹ค์ˆ˜๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋‹ค๋Š” ๋œป์„ ์˜๋ฏธํ•œ๋‹ค. ํ•จ์ˆ˜์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ๊ณ , ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ๋๋‚œ ํ›„์—๋„ ์ด๋ ‡๊ฒŒ ๋ฐ”๊พผ๊ฒƒ์„ ์ง€์†ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…์ถœ๋ ฅ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋Œ€์‹  ์ •์˜ํ•  ์ˆ˜์žˆ๋‹ค.

๋งค๊ฐœ ๋ณ€์ˆ˜ ํƒ€์ž… ๋ฐ”๋กœ ์•ž์— inout ํ‚ค์›Œ๋“œ๋ฅผ ๋‘ฌ์„œ ์ž…-์ถœ๋ ฅ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. ์ž…-์ถœ๋ ฅ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ์›๋ณธ ๊ฐ’์„ ๋Œ€์ฒดํ•˜๋ ค๊ณ , ํ•จ์ˆ˜ ์•ˆ์œผ๋กœ *์ž…๋ ฅ (in)*ํ•˜์—ฌ, ํ•จ์ˆ˜๊ฐ€ ์ˆ˜์ •ํ•œ ๋‹ค์Œ, ํ•จ์ˆ˜ ๋ฐ–์œผ๋กœ ์ถœ๋ ฅ (out) ๋˜๋Š” ๊ฐ’์„ ๊ฐ€์ง„๋‹ค.

๋ณ€์ˆ˜๋งŒ ์ž…์ถœ๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ธ์ž๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ƒ์ˆ˜๋‚˜ ๊ธ€์ž๊ฐ’(literal)์€ ์ธ์ž๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์—†๋Š”๋ฐ, ์ƒ์ˆ˜์™€ ๊ธ€์ž๊ฐ’์€ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ž…์ถœ๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌํ•  ๋•Œ๋Š”, ํ•จ์ˆ˜๊ฐ€ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Œ์„ ์ง€์‹œํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€์ˆ˜ ์ด๋ฆ„ ๋ฐ”๋กœ ์•ž์— & ๋ฅผ ๋ถ™์ธ๋‹ค.

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
  let temporaryA = a
  a = b
  b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \\(someInt), and anotherInt is now \\(anotherInt)")
// "someInt is now 107, and anotherInt is now 3" ๋ฅผ ์ธ์‡„ํ•จ

 

Function Types

๋ชจ๋“  ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…๊ณผ ๋ฐ˜ํ™˜ํƒ€์ž…์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋Š” ํŠน์ •ํ•œ ํ•จ์ˆ˜ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค. ์˜ˆ์‹œ๋ฅผ ๋ณด์ž. ์•„๋ž˜ ์˜ˆ์ œ๋Š” ๋‹จ์ˆœํ•œ ์ˆ˜ํ•™ ํ•จ์ˆ˜ ๋‘๊ฐœ๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๊ฐ๊ฐ ๋‘๊ฐœ์˜ int๊ฐ’์„ ์ทจํ•˜๋ฉฐ ์—ฐ์‚ฐ๊ฒฐ๊ณผ๋„ Int๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

func addTwoInts(_ a: Int, _ b: Int) -> Int {
  return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
  return a * b
}

๋‹ค์Œ์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋Š” ํ•จ์ˆ˜๋ฅผ ์œ„ํ•œ ๋˜ ๋‹ค๋ฅธ ์˜ˆ์ œ์ด๋‹ค. ์ด ํ•จ์ˆ˜๋Š” () -> Void๋˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๊ณ  Void ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

func printHelloWorld() {
	print("hello, world")
}|

 

Using Function Types (ํ•จ์ˆ˜ ํƒ€์ž… ์‚ฌ์šฉํ•˜๊ธฐ)

ํ•จ์ˆ˜ ํƒ€์ž…์€ ์Šค์œ„ํ”„ํŠธ์˜ ๋‹ค๋ฅธ ์–ด๋–ค ํƒ€์ž…์ธ ๊ฒƒ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ์ƒ์ˆ˜๋‚˜ ๋ณ€์ˆ˜๋ฅผ ํ•จ์ˆ˜ ํƒ€์ž…์œผ๋กœ ์ •์˜ํ•˜๊ณ  ํ•ด๋‹น ๋ณ€์ˆ˜์— ์ ์ ˆํ•œ ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

“๋‘ Int๊ฐ’์„ ์ทจํ•˜๊ณ , Int๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ํƒ€์ž…์ธ, mathFunction ์ด๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ด ์„ธ๋ณ€์ˆ˜๊ฐ€ addTwoInts๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.”

var mathFunction: (Int, Int) -> Int = addTwoInts

addTwoInts(_:_:) ํ•จ์ˆ˜๋Š” mathFunction ๋ณ€์ˆ˜์™€ ๋˜‘๊ฐ™์€ ํƒ€์ž…์ด๋ฏ€๋กœ, ์Šค์œ„ํ”„ํŠธ ํƒ€์ž…-๊ฒ€์‚ฌ๊ธฐ๊ฐ€ ์ด ํ• ๋‹น์„ ํ—ˆ์šฉํ•œ๋‹ค.

์ด์ œ ํ• ๋‹นํ•œ ํ•จ์ˆ˜๋ฅผ mathFunction ์ด๋ž€ ์ด๋ฆ„์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค :

print("Result: \\(mathFunction(2, 3))")
// "Result: 5" ๋ฅผ ์ธ์‡„ํ•จ

ํƒ€์ž…์ด ๋™์ผํ•˜๊ฒŒ ์ผ์น˜ํ•˜๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋Š”, ํ•จ์ˆ˜ ์•„๋‹Œ ํƒ€์ž…๊ณผ ๋˜‘๊ฐ™์ด, ๋™์ผํ•œ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค.

mathFunction = multiplyTwoInts
print("Result: \\(mathFunction(2, 3))")
// "Result: 6" ์„ ์ธ์‡„ํ•จ

๋‹ค๋ฅธ ์–ด๋–ค ํƒ€์ž…์ฒ˜๋Ÿผ, ์ƒ์ˆ˜๋‚˜ ๋ณ€์ˆ˜์— ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•  ๋•Œ ์Šค์œ„ํ”„ํŠธ๊ฐ€ ํ•จ์ˆ˜ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๊ฒŒ ๋‚ด๋ฒ„๋ ค ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.

let anotherMathFunction = addTwoInts
// anotherMathFunction ์€ (Int, Int) -> Int ํƒ€์ž…์ด๋ผ๊ณ  ์ถ”๋ก ํ•จ

 

Function Types as Parameter Types (๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์œผ๋กœ์จ์˜ ํ•จ์ˆ˜ ํƒ€์ž…)

(Int, Int) -> Int ์™€ ๊ฐ™์€ ํ•จ์ˆ˜ ํƒ€์ž…์€ ๋˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ํ•จ์ˆ˜ ๊ตฌํ˜„ ์ผ๋ถ€๋ฅผ ํ•จ์ˆ˜ ํ˜ธ์ถœํ•œ ์ชฝ์ด ์ œ๊ณตํ•˜๊ฒŒ ๋‚ด๋ฒ„๋ ค ๋‘๊ฒŒ ํ•œ๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ๋Š” ์œ„์— ์žˆ๋Š” ์ˆ˜ํ•™ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ์ธ์‡„ํ•œ๋‹ค.

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
  print("Result: \\(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// "Result: 8" ๋ฅผ ์ธ์‡„ํ•จ

 

Function Types as Return Types (๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ์จ์˜ ํ•จ์ˆ˜ ํƒ€์ž…)

ํ•จ์ˆ˜ํƒ€์ž…์„ ๋˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ๋ฐ˜ํ™˜ํ•  ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํ™”์‚ดํ‘œ (->) ๋ฐ”๋กœ ๋’ค์— ์™„์ „ํ•œ ํ•จ์ˆ˜ ํƒ€์ž…์„ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

func stepForward(_ input: Int) -> Int {
  return input + 1
}
func stepBackward(_ input: Int) -> Int {
  return input - 1
}

๋‹ค์Œ์€ ๋ฐ˜ํ™˜ํƒ€์ž…์ด (Int) -> Int ์ธ ํ•จ์ˆ˜์ด๋‹ค. ์ด ํ•จ์ˆ˜๋Š” backward๋ผ๋Š” ๋ถˆ๋ฆฌ์–ธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ธฐ์ดˆ๋กœ, stepForward() ํ•จ์ˆ˜๋‚˜ stepBackward() ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
  return backward ? stepBackward : stepForward
}

์ด์ œ chooseStepFunction(backwardโ—กฬˆ ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด์ชฝ ๋˜๋Š” ์ €์ชฝ ๋ฐฉํ–ฅ์œผ๋กœ ๊ฑธ์Œ์„ ์˜ฎ๊ธฐ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero ๋Š” ์ด์ œ stepBackward() ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•จ

print("Counting to zero:")
// ์˜๊นŒ์ง€ ์…ˆ:
while currentValue != 0 {
  print("\\(currentValue)... ")
  currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// ์˜!

 

Nested Functions (์ค‘์ฒฉํ•จ์ˆ˜)

์ด ์žฅ์—์„œ ์ง€๊ธˆ๊นŒ์ง€ ๋งˆ์ฃผ์นœ ๋ชจ๋“  ํ•จ์ˆ˜๋Š” ์ „์—ญ ๋ฒ”์œ„์—์„œ ์ •์˜ํ•œ ์ „์—ญํ•จ์ˆ˜ ์˜ˆ์ œ์˜€๋‹ค. ๋‹ค๋ฅธ ํ•จ์ˆ˜ ๋ณธ๋ฌธ ์•ˆ์—์„œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ ์ด๋ฅผ ์ค‘์ฒฉํ•จ์ˆ˜๋ผ๊ณ ํ•œ๋‹ค.

์ค‘์ฒฉํ•จ์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์™ธ๋ถ€ ์„ธ๊ณ„๋กœ๋ถ€ํ„ฐ ์ˆจ๊ฒจ์ ธ ์žˆ์ง€๋งŒ, ์ž์‹ ์„ ๋‘˜๋Ÿฌ์‹ผ ํ•จ์ˆ˜์—์„  ์—ฌ์ „ํžˆ ํ˜ธ์ถœํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ค‘์ฒฉํ•จ์ˆ˜๋ฅผ ๋‘˜๋Ÿฌ์‹ผ ํ•จ์ˆ˜๋Š” ๋˜ ๋‹ค๋ฅธ ์˜์—ญ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž์‹ ์˜ ์ค‘์ฒฉํ•จ์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ค‘์ฒฉํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์œ„์˜ chooseStepFunction(backward: )์˜ˆ์ œ๋ฅผ ์žฌ์ž‘์„ฑ ํ•ด๋ณด์ž.

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
  func stepForward(input: Int) -> Int { return input + 1 }
  func stepBackward(input: Int) -> Int { return input - 1 }
  return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero ๋Š” ์ด์ œ ์ค‘์ฒฉ ํ•จ์ˆ˜์ธ stepForward() ๋ฅผ ์ฐธ์กฐํ•จ
while currentValue != 0 {
  print("\(currentValue)... ")
  currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// ์˜!

 

๋ฐ˜์‘ํ˜•