การเรียกซ้ำและฟังก์ชันลำดับสูง
ทำความเข้าใจการเรียกซ้ำในฐานะแนวคิดพื้นฐานของการเขียนโปรแกรมเชิงฟังก์ชัน และสำรวจฟังก์ชันลำดับสูงเพื่อแยกพฤติกรรมออกมาเป็นนามธรรม
การเรียกซ้ำและฟังก์ชันลำดับสูง เป็นบทเรียน Elixir & Phoenix: Scalable Backend Development ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Elixir & Phoenix: Scalable Backend Development และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Elixir & Phoenix: Scalable Backend Development มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Meet Recursion in Elixir
Welcome to recursion! In functional programming, recursion is a powerful technique where a function calls itself to solve a problem.
Instead of using loops (like for or while in other languages), Elixir often relies on recursion to iterate over data or repeat actions. It's a core concept you'll use a lot!
The Two Pillars of Recursion
Every recursive function needs two main parts to work correctly:
- Base Case: This is the stopping condition. It defines when the function should stop calling itself and return a direct result. Without it, your function would run forever!
- Recursive Step: This is where the function calls itself again, but with a smaller or simpler version of the original problem. Each call moves closer to the base case.
Recursion in Action: Factorial
Let's see recursion with a classic example: calculating the factorial of a number. The factorial of n (written as n!) is the product of all positive integers less than or equal to n. For example, 5! = 5 * 4 * 3 * 2 * 1 = 120.
Notice how factorial(n) calls factorial(n - 1) until it hits the base case of 0.
defmodule Math do
def factorial(0), do: 1
def factorial(n) when n > 0, do: n * factorial(n - 1)
end
IO.puts "Factorial of 5: #{Math.factorial(5)}"Efficient Recursion: Tail Calls
While recursion is great, naive recursion can sometimes lead to performance issues or 'stack overflows' for very deep calls.
Elixir (and the Erlang VM) offers Tail Call Optimization (TCO). If the recursive call is the very last operation in a function, the VM can optimize it, preventing new stack frames from being created. This makes tail-recursive functions as efficient as loops!
Optimizing with Tail Recursion
To achieve TCO, we often use an accumulator. This is an extra argument passed to the function that collects the result as the recursion progresses.
Compare this version to the previous one. The recursive call factorial(n - 1, n * acc) is the last thing happening in the function, making it tail-recursive.
defmodule Math do
# Public interface, calls the private tail-recursive function
def factorial(n), do: factorial(n, 1)
# Private tail-recursive function with accumulator
defp factorial(0, acc), do: acc
defp factorial(n, acc) when n > 0, do: factorial(n - 1, n * acc)
end
IO.puts "Tail factorial of 5: #{Math.factorial(5)}"Functions as First-Class Citizens
Now, let's explore Higher-Order Functions (HOFs). In Elixir, functions are 'first-class citizens'. This means you can:
- Pass functions as arguments to other functions.
- Return functions as results from other functions.
- Assign functions to variables.
HOFs enable powerful abstractions, making your code more concise, flexible, and reusable.
Transforming Lists with Enum.map
Enum.map/2 is one of the most common HOFs. It takes an enumerable (like a list) and a function. It applies that function to each element and returns a new list with the transformed elements.
It never modifies the original list, embracing Elixir's immutability.
numbers = [1, 2, 3, 4]
doubled_numbers = Enum.map(numbers, fn n -> n * 2 end)
IO.puts "Original: #{inspect numbers}"
IO.puts "Doubled: #{inspect doubled_numbers}"Filtering Lists with Enum.filter
Another handy HOF is Enum.filter/2. It takes an enumerable and a function that should return a boolean (true or false).
It returns a new list containing only the elements for which the function returned true. It's perfect for selecting specific items from a collection.
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = Enum.filter(numbers, fn n -> rem(n, 2) == 0 end)
IO.puts "Original: #{inspect numbers}"
IO.puts "Even: #{inspect even_numbers}"Aggregating with Enum.reduce
Enum.reduce/3 is perhaps the most powerful HOF for working with enumerables. It takes an enumerable, an initial accumulator value, and a function.
It iterates through the collection, applying the function to each element and the current accumulator, eventually reducing the entire collection to a single value.
numbers = [1, 2, 3, 4]
sum = Enum.reduce(numbers, 0, fn n, acc -> n + acc end)
product = Enum.reduce(numbers, 1, fn n, acc -> n * acc end)
IO.puts "Numbers: #{inspect numbers}"
IO.puts "Sum: #{sum}"
IO.puts "Product: #{product}"Anonymous Functions and HOFs
You've seen fn n -> n * 2 end. These are anonymous functions (or lambdas). Elixir provides a shorthand for simple anonymous functions:
&1refers to the first argument.&2refers to the second argument, and so on.&(&1 + &2)is equivalent tofn a, b -> a + b end.
This makes HOF calls even more concise!
numbers = [1, 2, 3, 4]
doubled_short = Enum.map(numbers, &(&1 * 2))
even_short = Enum.filter(numbers, &(rem(&1, 2) == 0))
IO.puts "Doubled (short): #{inspect doubled_short}"
IO.puts "Even (short): #{inspect even_short}"Test Your HOF Knowledge
Higher-Order Functions are a cornerstone of functional programming in Elixir. Let's check your understanding.
Recursion & HOFs: Key Takeaways
Great job! In this lesson, you've grasped two fundamental concepts in functional Elixir:
- Recursion: A function calling itself, defined by a base case and a recursive step.
- Tail Call Optimization (TCO): An important Elixir feature for efficient, stack-safe recursion, often achieved with an accumulator.
- Higher-Order Functions (HOFs): Functions that take other functions as arguments or return them, like
Enum.map,Enum.filter, andEnum.reduce. - Anonymous Functions: Concise ways to define functions inline, often used with HOFs, including the
&1shorthand.
These tools are essential for writing expressive and powerful Elixir code. Keep practicing!
คำถามที่พบบ่อย
บทเรียน “การเรียกซ้ำและฟังก์ชันลำดับสูง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การเรียกซ้ำและฟังก์ชันลำดับสูง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Elixir & Phoenix: Scalable Backend Development ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Elixir & Phoenix: Scalable Backend Development มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การเรียกซ้ำและฟังก์ชันลำดับสูง”
ทำความเข้าใจการเรียกซ้ำในฐานะแนวคิดพื้นฐานของการเขียนโปรแกรมเชิงฟังก์ชัน และสำรวจฟังก์ชันลำดับสูงเพื่อแยกพฤติกรรมออกมาเป็นนามธรรม คุณปฏิบัติ Elixir & Phoenix: Scalable Backend Development ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Elixir & Phoenix: Scalable Backend Development หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Elixir & Phoenix: Scalable Backend Development บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การเรียกซ้ำและฟังก์ชันลำดับสูง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Elixir & Phoenix: Scalable Backend Development นี้ได้ไหม
ได้ บทเรียน Elixir & Phoenix: Scalable Backend Development ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ฟังก์ชัน โมดูล และการส่งต่อข้อมูล
- การทำงานกับคอลเลกชันที่แจกแจงได้
- การเรียกซ้ำและฟังก์ชันลำดับสูง
- การประเมินแบบขี้เกียจด้วยโมดูล Stream