π Chapter 2: μ€μΉΌλΌλ‘ ν¨μν νλ‘κ·Έλλ° μμνκΈ°
π μ€μΉΌλΌ μΈμ΄μ μκ°: μμ νλβ
μ΄λ² μ μ λͺ©νλ μ€μΉΌλΌ μΈμ΄μ κ·Έ ꡬ문(λ¬Έλ²)μ μκ°νλ κ²μΌ λΏμ΄λ€.
// μ΄κ²μ μ£Όμ!
/* μ΄κ²λ μ£Όμ */
/** λ¬Έμν μ£Όμ */
object MyModule { // λ¨μΌ κ°μ²΄μ μ μΈ ν΄λμ€μ ν΄λμ€μ μ μΌν μΈμ€ν΄μ€λ₯Ό λμμ μ μΈνλ€.
def abs(n: Int): Int =
// λ§μ½ nμ΄ 0λ³΄λ€ μμΌλ©΄ nμ λΆμ (λΆνΈκ° λ°λ)μ λλ €μ€λ€.
if (n < 0) -n
else n
// μ μ©(private) λ©μλλ μ€μ§ MyModuleμ λ€λ₯Έ λ©€λ²λ€λ§ νΈμΆν μ μλ€.
private def formatAbs(x: Int) = {
// μμΉλ₯Ό μν μ리ν %dκ° λ κ° μλ λ¬Έμμ΄.
val msg = "The absolute value of %d is %d"
// λ¬Έμμ΄ λ %d μ리νλ₯Ό κ°κ° xμ abs(x)λ‘ μΉννλ€.
msg.format(x, abs(x))
}
// Unitμ Javaλ C κ°μ μΈμ΄μ voidμ κ°μ λͺ©μ μΌλ‘ μ°μΈλ€.
def main(args: Array[String]): Unit =
println(formatAbs(-42))
}
μ€μΉΌλΌ μ½λλ λ°λμ object
λ‘ μ μΈλλ κ°μ²΄λ class
λ‘ μ μΈλλ ν΄λμ€ μμ λ€μ΄κ°μΌ νλλ°, μ¬κΈ°μλ λ μ€ λ κ°λ¨ν object
λ₯Ό μ¬μ©νλ€.
abs
λ©μλλ μ μ νλλ₯Ό λ°μμ κ·Έ μ λκ°μ λλ €μ£Όλ μμ ν¨μμ΄λ€.
def abs(n: Int): Int =
if (n < 0) -n
else n
λ©μλ μ체μ λ³Έλ¬Έμ λ±νΈ(=
) λ€μμ μ¨λ€. νν, λ©μλ μ μΈμμ λ±νΈ μΌμͺ½μ μλ κ²μ μ’λ³ λλ μλͺ
μ΄λΌκ³ λΆλ₯΄κ³ λ±νΈ μ€λ₯Έμͺ½μ μ½λλ₯Ό μ°λ³ λλ μ μλΌκ³ λΆλ₯Έλ€. λ©μλμ μ μμ λͺ
μμ μΈ return
ν€μλκ° μλ€. κ·Έλ₯ μ°λ³μ νκ° κ²°κ³Όκ° κ³§ λ©μλμ λ°νκ°μ΄λ€.
formatAbs
λ©μλ μμ μμ ν¨μμ΄λ€.
private def formatAbs(x: Int) = {
val msg = "The absolute value of %d is %d"
msg.format(x, abs(x))
}
μ΄ λ©μλλ private
λ‘ μ μΈλμ΄ μλ€. μ΄λ μ΄ λ©μλλ₯Ό MyModule
κ°μ²΄μ μ€λΆμμλ νΈμΆν μ μμμ λ»νλ€. μ΄ ν¨μλ Int
νλλ₯Ό λ°κ³ String
νλλ₯Ό λλ €μ£Όλλ€, λ°ν νμμ΄ μ μΈλμ΄ μμ§ μλ€. μ€μΉΌλΌκ° λ©μλμ λ°ν νμμ μΆλ‘ ν μ μλ κ²½μ°κ° λ§μΌλ©°, κ·Έλ΄ λμλ λ°ν νμμ μλ΅ν μ μλ€. κ·Έλ¬λ λ€λ₯Έ μ¬λμ΄ μ¬μ©ν λ©μλμμλ λ°ν νμμ λͺ
μμ μΌλ‘ μ§μ ν΄ μ£Όλ κ²μ΄ λμ²΄λ‘ μ’μ μ€νμΌλ‘ κ°μ£Όλλ€.
λ§μ§λ§μΌλ‘, main
λ©μλλ μμ ν¨μμ ν΅μ¬λΆλ₯Ό νΈμΆνκ³ κ·Έ κ²°κ³Όλ₯Ό μ½μμ μΆλ ₯νλ μΈλΆ κ³μΈ΅(shell)μ΄λ€. λΆμ ν¨κ³Όκ° λ°μν¨μ κ°μ‘°νκΈ° μν΄, μ΄λ° λ©μλλ₯Ό μ μ°¨(procedure) λλ λΆμ ν¨μ(impure function)λΌκ³ λΆλ₯΄κΈ°λ νλ€.
def main(args: Array[String]): Unit =
println(formatAbs(-42))
main
μ΄λΌλ μ΄λ¦μ νΉλ³νλ€. νλ‘κ·Έλ¨μ μ€νν λ μ€μΉΌλΌκ° νΉμ ν μλͺ
μ κ°μ§ main
μ΄λΌλ μ΄λ¦μ λ©μλλ₯Ό μ°ΎκΈ° λλ¬Έμ΄λ€. μ’ λ ꡬ체μ μΌλ‘, main
λ©μλλ λ°λμ String
λ€μ Array
λ₯Ό μΈμλ‘ λ°μμΌ νλ©°, λ°ν νμμ λ°λμ Unit
μ΄μ΄μΌ νλ€.
μ€μΉΌλΌμμ λͺ¨λ λ©μλλ νμ£Όνμ§ μλ ν μ΄λ€ κ°μ λλ €μ€λ€. κ·Έλ°λ° main
μ λ±ν μλ―Έ μλ κ°μ λλ €μ£Όμ§ μλλ€. νΉλ³ν νμμΈ Unit
μ κ·Έλ° γ΄λ©μλμ λ°ν νμμΌλ‘ μ°μΈλ€. μΌλ°μ μΌλ‘, λ°ν νμμ΄ Unit
μ΄λΌλ κ²μ κ·Έ λ©μλμ λΆμ ν¨κ³Όκ° μ‘΄μ¬ν¨μ μμνλ€.
π νλ‘κ·Έλ¨μ μ€νβ
보ν΅μ μ€μΉΌλΌμ© λΉλ λκ΅¬μΈ sbtλ₯Ό μ΄μ©νκ±°λ IntelliJλ Eclipse κ°μ IDEλ₯Ό μ΄μ©ν΄ μ€μΉΌλΌ μ½λλ₯Ό ꡬμΆνκ³ μ€ννλ€.
μ΄ μ€μΉΌλΌ νλ‘κ·Έλ¨(MyModule)μ μ€ννλ κ°μ₯ κ°λ¨ν λ°©λ²μ λͺ
λ Ήμ€μμ μ§μ μ€μΉΌλΌ μ»΄νμΌλ¬λ λΆλ¬μ€λ κ²μ΄λ€. μ°μ μμ νλ‘κ·Έλ¨μ MyModule.scala
μ κ°μ μ΄λ¦μ νμΌλ‘ μ μ₯νκ³ , λ€μκ³Ό κ°μ΄ scalac
μ»΄νμΌλ¬λ₯Ό μ΄μ©ν΄μ κ·Έ νλ‘κ·Έλ¨μ Java λ°μ΄νΈμ½λλ‘ μ»΄νμΌ νλ€. μ΄λ κ² νλ©΄ νμ₯μκ° .class
μΈ νμΌλ€μ΄ μκΈ΄λ€. μ΄ νμΌλ€μλ Java κ°μ κΈ°κ²(JVM)λ‘ μ€νν μ μλ μ»΄νμΌλ μ½λκ° λ€μ΄ μλ€. κ·Έ μ½λλ₯Ό λͺ
λ Ήμ€ λꡬ scalaλ₯Ό μ΄μ©ν΄μ μ§μ μ€νν μ μλ€.
λ λ€λ₯Έ λ°©λ²μΌλ‘, μ€μΉΌλΌ ν΄μκΈ°μ λνμ λͺ¨λ, μ¦ REPL(read-evaluate-print loop)μ μ΄μ©ν΄λ λλ€. REPLμ λ μκ° μ€μΉΌλΌ νλ‘κ·Έλλ¨Έλ‘μ μμ£Ό μ¬μ©νκ² λ λꡬμ΄λ―λ‘, REPLμ μ¬λ¬ κ°μ§ κΈ°λ₯μ μ΅μνμ§λ©΄ λμμ΄ λ κ²μ΄λ€.
π λͺ¨λ, κ°μ²΄, μ΄λ¦κ³΅κ°β
MyModule
μ abs
κ° μν μ΄λ¦κ³΅κ°(namespace)μ΄λ€. λͺ κ°μ§ μΈλΆμ μΈ μ¬νμ μλ΅ν λ, μ€μΉΌλΌμ λͺ¨λ κ°μ μμ κ°μ²΄(object)μ΄λ©°, κ°κ°μ κ°μ²΄λ 0κ° λλ νλ μ΄μμ λ©€λ²(member)λ₯Ό κ°μ§ μ μλ€. μμ μ λ©€λ²λ€μκ² μ΄λ¦κ³΅κ°μ μ 곡νλ κ²μ΄ μ£Όλ λͺ©μ μΈ κ°μ²΄λ₯Ό νν λͺ¨λ(module)μ΄λΌκ³ λΆλ₯Έλ€. λ©€λ²λ def
ν€μλλ‘ μ μΈλ λ©μλμΌ μλ μκ³ val
μ΄λ object
λ‘ μ μΈλ λ λ€λ₯Έ κ°μ²΄μΌ μλ μλ€.
μ€μΉΌλΌμλ μ°μ°μλΌλ νΉλ³ν κ°λ
μ΄ μ‘΄μ¬νμ§ μλλ€. μ€μΉΌλΌμμ +
λ κ·Έλ₯ μ ν¨ν λ©μλ μ΄λ¦μΌ λΏμ΄λ©°, μΈμ νλμΈ λ©μλλ κ·Έ μ΄λ€ κ²μ΄λΌλ λ§μΉ¨νμ κ΄νΈλ₯Ό μλ΅ν μ€μ νκΈ°λ²μΌλ‘ νΈμΆν μ μλ€. μλ₯Ό λ€μ΄ MyModule.abs(42)
λμ MyModule abs 42
λΌκ³ ν΄λ κ°μ κ²°κ³Όκ° λλ€. κ·Έλ¬λ©΄ κ°μ²΄ μ΄λ¦μ μλ΅ν μ μλ€.
κ·Έλ¦¬κ³ λ€μκ³Ό κ°μ΄ λ°μ€ νκΈ°λ²μ μ΄μ©νλ©΄ κ°μ²΄μ λͺ¨λ λΉμ μ© λ©€λ²λ₯Ό λ²μμ λμ ν μ μλ€.
import MyModule._
π κ³ μ°¨ ν¨μ: ν¨μλ₯Ό ν¨μμ μ λ¬β
μ μλ λ¬Έμμ΄, λͺ©λ‘ κ°μ λ€λ₯Έ νμμ κ°μ²λΌ ν¨μλ λ³μμ λ°°μ νκ±°λ μλ£κ΅¬μ‘°μ μ μ₯νκ±°λ μΈμλ‘μ ν¨μμ λκ²¨μ€ μ μλ€.
μμν ν¨μμ νλ‘κ·Έλ¨μ μμ±ν λλ λ€λ₯Έ ν¨μλ₯Ό μΈμλ‘ λ°λ ν¨μλ₯Ό μμ±νλ κ²μ΄ μ μ©ν κ²½μ°κ° λ§λ€. κ·Έλ° ν¨μλ₯Ό κ³ μ°¨ ν¨μ(higher-order function, HOF)λΌκ³ λΆλ₯Έλ€.
π μ κΉ κ³κ°μ§: ν¨μμ μΌλ‘ 루ν μμ±νκΈ°β
κ³μΉμ ꡬνλ factorial ν¨μλΆν° μμ±ν΄λ³΄μ.
def factorial(n: Int): Int = {
def go(n: Int, acc: Int): Int =
if (n <= 0) acc
else go(n - 1, n*acc)
go(n, 1)
}
루νλ₯Ό ν¨μμ μΌλ‘ μμ±νλ λ°©λ²μ λ°λ‘ μ¬κ· ν¨μλ₯Ό μ΄μ©νλ κ²μ΄λ€. μ€μΉΌλΌλ μ΄λ° μ’
λ₯μ μκΈ° μ¬κ·(self-recursion)λ₯Ό κ²μΆν΄μ, μ¬κ· νΈμΆμ΄ 꼬리 μμΉ(tail position)μμ μΌμ΄λλ€λ©΄ while
루νλ₯Ό μ¬μ©νμ λμ κ°μ μ’
λ£μ λ°μ΄νΈμ½λλ‘ μ»΄νμΌνλ€. ν΅μ¬μ, μ¬κ· νΈμΆμ λ°ν μ΄μ°μ νΉλ³ν λ νλ μΌμ΄ μλ€λ©΄ μ΄λ° μ’
λ₯μ μ΅μ ν(꼬리 νΈμΆ μ κ±°λΌκ³ λΆλ₯Έλ€)κ° μ μ©λλ€λ κ²μ΄λ€.
μ€μΉΌλΌμ 꼬리 νΈμΆ
νΈμΆμκ° μ¬κ· νΈμΆμ κ²°κ³Όλ₯Ό κ·Έλλ λλ €μ£Όλ κ² μΈμλ μ무 μΌλ νμ§ μμ λ, κ·Έλ° νΈμΆμ 꼬리 μμΉμμμ νΈμΆ, μ€μ¬μ 꼬리 νΈμΆμ΄λΌκ³ λ§νλ€. λ§μ½μ1 + go(n - 1, n * acc)
μ¬κ· νΈμΆ μΈ κ²½μ° λ μ΄μ 꼬리 νΈμΆμ΄ μλλ€.go
μκ²°κ³Όμ λν΄ λ€λ₯Έ μ΄λ€ μΌ(1μ λνλ κ²)μ μνν΄μΌ νκΈ° λλ¬Έμ΄λ€.
ν ν¨μκ° μννλ λͺ¨λ μ¬κ· νΈμΆμ΄ 꼬리 νΈμΆμ΄λ©΄ μ€μΉΌλΌλ ν΄λΉ μ¬κ·λ₯Ό 맀 λ°λ³΅λ§λ€ νΈμΆ μ€νμ μλΉνμ§ μλ λ°λ³΅ 루ν ννλ‘ μ»΄νμΌ νλ€. κΈ°λ³Έ μ€μ μμ μ€μΉΌλΌ μ»΄νμΌλ¬λ 꼬리 νΈμΆ μ κ±°μ μ±κ³΅ μ¬λΆλ₯Ό μλ €μ£Όμ§ μμ§λ§, μμ μ΄ μμ±ν μ¬κ· ν¨μμ λν΄ κΌ¬λ¦¬ νΈμΆμ΄ μ€μ λ‘ μ κ±°λμλμ§ νμΈν νμκ° μλ€λ©΄ tailrec μ£Όν΄(http://mng.bz/bWT5)λ₯Ό μ¬κ· ν¨μμ μ μ©νλ©΄ λλ€.
π 첫 λ²μ§Έ κ³ μ°¨ ν¨μ μμ±β
factorial
ν¨μλ₯Ό λ§λ€μμΌλ, μ΄μ μ΄ ν¨μλ₯Ό μ¬μ©νλλ‘ μμ νλ‘κ·Έλ¨μ μμ ν΄ λ³΄μ.
object MyModule {
def abs(n: Int): Int =
if (n < 0) -n
else n
def factorial(n: Int): Int = {
def go(n: Int, acc: Int): Int =
if (n <= 0) acc
else go(n - 1, n*acc)
go(n, 1)
}
private def formatAbs(x: Int) = {
val msg = "The absolute value of %d is %d"
msg.format(x, abs(x))
}
private def formatFactorial(n: Int) = {
val msg = "The factorial of %d is $d."
msg.format(n, factorial(n))
}
def main(args: Array[String]): Unit = {
println(formatAbs(-42))
println(formatFactorial(7))
}
}
λ ν¨μ formatAbs
μ formatFactorial
μ κ±°μ λμΌνλ€ μ΄ λμ λ€μμ²λΌ μΈμλ€μ μ μ©ν ν¨μλ₯Ό μΈμλ‘ λ°λ νλμ ν¨μ formatResult
λ‘ μΌλ°ννλ©΄ μ΄λ¨κΉ?
def formatResult(name: String, n: Int, f: Int => Int) = {
val msg = "The %s of %d is %d."
msg.format(name, n, f(n))
}
μ΄ formatResult
ν¨μλ f
λΌλ λ€λ₯Έ ν¨μλ₯Ό λ°λ νλμ κ³ μ°¨ ν¨μλ€. λ€λ₯Έ μΈμλ€μ²λΌ f
μλ νμμ μ§μ νλ€. μ΄ μΈμμ νμμ Int => Int
μΈλ°, f
κ° μ μ μΈμ νλλ₯Ό λ°κ³ μ μ νλλ₯Ό λλ €μ£ΌλΌλ λ»μ΄λ€.
formatResult("absolute value", -42, abs)
formatResult("factorial", 7, factorial)
π λ€νμ ν¨μ: νμμ λν μΆμβ
μ§κΈκΉμ§ μ μν ν¨μλ€μ λͺ¨λ λ¨νμ ν¨μ(monomorphic function), μ¦ ν νμμ μλ£μλ§ μμ©νλ ν¨μμλ€. μλ₯Ό λ€μ΄ abs
μ factorial
μ Int
νμμ μΈμμλ§ νΉνλμ΄ μμΌλ©°, κ³ μ°¨ ν¨μ formatResult
μμ Int
νμμ μΈμλ₯Ό λ°λ ν¨μμλ§ μμ©νλλ‘ κ³ μ λμ΄ μλ€. κ·Έλ°λ° μμμ νμμ λν΄ μλνλ μ½λλ₯Ό μμ±ν΄μΌ νλ κ²½μ°λ λ§μ΄ μκΈ΄λ€. κ·Έλ° ν¨μλ₯Ό λ€νμ ν¨μ(polymorphic function)λΌκ³ λΆλ₯Έλ€.
π λ€νμ ν¨μμ μβ
κ΅¬μ‘°κ° λΉμ·ν λ¨νμ ν¨μ μ¬λ¬ κ°λ₯Ό κ΄μ°°νλ€ λ³΄λ©΄ λ€νμ ν¨μλ₯Ό λ°κ²¬νλ κ²½ μ°κ° λ§λ€.
// λ°°μ΄μμ λ¬Έμμ΄μ μ°Ύλ λ¨νμ ν¨μ
def findFirst(ss: Array[String], key: String): Int = {
@annotation.tailrec
def loop(n: Int): Int =
if (n >= ss.length) -1
else if (ss(n) == key) n
else loop(n + 1)
}
λ€μμ μμμ νμ Aμ λν΄ νΉμ A κ°μ μ κ²νλ ν¨μλ₯Ό μΈμλ‘ λ°μμΌλ‘μ¨ findFirst
λ₯Ό μ’ λ μΌλ°νν κ²μ΄λ€.
def findFirst[A](as: Array[A], p: A => Boolean): Int = {
@annotation.tailrec
def loop(n: Int): Int =
if (n >= as.length) - 1
// ν¨μ pκ° νμ¬ μμμ λΆν©νλ€λ©΄ μνλ μμλ₯Ό μ°Ύλ κ²μ΄λ―λ‘ λ°°μ΄ μμμ ν΄λΉ μμΈμ λλ €μ€λ€.
else if (p(as(n))) n
else loop(n + 1)
loop(0)
}
μ΄λ μΌλ°μ ν¨μ(generic function)λΌκ³ λ λΆλ₯΄λ λ€νμ ν¨μμ ν μμ΄λ€. μ΄ ν¨μλ νμμ λν μΆμ(abstracting over the type)μ λ°°μ΄κ³Ό λ°°μ΄ μμ ν μμλ₯Ό κ²μνλ ν¨μμ μ μ©ν κ²°κ³Όμ΄λ€. λ€νμ ν¨μλ₯Ό νλμ λ©μλλ‘μ μμ±ν λμλ μΌνλ‘ κ΅¬λΆλ νμ 맀κ°λ³μ(type parameter)λ€μ λͺ©λ‘μ λκ΄νΈλ‘ κ°μΈκ³ (μ§κΈ μμμλ νλμ [A]), κ·Έλ€μμ ν¨μμ μ΄λ¦μ μ§μ νλ€(μ§κΈμ μμμλ findFirst
). νμ 맀κ°λ³μ μ΄λ¦μΌλ‘λ μ΄λ€ κ²μ΄λΌλ μ¬μ©ν μ μλ€. κ·Έλ¬λ 보ν΅μ [A, B, C]
κ°μ 짧μ ν κΈμμ§λ¦¬ λλ¬Έμ νμ 맀κ°λ³μ μ΄λ¦λ€μ μ¬μ©νλ κ²μ΄ κ΄λ‘μ΄λ€.
νμ 맀κ°λ³μ λͺ©λ‘μ νμ μλͺ
μ λλ¨Έμ§ λΆλΆμμ μ°Έκ³ ν μ μλ νμ λ³μ(type variable)λ€μ λμ
νλ€. findFirst
μμ νμ λ³μ A
λ λ κ³³μμ μ°Έμ‘°λλ€. λ°°μ΄μ μμλ€μ νμμ΄ λ°λμ A
μ΄μ΄μΌ νλ©°, ν¨μ p
λ λ°λμ A
νμμ κ°μ λ°μμΌ νλ€. νμ μλͺ
μ λ μ₯μμμ λμΌν νμ λ³μλ₯Ό μ°Έμ‘°νλ€λ μ¬μ€μ ν΄λΉ λ μΈμμ νμμ΄ λμΌν΄μΌ ν¨μ μλ―Ένλ©°, μ»΄νμΌλ¬λ λͺ¨λ findFirst
νΈμΆ μ₯μμμ μ΄ μ¬μ€μ κ°μ νλ€.
π μ΅λͺ ν¨μλ‘ κ³ μ°¨ ν¨μ νΈμΆβ
κ³ μ°¨ ν¨μλ₯Ό νΈμΆν λ, κΈ°μ‘΄μ μ΄λ¦ λΆμ ν¨μλ₯Ό μΈμλ‘ μ§μ ν΄μ νΈμΆνλ κ²μ΄ μλλΌ μ΅λͺ ν¨μ(anonymous function) λλ ν¨μ 리ν°λ΄(function literal)μ μ§μ ν΄μ νΈμΆνλ κ²μ΄ νΈλ¦¬ν κ²½μ°κ° λ§λ€.
findFirst(Array(7, 9, 13), (x: Int) => x == 9)
μ μμμμ λ°°μ΄ λ¦¬ν°λ΄μ μ μ μΈ κ°λ₯Ό λ΄μ μ λ°°μ΄μ μμ±νκ³ new
κ°μ ν€μλ μμ΄ λ°°μ΄μ μμ±ν μ μλ€. (x: Int) => x == 9
λΌλ ꡬ문μ ν¨μ 리ν°λ΄ λλ μ΅λͺ
ν¨μμ΄λ€. μΌλ°μ μΌλ‘, ν¨μμ μΈμλ€μ =>
νμ΄νμ μ’λ³μμ μ μΈλλ€. μ μΈλ μΈμλ νμ΄ν μ€λ₯Έμͺ½μ μλ ν¨μ λ³Έλ¬Έμμ μ¬μ©ν μ μλ€.
(Int, Int) => Boolean = <function2>
π νμμμ λμΆλ ꡬνβ
λ€νμ ν¨μλ₯Ό ꡬνν λμλ κ°λ₯ν ꡬνλ€μ 곡κ°μ΄ ν¬κ² μ€μ΄λ λ€. ν¨μκ° μ΄λ€ νμ Aμ λν΄ λ€νμ μ΄λ©΄, Aμ λν΄μλ μ€μ§ μΈμλ€λ‘μ ν¨μμ μ λ¬λ μ°μ°λ€λ§ μνν μ μλ€. μ¬μ§μ΄, μ£Όμ΄μ§ λ€νμ νμμ λν΄ μ€μ§ λ¨ νλμ ꡬνλ§ κ°λ₯ν΄μ§ μ λλ‘ κ°λ₯μ±μ 곡κ°μ΄ μΆμλλ κ²½μ°λ μλ€.
κ·ΈλΌ λ¨ ν κ°μ§ λ°©μμΌλ‘λ§ κ΅¬νν μ μλ ν¨μ μλͺ
μ μλ‘, λΆλΆ μ μ©(partial application)μ΄λΌκ³ λΆλ₯΄λ μμ
μ μννλ κ³ μ°¨ ν¨μλ₯Ό μ΄ν΄λ³΄μ. partial1
μ΄λΌλ μ΄ ν¨μλ κ° νλμ ν¨μ(μΈμλ₯Ό λ κ° λ°λ) νλλ₯Ό λ°κ³ μΈμλ₯Ό νλμΈ ν¨μλ₯Ό κ²°κ³Όλ‘ λλ €μ€λ€.
def partial1[A, B, C](a: A, f: (A, B) => C): B => C
μ΄λ¬ν κ³ μ°¨ ν¨μλ₯Ό μ΄λ»κ² ꡬνν΄μΌ ν κΉ? μ»΄νμΌ κ°λ₯ν ꡬνμ λ¨ ν κ°μ§μ΄λ©°, κ·Έ ꡬνμ ν¨μμ νμ μλͺ
μμ λ
Όλ¦¬μ μΌλ‘ λμΆλλ€. partial1
μ λ°ν νμμ B => C
μ΄λ―λ‘, λ°λμ κ·Έλ° νμμ ν¨μλ₯Ό λλ €μ£Όμ΄μΌ νλ€.
def partial1[A, B, C](a: A, f: (A, B) => C): B => C =
(b: B) => ???
Bλ μ΄λμ λΉλ‘―λ κ²μΌκΉ?? λ°©κΈ μΆκ°ν μ½λλ "B νμμ κ° bλ₯Ό λ°λ ν¨μλ₯Ό λλ €μ€λ€"λΌλ λ»μ΄λ€. =>
νμ΄νμ μ°λ³(μ§κΈ λ¬Όμνλ€)μ κ·Έ μ΅λͺ
ν¨μμ λ³Έλ¬Έμ΄λ€. partial1
μ λ³Έλ¬Έμμ a
μ κ°μ μ°Έμ‘°ν μ μλ κ²μ²λΌ. κ·Έ μ°λ³μμ κ° b
λ₯Ό λ§μλλ‘ μ°Έμ‘°ν μ μλ€.
λ€μμΌλ‘, νμ Bλ₯Ό λ°λ ν¨μκ° λλ €μ£Όλ κ°μ μ΄λ€ κ²μ΄μ΄μΌ ν κΉ? νμ μλͺ μ 보면 κ·Έ κ°μ νμμ΄ Cμ΄μ΄μΌ ν¨μ μ μ μλ€. κ·Έλ¦¬κ³ κ·Έλ¬ν νμμ κ°μ μ»λ λ°©λ²μ λ¨ νλλΏμ΄λ€. μλͺ μ λ°λ₯΄λ©΄ C λ ν¨μ fμ λ°ν νμμ΄λ€.
def partial1[A, B, C](a: A, f: (A, B) => C): B => C =
(b: B) => f(a, b)
μ΄μ μΈμκ° λ κ°μΈ ν¨μλ₯Ό λ°μμ κ·Έκ²μ λΆλΆμ μΌλ‘ μ μ©νλ κ³ μ°¨ ν¨μκ° λ§λ€μ΄μ‘λ€. μ¦, λ§μΌ AλΌλ νμμ΄ μκ³ Aμ Bλ₯Ό λͺ¨λ λ°μμ Cλ₯Ό μ°μΆνλ ν¨μκ° μλ€λ©΄, Bλ§μΌλ‘λ Cλ₯Ό μ°μΆνλ ν¨μλ₯Ό μ»μ μ μλ κ²μ΄λ€(Aλ μ΄λ―Έ μμΌλ―λ‘).
μ¬κΈ°μ bμ λν νμμ μ§μ ν νμκ° μμμ μ£Όλͺ©νμ. λ°ν νμμ B => C
λ‘ λͺ
μνμΌλ―λ‘, ꡬνμμ κ·Έλ₯ b => f(a, b)
λΌκ³ νκΈ°ν΄λ μ€μΉΌλΌλ λ¬Έλ§₯μμ b
μ νμμ μΆλ‘ ν μ μλ€. μΌλ°ννμλ©΄, μ€μΉΌλΌκ° μΆλ‘ ν μ μμ λμλ ν¨μ 리ν°λ΄μμ νμ μ£Όν΄λ₯Ό μλ΅ν μ μλ€.
λ§μ§λ§ μλ‘ ν¨μ ν©μ±(function composition)μ μ΄ν΄λ³΄μ. ν¨μ ν©μ±μμλ ν ν¨μμ μΆλ ₯μ λ€λ₯Έ ν¨μμ μ λ ₯μΌλ‘ 곡κΈνλ€. μ΄ ν¨μμ ꡬν μμ μ μ μΌλ‘ κ·Έ νμ μλͺ μΌλ‘ κ²°μ λλ€.
ν¨μν νλ‘κ·Έλλ°μμλ μ΄λ° ν©μ±μ΄ μμ£Ό μΌμ¬μ μΌλ‘ μ°μ΄κΈ° λλ¬Έμ, μ΄λ₯Ό μν΄ μ€μΉΌλΌμ νμ€ λΌμ΄λΈλ¬λ¦¬λ Function1
μ compose
λ©μλλ₯Ό μ 곡νλ€. λ ν¨μ f
μ g
λ₯Ό ν¨μ±νλ €λ©΄ κ·Έλ₯ f compose g
λΌκ³ νλ©΄ λλ€. λν μ΄ μΈν°νμ΄μ€λ andThen
μ΄λΌλ λ©μλλ μ 곡νλ€. f andThen g
λ g compose f
μ κ°λ€.
val f = (x: Double) => math.Pi / 2 - x
// Double => Double => <function1>
val cos = f andThen math.sin
// Double => Double => <function1>
compose
κ°μ κ³ μ°¨ ν¨μλ μμ μ΄ μλ°±λ§ μ€μ μ½λλ‘ μ΄λ£¨μ΄μ§ κ±°λν ν¨μλ₯Ό λ€λ£¨λμ§ μλλ©΄ κ°λ¨ν ν μ€μ§λ¦¬ ν¨μλ₯Ό λ€λ£¨λμ§ μ κ²½μ°μ§ μλλ€. λ€νμ μΈ κ³ μ°¨ ν¨μλ€μ κ·Έ μ μ© λ²μκ° κ·Ήλλ‘ λμ κ²½μ°κ° λ§μλ°, μ΄λ κ·Έλ° ν¨μκ° νΉμ λ¬Έμ μμμ λν΄ νΉλ³ν μꡬλ₯Ό κ°μ§κ³ μμ§ μμΌλ©° μ€μ§ λ€μμ λ¬Έλ§₯μμ λ°μνλ 곡ν΅μ ν¨ν΄μ μΆμννκΈ° λλ¬Έμ΄λ€. μ΄ λ λ¬Έμ ν° κ·λͺ¨μ νλ‘κ·Έλλ°λ μμ κ·λͺ¨μ νλ‘κ·Έλλ°κ³Ό μμ£Ό λΉμ·ν λλμΌλ‘ μ§νν μ μλ€.