폴딩과 리듀싱
foldLeft와 reduce를 알아봅니다
폴딩과 리듀싱은(는) CoddyKit의 무료 Scala for Backend Engineering & Functional Programming 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Scala for Backend Engineering & Functional Programming 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Scala for Backend Engineering & Functional Programming 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Combining elements into one
Sometimes you need to combine all elements of a collection into a single value, like a sum or a concatenation. Scala provides fold, foldLeft, foldRight, and reduce for this.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
println(nums.sum)
println(nums.product)
}
}reduce: combine without a seed
reduce combines elements pairwise using a binary function. It needs at least one element, otherwise it throws an exception.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val total = nums.reduce((a, b) => a + b)
println(total)
val max = nums.reduce((a, b) => if (a > b) a else b)
println(max)
}
}foldLeft: combine with a seed
foldLeft takes an initial seed value and a function. It is safe on empty collections (returns the seed) and lets the result type differ from the element type.
Syntax: xs.foldLeft(seed)((acc, x) => ...).
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val sum = nums.foldLeft(0)((acc, x) => acc + x)
println(sum)
val empty = List.empty[Int].foldLeft(0)(_ + _)
println(empty)
}
}The accumulator pattern
In a fold, the first argument is the accumulator that carries the running result, and the second is the current element. Each step updates the accumulator.
object Main {
def main(args: Array[String]): Unit = {
val words = List("Scala", "is", "great")
val sentence = words.foldLeft("")((acc, w) => acc + w + " ")
println(sentence.trim)
}
}Result type can differ
A powerful feature of foldLeft: the accumulator type can differ from the elements. Here we fold a list of numbers into a String.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3)
val joined = nums.foldLeft("nums:")((acc, n) => acc + " " + n)
println(joined)
}
}foldRight: from the right
foldRight processes elements from right to left. The accumulator is the second argument: (x, acc) => .... Direction matters for non-commutative operations.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val left = nums.foldLeft("")((acc, x) => acc + x)
val right = nums.foldRight("")((x, acc) => acc + x)
println("foldLeft: " + left)
println("foldRight: " + right)
}
}Left vs right and performance
foldLeft is tail-recursive and stack-safe on large lists. foldRight on a List can overflow the stack for very large inputs. Prefer foldLeft unless order forces otherwise.
object Main {
def main(args: Array[String]): Unit = {
val big = (1 to 100000).toList
val total = big.foldLeft(0L)((acc, x) => acc + x)
println(total)
}
}Building a collection with fold
Folds are general enough to build collections. Here we reverse a list by prepending each element to an accumulator list.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val reversed = nums.foldLeft(List.empty[Int])((acc, x) => x :: acc)
println(reversed)
}
}reduceOption for safety
Because reduce fails on empty collections, reduceOption returns an Option instead: Some(result) when non-empty, None when empty.
object Main {
def main(args: Array[String]): Unit = {
println(List(3, 1, 4).reduceOption(_ + _))
println(List.empty[Int].reduceOption(_ + _))
}
}fold: a symmetric variant
fold is like foldLeft but the accumulator must be the same type as the elements. It is often used with parallel collections.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val total = nums.fold(0)(_ + _)
println(total)
}
}Counting with foldLeft
Folds can compute richer results, like counting how many elements satisfy a condition, all in one pass.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(4, 7, 2, 9, 6, 1)
val evenCount = nums.foldLeft(0)((acc, x) => if (x % 2 == 0) acc + 1 else acc)
println(s"even numbers: $evenCount")
}
}Quick Check
What is the key difference between reduce and foldLeft?
Recap
You learned folding and reducing:
reduce— combine pairwise, no seed, fails if emptyreduceOption— safe variant returningOptionfoldLeft— seed + accumulator, stack-safe, flexible result typefoldRight— right-to-left, watch the stack on large lists- Folds can even build new collections
자주 묻는 질문
“폴딩과 리듀싱” 강의는 무료인가요?
네 — “폴딩과 리듀싱” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Scala for Backend Engineering & Functional Programming 강의 전체를 잠금 해제할 수 있습니다. Scala for Backend Engineering & Functional Programming 강의에는 총 4개의 강의가 포함되어 있습니다.
“폴딩과 리듀싱”에서 뭘 배우나요?
foldLeft와 reduce를 알아봅니다 브라우저에서 직접 실행하는 실습 코드로 Scala for Backend Engineering & Functional Programming을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Scala for Backend Engineering & Functional Programming을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Scala for Backend Engineering & Functional Programming은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“폴딩과 리듀싱” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Scala for Backend Engineering & Functional Programming 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Scala for Backend Engineering & Functional Programming 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.