การกำหนดค่า
การกำหนดค่า ในทางวิทยาการคอมพิวเตอร์ คือการระบุค่าหรือการตั้งค่าใหม่ให้กับตำแหน่งเก็บข้อมูลที่แสดงไว้โดยชื่อตัวแปร ในภาษาโปรแกรมเชิงคำสั่ง ข้อความสั่งกำหนดค่า เป็นข้อความสั่งพื้นฐานอย่างหนึ่ง ข้อความสั่งกำหนดค่ามักอนุญาตให้ชื่อตัวแปรเดิมสามารถมีได้หลายค่าในเวลาต่าง ๆ ในระหว่างที่โปรแกรมทำงาน
สัญกรณ์
ตัวแทนการนำเสนอแบบข้อความโดยสามัญของการกำหนดค่ามักจะใช้เครื่องหมายเท่ากับ "=" และ ":=" รูปแบบทั้งสองนี้เป็นรูปแบบปกติของภาษาโปรแกรมหลายภาษา (เช่นภาษาซี) ซึ่งจัดจำแนกการกำหนดค่าว่าเป็นตัวดำเนินการเติมกลาง
ตัวแปร = นิพจน์ | ภาษาเบสิก, ภาษาฟอร์แทรน, ภาษาซี, ภาษาจาวา, ภาษาพีแอล/วัน, วินโดวส์ เพาเวอร์เชลล์, บอร์นเชลล์, ฯลฯ |
ตัวแปร := นิพจน์ | ภาษาอัลกอล, ภาษาปาสกาล, ภาษาเอดา, ภาษาดิลัน, ภาษาไอเฟล, ฯลฯ |
ความเป็นไปได้อย่างอื่นคือเพิ่มลูกศรชี้ข้างซ้ายหรือคำหลักเข้าไป หรือแม้แต่รูปแบบต่างที่สามารถใช้ได้ซึ่งพบเห็นได้น้อยกว่า
ตัวแปร << นิพจน์ | ภาษาแมจิก |
ตัวแปร <- นิพจน์ | ภาษาอ็อบเจกทีฟแคมัล, ภาษาเอส, ภาษาอาร์, ฯลฯ |
ตัวแปร ← นิพจน์ | ภาษาเอพีแอล |
ตัวแปร =: นิพจน์ | ภาษาเจ |
LET ตัวแปร = นิพจน์ | ภาษาเบสิก |
set ตัวแปร to นิพจน์ | แอปเปิลสคริปต์ |
set ตัวแปร = นิพจน์ | ซีเชลล์ |
Set-Variable ตัวแปร (นิพจน์) | วินโดวส์ เพาเวอร์เชลล์ |
val ตัวแปร = นิพจน์ | ภาษาเอ็มแอล |
ตัวแปร : นิพจน์ | แมกซิมา |
บางแพลตฟอร์มก็วางนิพจน์ไว้ทางซ้ายและวางตัวแปรไว้ทางขวา
MOVE นิพจน์ TO ตัวแปร | ภาษาโคบอล |
นิพจน์ → ตัวแปร | ภาษาทีไอ-เบสิก, ภาษาเบสิกคาสิโอ (เครื่องคิดเลข) |
นิพจน์ -> ตัวแปร | ภาษาอาร์ |
ในภาษาโปรแกรมเชิงนิพจน์บางภาษา อย่างเช่นภาษาลิสป์ และภาษาทีซีแอล ใช้วากยสัมพันธ์แบบเติมหน้าเพียงอย่างเดียวสำหรับทุกข้อความสั่ง ซึ่งรวมทั้งการกำหนดค่าด้วย
(setq ตัวแปร นิพจน์) | ภาษาลิสป์, ภาษาสกีม (set! ), ฯลฯ |
set ตัวแปร นิพจน์ | ภาษาทีซีแอล |
การดำเนินการ
การดำเนินการกำหนดค่าตามความหมายแล้วเป็นการเปลี่ยนแปลงสถานะปัจจุบันของโปรแกรมที่กำลังทำงานอยู่ ดังนั้นการกำหนดค่าจึงขึ้นอยู่กับแนวคิดของตัวแปร ในการกำหนดค่าหนึ่ง ๆ นิพจน์ จะถูกประเมินค่าในสถานะปัจจุบันของโปรแกรม และ ตัวแปร จะถูกกำหนดด้วยค่าที่ประเมินนั้น แทนที่ค่าที่มีอยู่ก่อนหน้าในตัวแปร ตัวอย่างเช่น สมมติให้ a
เป็นตัวแปรเชิงตัวเลข การกำหนดค่า a := 2*a
หมายถึงการทำให้ข้อมูลของตัวแปร a
เพิ่มค่าเป็นสองเท่าหลังจากทำงานข้อความสั่งนี้แล้ว
ต่อไปนี้คือตัวอย่างส่วนหนึ่งของภาษาซี
int x = 10; float y; x = 23; y = 32.4;
จากตัวอย่างนี้ ตัวแปร x
ประกาศไว้ว่าเป็นจำนวนเต็ม (int
) เมื่อเริ่มแรก จากนั้นจึงกำหนดค่าเป็น 10 สังเกตว่าการประกาศและการกำหนดค่าเกิดขึ้นในข้อความสั่งเดียวกัน บรรทัดที่สอง ตัวแปร y
ประกาศเป็นจำนวนจุดลอยตัว (float
) โดยไม่กำหนดค่า บรรทัดถัดไป x
ถูกกำหนดค่าใหม่ให้เป็น 23 และท้ายสุด y
ถูกกำหนดให้มีค่าเท่ากับ 32.4
ในการดำเนินการกำหนดค่านั้น สิ่งสำคัญคือค่าของ นิพจน์ จะต้องนิยามไว้แล้วเป็นอย่างดี (เป็น rvalue ที่ถูกต้อง) และ ตัวแปร จะต้องแทนด้วยเอนทิตีที่สามารถแก้ไขได้ (เป็น lvalue ที่เปลี่ยนแปลงได้ คือไม่เป็นค่าคงตัว) ในบางภาษาอย่างเช่นภาษาเพิร์ล ไม่จำเป็นต้องประกาศตัวแปรก่อนกำหนดค่าก็ได้
การกำหนดค่าแบบขนาน
ภาษาโปรแกรมบางภาษาเช่น ภาษาอ็อกแคม 2ภาษาไพทอนภาษาเพิร์ลภาษาเรบัล ภาษารูบีวินโดวส์ เพาเวอร์เชลล์ และจาวาสคริปต์ (ตั้งแต่รุ่น 1.7) อนุญาตให้กำหนดค่าตัวแปรหลายตัวแบบขนานได้ (parallel assignment) ด้วยวากยสัมพันธ์คล้ายดังนี้
a,b := 0,1
คำสั่งนี้กำหนดค่า 0 ลงใน a
และค่า 1 ลงใน b
ในเวลาเดียวกัน ถ้าฝั่งขวามือของการกำหนดค่าเป็นตัวแปรแถวลำดับ คุณลักษณะดังนี้อาจเรียกว่า การขยายลำดับออก (sequence unpacking)
var list := 0,1 a,b := list
รายการแถวลำดับจะถูกขยายออก ทำให้กำหนดค่า 0 ลงใน a
และค่า 1 ลงใน b
ได้เช่นกัน รหัสต่อไปนี้เป็นตัวอย่างที่น่าสนใจ
a,b := b,a
ข้อความสั่งดังกล่าวจะสลับค่าของ a
กับ b
ส่วนภาษาที่ไม่มีการกำหนดค่าแบบขนาน การสลับค่าอาจต้องเขียนโดยใช้ตัวแปรชั่วคราว t
ดังนี้
var t := a a := b b := t
เนื่องจากข้อความสั่ง a:=b ; b:=a
จะส่งผลให้ตัวแปรทั้งสองมีค่าเดียวกันคือค่าเริ่มต้นของ b
การกำหนดค่าแบบขนานเริ่มแนะนำในภาษาซีพีแอลเมื่อ พ.ศ. 2506 (ค.ศ. 1963) ในชื่อ การกำหนดค่าพร้อมกัน (simultaneous assignment)
ค่าของการกำหนดค่า
ในภาษาโปรแกรมเชิงนิพจน์ส่วนใหญ่ ข้อความสั่งกำหนดค่าจะคืนค่าเป็นค่าที่ถูกกำหนดนั้น ซึ่งทำให้ข้อความสั่งเช่น x = y = a
ค่าของ a
จะถูกกำหนดให้กับทั้ง x
และ y
หรืออย่างเช่น while (f = read()) {…}
ค่าที่คืนจากฟังก์ชันจะเป็นตัวควบคุมการวนรอบ ในเวลาเดียวกันก็กำหนดค่าที่เหมือนกันให้กับตัวแปรด้วย
ส่วนภาษาโปรแกรมอื่น ค่าที่ส่งคืนจากการกำหนดค่าอาจไม่นิยาม และทำให้ข้อความสั่งเช่นนั้นใช้การไม่ได้ ยกตัวอย่างเช่นภาษาสกีม
ภาษาไพทอนถือว่าการกำหนดค่าไม่ใช่นิพจน์ ดังนั้นมันจึงไม่มีค่าใด ๆ ส่งคืนกลับมา
ในภาษาแฮสเกลล์ ไม่มีการกำหนดค่าให้กับตัวแปร แต่การดำเนินการที่คล้ายกับการกำหนดค่า (เหมือนการกำหนดค่าไปยังเขตข้อมูลของแถวลำดับ หรือเขตข้อมูลของโครงสร้างข้อมูลเปลี่ยนแปลงได้) คือการประเมินค่าเป็นยูนิต ซึ่งเป็นชนิดข้อมูลทั่วไปของนิพจน์ที่ถูกประเมินค่าเพื่อให้เกิดผลข้างเคียงโดยเฉพาะ
การกำหนดค่าปกติกับการกำหนดค่าเชิงเดี่ยว
ในการเขียนโปรแกรมเชิงฟังก์ชัน การกำหนดค่าจะลดความสำคัญลงเพื่อประโยชน์ในการกำหนดค่าเชิงเดี่ยว (single assignment) หรืออาจเรียกว่า การยึดเหนี่ยวกับชื่อ หรือ การกำหนดค่าเริ่มต้น การกำหนดค่าเชิงเดี่ยวต่างจากการกำหนดค่าปกติตรงที่สามารถกำหนดค่าได้เพียงครั้งเดียวเท่านั้น โดยเฉพาะเมื่อตัวแปรถูกสร้างขึ้น นั่นคือไม่สามารถกำหนดค่าใหม่ภายหลัง ค่าที่ถูกตั้งชื่อโดยการกำหนดค่าเชิงเดี่ยวจะไม่ถือว่าเป็นตัวแปร แต่จะเป็นวัตถุเปลี่ยนแปลงไม่ได้
การกำหนดค่าเชิงเดี่ยวเป็นรูปแบบเพียงอย่างเดียวที่มีอยู่สำหรับภาษาโปรแกรมเชิงฟังก์ชันอย่างแท้จริง (purely funtional) เช่นภาษาแฮสเกลล์ ซึ่งไม่มีตัวแปรอย่างภาษาโปรแกรมเชิงคำสั่งอื่น ๆ ภาษาโปรแกรมเชิงฟังก์ชันที่ไม่แท้จริงก็อาจมีทั้งการกำหนดค่าเชิงเดี่ยวและการกำหนดค่าปกติ (แม้ว่าการกำหนดค่าปกติมีที่ใช้น้อยกว่าในภาษาโปรแกรมเชิงคำสั่ง) ตัวอย่างเช่น ในภาษาสกีม การกำหนดค่าเชิงเดี่ยวและการกำหนดค่าปกติสามารถใช้ได้กับตัวแปรทุกตัว หรือในภาษาอ็อบเจกทีฟแคมัล การกำหนดค่าเชิงเดี่ยวใช้กับตัวแปรโดยใช้รูปแบบ let ชื่อ = ค่า
ส่วนการกำหนดค่าปกติซึ่งใช้ตัวดำเนินการ <-
ใช้กับสมาชิกของแถวลำดับและสายอักขระ เช่นเดียวกับเขตข้อมูลของระเบียนและวัตถุที่ถูกประกาศอย่างชัดเจนว่าให้สามารถเปลี่ยนแปลงได้ (หมายความว่าขนาดความจุของมันสามารถเปลี่ยนแปลงได้หลังจากการประกาศตอนเริ่มต้น)
การกำหนดค่าและภาวะเท่ากัน
โปรแกรมเมอร์ ระดับเริ่มต้นเกิดความสับสนบ่อยครั้งระหว่างการกำหนดค่ากับตัวดำเนินการสัมพันธ์ของภาวะเท่ากัน เนื่องจาก = หมายถึงภาวะเท่ากันในทางคณิตศาสตร์ และถูกใช้เป็นตัวดำเนินการกำหนดค่าในหลายภาษา แต่การกำหนดค่าคือการเปลี่ยนแปลงค่าของตัวแปร ในขณะที่การทดสอบภาวะเท่ากันจะตรวจสอบนิพจน์สองนิพจน์ว่ามีค่าเหมือนกันหรือไม่
หลายภาษาใช้สัญกรณ์ที่แตกต่างกันสำหรับการดำเนินการแต่ละชนิด ตัวอย่างเช่น ตัวดำเนินการกำหนดค่าใช้เครื่องหมายเท่ากับตัวเดียว = ในขณะที่ตัวดำเนินการเทียบเท่าใช้เครื่องหมายเท่ากับสองตัว == ในภาษาซี แต่ในบางภาษาเช่นภาษาเบสิก เครื่องหมายเท่ากับตัวเดียวใช้แทนการดำเนินการทั้งสอง ซึ่งความหมายของมันจะพิจารณาจากบริบท
ความสับสนเช่นนี้อาจนำไปสู่ความผิดพลาด หากโปรแกรมเมอร์หลงลืมว่ารูปแบบใดถูกต้องเหมาะสม หรือลงรหัสผิดพลาด (เช่นพิมพ์ = แทนที่ตั้งใจให้เป็น ==) เป็นปัญหาปกติสามัญของการเขียนโปรแกรม อาทิในภาษาซี ตัวดำเนินการกำหนดค่าจะคืนค่าเป็นค่าที่กำหนดไปนั้น และสามารถใช้ซ้อนภายในนิพจน์ได้ (แบบเดียวกับฟังก์ชันที่คืนค่าออกมา) ถ้าความตั้งใจคือการเปรียบเทียบค่าสองค่าในเงื่อนไข if
การกำหนดค่าในเงื่อนไขอาจถูกตีความหมายว่าเป็นค่า TRUE
ซึ่งจะทำให้ข้อความสั่งตามเงื่อนไขทำงาน นำไปสู่พฤติกรรมของโปรแกรมที่ไม่คาดหวัง ตัวประมวลผลของบางภาษาสามารถตรวจจับสถานการณ์เช่นนั้น และแจ้งเตือนโปรแกรมเมอร์เกี่ยวกับความผิดพลาดที่อาจเกิดขึ้นได้
อ้างอิง
- Moore, Lawrie (1980). Foundations of Programming with Pascal. New York: John Wiley & Sons. ISBN 0-470-26939-1.
- Feinberg, Neal (1997). Dylan Programming. Massachusetts: Addison Wesley. ISBN 0-201-47976-1. Unknown parameter
|coauthors=
ignored (|author=
suggested) (help) - Meyer, Bertrand (1992). Eiffel the Language. Hemel Hempstead: Prentice Hall International(UK). ISBN 0-13-247925-7.
- Wiener, Richard (1996). An Object-Oriented Introduction to Computer Science Using Eiffel. Upper Saddle River, New Jersey: Prentice Hall. ISBN 0-13-183872-5.
- Iverson, Kenneth E. (1962). A Programming Language. John Wiley and Sons. ISBN 0471430145.
- Ullman, Jeffrey D. (1998). Elements of ML Programming: ML97 Edition. Englewood Cliffs, New Jersey: Prentice Hall. ISBN 0-13-790387-1.
- Graham, Paul (1996). Ansi Common Lisp. New Jersey: Prentice Hall. ISBN 0-13-370875-6.
- Steele, Guy L. (1990). Common Lisp - The Language. Lexington: Digital Press. ISBN 1-55558-041-6.
- Dybvig, R. Kent (1996). The Scheme Programming Language: Ansi Scheme. New Jersey: Prentice Hall. ISBN 0-13-454646-6.
- Smith, Jerry D. (1988). Introduction to Scheme. New Jersey: Prentice Hall. ISBN 0-13-496712-7.
- Abelson, Harold (1996). Structure and Interpretation of Computer Programs. New Jersey: McGraw-Hill. ISBN 0-07-000484-6. Unknown parameter
|coauthors=
ignored (|author=
suggested) (help) - INMOS Limited, บ.ก. (1988). Occam 2 Reference Manual. New Jersey: Prentice Hall. ISBN 0-13-629312-3.
- Lutz, Mark (2001). Python programming language (2 ed.). Sebastopol: O´Reilly. ISBN 0-596-00085-5.
- Wall, Larry (1996). Perl programming language (2 ed.). Cambridge: O´Reilly. ISBN 1-56592-149-6. Unknown parameter
|coauthors=
ignored (|author=
suggested) (help) - Thomas, David (2001). Programming Ruby: The Pragmatic Programmer´s Guide. Upper Saddle River: Addison Wesley. ISBN 0-201-71089-7. Unknown parameter
|coauthors=
ignored (|author=
suggested) (help) - D.W. Barron et al., "The main features of CPL", Computer Journal 6:2:140 (1963). full text (subscription)
- Hudak, Paul (2000). The Haskell School of Expression: Learning Functional Programming Through Multimedia. Cambridge: Cambridge University Press. ISBN 0-521-64408-9.
ดูเพิ่ม
- การยึดเหนี่ยวกับชื่อ
- การรวมเป็นหนึ่ง