การกำหนดค่าการกำหนดค่า
**การกำหนดค่า** ในทางวิทยาการคอมพิวเตอร์ คือการระบุค่าหรือการตั้งค่าใหม่ให้กับตำแหน่งเก็บข้อมูลที่แสดงไว้โดยชื่อตัวแปร ในภาษาโปรแกรมเชิงคำสั่ง *ข้อความสั่งกำหนดค่า* เป็นข้อความสั่งพื้นฐานอย่างหนึ่ง ข้อความสั่งกำหนดค่ามักอนุญาตให้ชื่อตัวแปรเดิมสามารถมีได้หลายค่าในเวลาต่าง ๆ ในระหว่างที่โปรแกรมทำงาน

สัญกรณ์
-------

ตัวแทนการนำเสนอแบบข้อความโดยสามัญของการกำหนดค่ามักจะใช้เครื่องหมายเท่ากับ "=" และ ":=" รูปแบบทั้งสองนี้เป็นรูปแบบปกติของภาษาโปรแกรมหลายภาษา (เช่นภาษาซี) ซึ่งจัดจำแนกการกำหนดค่าว่าเป็นตัวดำเนินการเติมกลาง

|  |  |
| --- | --- |
| `*ตัวแปร* = *นิพจน์*` | ภาษาเบสิก, ภาษาฟอร์แทรน, ภาษาซี, ภาษาจาวา, ภาษาพีแอล/วัน, วินโดวส์ เพาเวอร์เชลล์, บอร์นเชลล์, ฯลฯ |
| `*ตัวแปร* := *นิพจน์*` | ภาษาอัลกอล, ภาษาปาสกาล, ภาษาเอดา, ภาษาดิลัน, ภาษาไอเฟล, ฯลฯ |

ความเป็นไปได้อย่างอื่นคือเพิ่มลูกศรชี้ข้างซ้ายหรือคำหลักเข้าไป หรือแม้แต่รูปแบบต่างที่สามารถใช้ได้ซึ่งพบเห็นได้น้อยกว่า

|  |  |
| --- | --- |
| `*ตัวแปร* << *นิพจน์*` | ภาษาแมจิก |
| `*ตัวแปร* <- *นิพจน์*` | ภาษาอ็อบเจกทีฟแคมัล, ภาษาเอส, ภาษาอาร์, ฯลฯ |
| `*ตัวแปร* ← *นิพจน์*` | ภาษาเอพีแอล |
| `*ตัวแปร* =: *นิพจน์*` | ภาษาเจ |
| `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` ซึ่งจะทำให้ข้อความสั่งตามเงื่อนไขทำงาน นำไปสู่พฤติกรรมของโปรแกรมที่ไม่คาดหวัง ตัวประมวลผลของบางภาษาสามารถตรวจจับสถานการณ์เช่นนั้น และแจ้งเตือนโปรแกรมเมอร์เกี่ยวกับความผิดพลาดที่อาจเกิดขึ้นได้

อ้างอิง
-------

1. ↑  Moore, Lawrie (1980). *Foundations of Programming with Pascal*. New York: John Wiley & Sons. ISBN 0-470-26939-1.
2. ↑  Feinberg, Neal; Keene, Sonya E.; Mathews, Robert O.; Withington, P. Tucker (1997). *Dylan Programming*. Massachusetts: Addison Wesley. ISBN 0-201-47976-1.
3. ↑  Meyer, Bertrand (1992). *Eiffel the Language*. Hemel Hempstead: Prentice Hall International(UK). ISBN 0-13-247925-7.
4. ↑  Wiener, Richard (1996). *An Object-Oriented Introduction to Computer Science Using Eiffel*. Upper Saddle River, New Jersey: Prentice Hall. ISBN 0-13-183872-5.
5. ↑  Iverson, Kenneth E. (1962). *A Programming Language*. John Wiley and Sons. ISBN 0471430145.
6. ↑  Ullman, Jeffrey D. (1998). *Elements of ML Programming: ML97 Edition*. Englewood Cliffs, New Jersey: Prentice Hall. ISBN 0-13-790387-1.
7. ↑  Graham, Paul (1996). *Ansi Common Lisp*. New Jersey: Prentice Hall. ISBN 0-13-370875-6.
8. ↑  Steele, Guy L. (1990). *Common Lisp - The Language*. Lexington: Digital Press. ISBN 1-55558-041-6.
9. ↑  Dybvig, R. Kent (1996). *The Scheme Programming Language: Ansi Scheme*. New Jersey: Prentice Hall. ISBN 0-13-454646-6.
10. ↑  Smith, Jerry D. (1988). *Introduction to Scheme*. New Jersey: Prentice Hall. ISBN 0-13-496712-7.
11. ↑  Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie (1996). *Structure and Interpretation of Computer Programs*. New Jersey: McGraw-Hill. ISBN 0-07-000484-6.
12. ↑  INMOS Limited, บ.ก. (1988). *Occam 2 Reference Manual*. New Jersey: Prentice Hall. ISBN 0-13-629312-3.
13. ↑  Lutz, Mark (2001). *Python programming language* (2 ed.). Sebastopol: O´Reilly. ISBN 0-596-00085-5.
14. ↑  Wall, Larry; Christiansen, Tom; Schwartz, Randal C. (1996). *Perl programming language* (2 ed.). Cambridge: O´Reilly. ISBN 1-56592-149-6.
15. ↑  Thomas, David; Hunt, Andrew (2001). *Programming Ruby: The Pragmatic Programmer´s Guide*. Upper Saddle River: Addison Wesley. ISBN 0-201-71089-7.
16. ↑  D.W. Barron *et al.*, "The main features of CPL", *Computer Journal* **6**:2:140 (1963). full text (subscription)
17. ↑  Hudak, Paul (2000). *The Haskell School of Expression: Learning Functional Programming Through Multimedia*. Cambridge: Cambridge University Press. ISBN 0-521-64408-9.

ดูเพิ่ม
-------

* การยึดเหนี่ยวกับชื่อ
* การรวมเป็นหนึ่ง