ตัวแปรที่เปลี่ยนค่าได้
ภาษาส่วนใหญ่เมื่อกำหนดค่าให้ตัวแปรใดๆแล้ว ยังสามารถเปลี่ยนแปลงค่าของตัวแปรนั้นได้ผ่านการ assign ค่าใหม่ หรือผ่าน operator อื่นๆเช่นโค้ด Go ต่อไปนี้
var num int
num = 10
num = num + 20
info := map[string]string{"name": "John"}
info["forvorite_sport"] = "Football"
ในภาษา Go ตัวแปรอย่างเช่น num และ info สามารถถูกเปลี่ยนแปลงค่าได้แม้จะกำหนดค่าเริ่มต้นไปแล้ว
ตัวภาษาในลักษณะนี้ไม่ได้แค่มองว่าตัวแปรแทนชื่อของข้อมูลอย่างเดียว แต่ตัวแปรคือชื่อของตำแหน่งที่เก็บข้อมูลด้วย (memory address) ทำให้เราแก้ไขค่าของตัวแปร ก็คือแก้ไขค่าในตำแหน่งข้อมูลเดิมได้ นั่นเอง
ตัวแปรที่เปลี่ยนค่าไม่ได้
ในขณะที่ภาษาที่ตัวแปรไม่สามารถเปลี่ยนค่าได้อย่าง Elixir (หรือ Erlang) เราจะไม่ได้มองว่าตัวแปรแทนชื่อของตำแหน่งข้อมูล แต่เรามองว่าตัวแปรเป็นชื่อที่เราเอามาใช้แทนข้อมูลที่เก็บอยู่จริงๆ และโดยเฉพาะ Elixir กับ Erlang เครื่องหมาย =
ไม่ได้สื่อถึงการ Assign ค่าให้ตัวแปร แต่เป็นการ binding คือการเชื่อมโยงชื่อของตัวแปรหนึ่ง ให้กับค่าใดๆ (และใช้ในเรื่อง pattern matching ด้วย) ตัวอย่างเช่น
num = 10
num = num + 20
info = %{"name" => "John"}
info = Map.put(info, "forvorite_sport", "Football")
เมื่อเรากำหนดค่า num = 10 ใน Elixir แล้วอีกบรรทัดเรากำหนด num = num + 20 สำหรับ Elixir แล้วจะไม่ได้สนใจว่า num เป็นตำแหน่งข้อมูล แต่แค่ว่าเราได้ทำให้ num นั้นเชื่อมโยงไปหาค่าใหม่คือ 30 นั่นเอง ส่วน 10 และ 30 ตอนนี้อาจจะเก็บคนละที่ตอน runtime ก็อาจจะเป็นได้
ซึ่งไม่เหมือนกับ Go ด้านบน num ตอนเป็น 10 และ 30 อยู่ในตำแหน่งหน่วยความจำเดียวกันแน่นอน
ในส่วนของ info เช่นกันเมื่อเราทำการเพิ่ม key => value เข้าไปใหม่ด้วยฟังก์ชัน Map.put แล้วกำหนดค่าให้ info อีกครั้งมันคือการเชื่อมโยงชื่อ info ไปยังค่าใหม่ที่ไม่ได้สนใจแล้วว่าจะอยู่ตำแหน่งข้อมูลไหนตอน runtime
สรุป
ถ้าเข้าใจเราก็จะพอเห็นภาพว่าตอนเป็น mutable แบบ Go เราย้ายข้อมูลเข้าหาตำแหน่งข้อมูลที่แทนด้วยชื่อตัวแปร
แต่พอเป็น immutable จะตรงข้าม ตัวข้อมูลที่เปลี่ยนไป อาจจะอยู่คนละที่เลยแล้วชื่อตัวแปรต่างหาที่ถูกย้ายไปหาค่าใหม่
อาจจะมีคำถามว่าแล้ว immutable จะไม่ทำให้ใช้หน่วยความจำเยอะเกินไปเหรอ จริงๆแล้วไม่เสมอไป เผลอๆอาจจะได้ผลลัพธ์ที่ทำให้ใช้หน่วยความจำได้อย่างมีประสิทธิภาพด้วยซ้ำ
เพราะภาษาที่รองรับ immutable ดีๆนั้นจะยกหน้าที่การจัดการตำแหน่งหน่วยความจำให้กับ runtime ของภาษา อย่าง Elixir กับ Erlang ก็ยกให้กับ ErlangVM ทำหน้าที่จัดการให้ ใช้เทคนิคที่ชื่อว่า Persistent Data Structures ช่วยให้ runtime ตัดสินใจเกี่ยวกับการทำ GC ได้ดีขึ้นมีผลต่อประสิทธิภาพตอน runtime โดยรวมด้วยซ้ำ
Top comments (0)