Operator Precedence ใน Ruby
December 19th, 2009 Posted in Programming, Ruby | CommentsOperator Precedence หรือลำดับสำคัญของตัวดำเนินการนั้น ถือเป็นหลักสำคัญของโปรแกรมเมอร์ ที่จะทำให้สามารถทำการเขียนอัลกอริธึมเพื่อแก้ไขปัญหาต่างๆ ได้ ในทางคณิตศาสตร์นั้น มักมีคนสรุปมันออกมาง่ายๆ ว่า “วงเล็บมาก่อน คูณหารก่อนบวกลบ”
ถ้าใครเคยเห็น code ภาษา Ruby นั้น คงจะเคยเห็นว่า Ruby นั้นมีทั้ง operator && และ || เหมือนกับในภาษา C แล้วยังมี and กับ or ที่เพิ่มเข้ามาใน Ruby ซึ่งเป็นสิ่งที่ทำให้โค้ดนั้นดูสวยงามขึ้น อ่านง่ายขึ้นตามหลักของ Ruby
ลองดูโค้ดด้านล่างนี้เป็นตัวอย่างครับ
irb(main):001:0> dessert = "Cheesecake" => "Cheesecake" irb(main):002:0> drink = "Coffee" => "Coffee" irb(main):003:0> dessert == "Cheesecake" && drink == "Tea" => false irb(main):004:0> dessert == "Cheesecake" and drink == "Tea" => false
จะเห็นได้ว่า && และ and นั้นให้ผลลัพธ์ที่เหมือนกัน ทำให้บางครั้งเราสามารถใช้ and มาแทนที่ && และ or มาแทนที่ || ได้
แต่ entry นี้มันชื่อ Operator Precedence … เพราะฉะนั้นเรื่องราวมันไม่ได้จบแค่นี้ครับ คำถามต่อไปคือ คุณคิดว่าค่าของตัวแปร first_order และ second_order จะเป็นอย่างไร ในคำสั่งต่อไปนี้:
first_order = dessert == "Cheesecake" && drink == "Tea" second_order = dessert == "Cheesecake" and drink == "Tea"
คำตอบลองดูในนี้เลยครับ:
irb(main):005:0> first_order = dessert == "Cheesecake" && drink == "Tea" => false irb(main):006:0> second_order = dessert == "Cheesecake" and drink == "Tea" => false irb(main):007:0> first_order => false irb(main):008:0> second_order => true
อะไรนี่ 0_o!
จะเห็นได้จากบรรทัดที่ 005 และ 006 ว่า ทั้งคู่ก็คืนค่าออกมาเป็น false ทั้งนั้น แล้วทำไมค่าที่เก็บใน first_order กับ second_order มันกลับไม่เหมือนกัน
คำตอบคือ เป็นเพราะ Operator Precedence ของ Ruby ครับ
เหตุผลที่ second_order นั้นมีค่าเป็น true นั้น เพราะว่าใน Ruby นั้น เครื่องหมาย = จะมีลำดับขั้นที่สูงกว่า and และ or ครับ
กล่าวคือ ในการเขียน statement ว่า
>> second_order = dessert == "Cheesecake" and drink == "Tea"
เจ้าตัว Ruby Interpreter นั้น จะทำการ evaluate ออกมาเป็นอย่างนี้
001> second_order = dessert == "Cheesecake" and drink == "Tea" 002> (second_order = dessert == "Cheesecake") and drink == "Tea" 003> true and drink == "Tea" 004> false
เพราะฉะนั้น คำสั่งข้างต้นที่ใช้ and นั้น ถ้าอยากให้มีผลเช่นเดียวกับ && จำเป็นที่จะต้องใส่วงเล็บครอบให้เป็นอย่างนี้ครับ
>> second_order = (dessert == "Cheesecake" and drink == "Tea")
มีคนชอบบอกว่า Ruby เป็นภาษาที่แปลก … ผมเชื่อแล้วแหละว่าแปลกจริงๆ














