Predicates

หลังจากพูดถึง Booleans ไปแล้ว สิ่งต่อมา ก็คือสิ่งที่เรียกว่า “Predicates” จะพูดว่ามันคืออะไรก็ค่อนข้างยาก ดูเหมือนว่าคำนี้ใช้ในหลายๆความหมายและหลายๆสาขาวิชา /me เองก็สับสนอยู่เหมือนกัน

แต่ในที่นี้ Predicates หมายถึง ของ 2 อย่าง คือ

* Boolean-valued function : ฟังก์ชั่นที่ return boolean
* Characteristic function : ฟังก์ชั่นที่อธิบายความสัมพันธ์หรือลักษณะเฉพาะบางอย่างของสิ่งที่เราสนใจ

ตัวอย่างที่สำคัญ และเป็นฟังก์ชั่นที่จำเป็นสำหรับ isPrime() ก็คือ IS_ZERO(n) ซึ่งมีหน้าที่เช็คว่าตัวเลข n เท่ากับ 0 หรือไม่

IS_ZERO(n) ถือเป็นสะพานชิ้นสำคัญที่เชื่อมความสัมพันธ์ของ numbers ไปเป็น boolean แน่นอนว่า ทุกคนสามารถ implement IS_ZERO ได้อย่างง่ายได้ในภาษาโปรแกรมมิ่งทั่วๆไป แต่สำหรับเงื่อนไขที่ใช้เฉพาะ functions เราสามารถเขียนมันขึ้นมาได้อย่างไร?

ก่อนอื่น คือการพิจารณาตัวเลขที่เราสร้างขึ้นมากันอีกครั้ง

จะเห็นว่า ZERO เป็นเพียงตัวเลขเดียวที่ไม่เรียก function p และ /me สามารถใช้คุณสมบัตินี้ในการสร้าง IS_ZERO โดยกำหนดให้ p เป็นฟังก์ชั่นที่จะ return FALSE เสมอ เมื่อไรก็ตามที่ตัวเลขนั้นไม่ใช่ ZERO มันจะให้ค่าเป็น FALSE และในทางกลับกัน เราสามารถกำหนดให้ x มีค่าเป็น TRUE เมื่อ ZERO ทำการ return x เท่ากับว่า มันเป็นการ return TRUE ด้วยเช่นกัน

ลองทดสอบอีกครั้ง

ลองเอา IS_ZERO ไปใช้ใน isPrime(n)

หลังจากได้ส่วนประกอบสำคัญอย่าง IS_ZERO(n) มาแล้ว
บันไดขั้นต่อมา คือ เครื่องหมายเปรียบเทียบ(Comparison Operators) มากกว่า, น้อยกว่า, มากกว่าเท่ากับ และน้อยกว่าเท่ากับ

ความจริงแล้ว การเปรียบเทียบก็เสมอการหยิบแอ๊ปเปิ้ลและส้มออกจากถุงพร้อมๆกัน ใครโดนหยิบจนเหลือถุงเปล่าก่อนก็เป็นฝ่ายพ่ายแพ้และถือว่ามีจำนวนน้อยกว่าไปโดยปริยาย

หรือพูดเป็นสมการคณิตศาสตร์ได้ว่า m <= n ก็ต่อเมื่อ m – n <= 0

ดังนั้นการสร้าง LESS_THAN_OR_EQUAL(m, n) ก็หนีไม่พ้นการใช้ SUBTRACT และการเทียบเท่ากับ ZERO แต่โลกที่เราสร้างขึ้นนี้ไม่มีสิ่งที่เรียกว่า จำนวนลบ ดังนั้น การเทียบน้อยกว่า ZERO จึงไม่มีความหมายใดๆ (ทุกตัวเลขที่ต่ำกว่า 0 จะได้ค่าเท่ากับ 0)

เราจึงสามารถสร้าง LESS_THAN_OR_EQUAL(m, n) ได้ดังนี้

และเมื่อ /me พบว่า not LESS_THAN_OR_EQUAL คือ GREATER_THAN

สิ่งที่น่าคิดต่อมาคือ แล้ว “น้อยกว่าเฉยๆ” และ “มากกว่าเท่ากับ” จะสร้างขึ้นมายังไง? แต่ /me ยังไม่อับจนหนทาง เรายังมีคุณสมบัติสุดท้าย

คุณสมบัติสลับด้าน เมื่อ x < y แล้ว y > x

โดยทั่วไปแล้วเรามักใช้สมการแก้ไขปัญหา สำหรับสมการ ไม่ว่าเราสลับด้านมันยังไง มันก็ยังคงได้สิ่งเดียวกัน แต่สำหรับอสมการ เรากลับได้สิ่งที่แตกต่างจากเดิม และนี้คือหนึ่งในคุณสมบัติเฉพาะของอสมการ และทำให้ /me เอามาใช้ในการสร้าง LESS_THAN(m, n) และ GREATER_THAN_OR_EQUAL(m, n) ดังนี้

//เผื่อไม่สังเกต มันมีการสลับตัวแปรจากของเดิม

จบไปอีกหนึ่งตอน

ถึงแม้ว่าเรายังไม่เข้าใกล้เป้าหมาย isPrime(n) ของเราเลย แต่มันก็เป็นการวางรากฐานที่มั่นคง หลังจากนี้ เราจะสามารถลุยไปได้อย่างรวดเร็ว

สำหรับตอนหน้า /me จะพาไปเขียนฟังก์ชั่นที่เรายังค้างกันอยู่ DIVIDE และ MODULO ซึ่งต้องใช้สิ่งที่เราสร้างมาทั้งหมดไม่ว่าจะเป็น SUBTRACT, LESS_THAN_OR_EQUAL และ เครื่องมือชิ้นใหม่ที่เรียกว่า Y combinator และการทำ recursion

PS. อ่านตอนก่อนหน้าได้ที่
EP1: Introduction
EP2: Numbers
EP3: Arithmetic operators
EP4: Booleans
EP5: Predicates & Comparison Operators

ต้นฉบับ Programming with Nothing

แต่สามารถ ดูโค้ดส่วนต่างๆได้ที่ Github จะทยอย push ตามบล๊อคที่ทยอยเขียน

Tell your friend about thisShare on Facebook
Facebook
0Tweet about this on Twitter
Twitter