I'm a Ruby on Rails / jQuery web developer. Follow me at @sikachu

Operator Precedence ใน Ruby

December 19th, 2009 Posted in Programming, Ruby

Operator 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 เป็นภาษาที่แปลก … ผมเชื่อแล้วแหละว่าแปลกจริงๆ ;)

  • punneng

    ใช้วงเล็บ ลดความวิงเวียน มึนศีรษะ หน้ามืด จาเป็นโลมมมม