วิธีใช้การประเมินผลขี้เกียจของ if ()


10

ขณะนี้ฉันกำลังใช้ตัวประเมินผลนิพจน์ (นิพจน์บรรทัดเดียว, เช่นสูตร) ​​ตามสิ่งต่อไปนี้:

  • การแสดงออกที่ป้อนถูกโทเค็นเพื่อแยก booleans ตัวอักษรจำนวนเต็มทศนิยมสตริงฟังก์ชั่นตัวระบุ (ตัวแปร)
  • ฉันใช้อัลกอริทึม Shunting-yard (แก้ไขเบา ๆ เพื่อจัดการฟังก์ชันที่มีจำนวนตัวแปรที่มีข้อโต้แย้ง) เพื่อกำจัดวงเล็บและสั่งให้ผู้ประกอบการที่มีความสำคัญมาก่อนในลำดับ postfixed
  • shunting-yard ของฉันสร้างคิวโทเค็น (จำลอง) (โดยใช้อาร์เรย์อาร์เรย์ภาษา Powerbuilder Classic ของฉันสามารถกำหนดวัตถุ แต่มีอาร์เรย์แบบไดนามิกเป็นหน่วยเก็บข้อมูลดั้งเดิมไม่ใช่รายการจริงไม่มีพจนานุกรม) ที่ฉันประเมินตามลำดับด้วย เครื่องกองง่าย

ผู้ประเมินของฉันทำงานได้ดี แต่ฉันก็ยังขาดif()และฉันก็สงสัยว่าจะดำเนินการต่อไปอย่างไร

ถ้าฉันเพิ่มif()ฟังก์ชันอื่นที่มีส่วนที่เป็นจริงและเท็จอยู่คนเดียวif(true, msgbox("ok"), msgbox("not ok"))จะแสดงข้อความทั้งสองในขณะที่ฉันต้องการจะแสดงเพียงข้อความเดียว นี่เป็นเพราะเมื่อฉันต้องการประเมินฟังก์ชั่นข้อโต้แย้งทั้งหมดได้รับการประเมินและวางลงบนสแต็ก

คุณช่วยให้ฉันใช้if()วิธีขี้เกียจบางอย่าง?

ฉันคิดว่าการประมวลผลเหล่านี้เป็นมาโครชนิดหนึ่ง แต่ในตอนแรกฉันยังไม่ได้ประเมินสภาพ บางทีฉันอาจต้องใช้โครงสร้างชนิดอื่นที่ไม่ใช่คิวเพื่อแยกเงื่อนไขและนิพจน์จริง / เท็จออกจากกัน? สำหรับตอนนี้นิพจน์จะถูกวิเคราะห์ก่อนการประเมินผล แต่ฉันยังวางแผนที่จะเก็บการแทนค่ากลางไว้เป็นชนิดของนิพจน์ที่คอมไพล์แล้วสำหรับการประเมินในอนาคต

แก้ไข : หลังจากที่แม้ว่าบางอย่างเกี่ยวกับปัญหาที่เกิดขึ้นผมคิดว่าผมสามารถสร้างตัวแทนต้นไม้ในการแสดงออกของฉัน (เป็น AST แทนกระแสโทเค็นเชิงเส้น) if()จากที่ผมได้อย่างง่ายดายสามารถละเว้นหนึ่งหรือสาขาอื่นของฉัน

คำตอบ:


9

มีสองตัวเลือกที่นี่

1) อย่าใช้ifเป็นฟังก์ชั่น ทำให้เป็นคุณสมบัติภาษาที่มีความหมายพิเศษ ทำง่าย แต่น้อย "บริสุทธิ์" ถ้าคุณต้องการให้ทุกอย่างเป็นฟังก์ชั่น

2) ใช้ซีแมนทิกส์ "call by name" ซึ่งมีความซับซ้อนมากขึ้น แต่อนุญาตให้เวทมนตร์ของคอมไพเลอร์ดูแลปัญหาการประเมินที่ขี้เกียจในขณะที่ยังคงifทำหน้าที่แทนฟังก์ชั่นองค์ประกอบของภาษา มันจะเป็นเช่นนี้:

ifเป็นฟังก์ชั่นที่รับพารามิเตอร์สองตัวซึ่งทั้งคู่จะประกาศเป็น "ตามชื่อ" เมื่อคอมไพเลอร์เห็นว่ามันกำลังส่งบางสิ่งไปยังพารามิเตอร์ตามชื่อมันจะเปลี่ยนรหัสที่จะสร้าง แทนที่จะประเมินค่านิพจน์และส่งผ่านค่ามันจะสร้างการปิดที่ประเมินค่านิพจน์และส่งผ่านค่านั้นแทน และเมื่อเรียกใช้พารามิเตอร์ by-name ภายในฟังก์ชั่นคอมไพเลอร์สร้างรหัสเพื่อประเมินการปิด


ฉันไม่แน่ใจ แต่ควร "ปิด" เป็น "thunk" หรือไม่ อืมอาจจะไม่ เพิ่งดูที่หน้าวิกิพีเดีย: "thunk เป็นการปิดแบบไม่มีพารามิเตอร์"

เมื่อคุณพูดว่า "การโทรตามชื่อ" คุณหมายถึงทั่วโลก? อีกทางเลือกหนึ่งคือ Global call-by-name กำลังใช้ชนิดการปิดดังนั้นถ้าฟังก์ชันใช้เวลาปิด 3 ครั้งและประเมินสอง (เงื่อนไขแล้วหรืออย่างอื่น) แต่ไม่ใช่ทุกสิ่งที่จำเป็นต้องได้รับการยอมรับเช่นการปิดเช่นการโทรเต็มโดย อรรถศาสตร์ชื่อ
จิมมี่ฮอฟฟา

@ Matt: คำว่า "thunk" อาจหมายถึงสิ่งอื่น ๆ อีกมากมายในบริบทของการเขียนโปรแกรมและ "การปิดแบบไม่มีพารามิเตอร์" ไม่ใช่คำแรกที่ฉันนึกถึงเมื่อได้ยิน "การปิด" เป็นสิ่งที่ชัดเจนกว่ามาก
Mason Wheeler

1
@JimmyHoffa: เมื่อฉันพูดว่า "call by name" ฉันหมายถึงลักษณะเฉพาะของการตั้งค่าอาร์กิวเมนต์ของฟังก์ชันซึ่งควรเป็นทางเลือก คล้ายกับหลายภาษาที่มีอยู่จะช่วยให้คุณเลือกที่จะผ่านพารามิเตอร์ตามมูลค่าหรืออ้างอิงสำหรับสถานการณ์นี้คุณต้องเลือกที่จะผ่านชื่อ
Mason Wheeler

ในขณะที่ข้อเสนอแนะของคุณเกี่ยวกับซีแมนทิกส์ "call by name" แสดงให้ฉันเห็นประเด็นที่น่าสนใจบางอย่างมันค่อนข้างเกินความจริงสำหรับผู้ประเมินของฉันซึ่งไม่ใช่คอมไพเลอร์ที่สมบูรณ์เนื่องจากฟังก์ชั่นการโทรของฉันเป็นแบบบรรทัดเดียว ฉันคิดว่าฉันสามารถเพิ่มอีกหนึ่งขั้นตอนหลังจากการเข้าคิวโทเค็นโดยทำการประเมินปลอมของสแต็กเพื่ออนุมานทรีที่เรียก มันควรจะง่ายกว่าที่จะรู้จากต้นไม้กิ่งเพื่อทิ้ง
เซกิ

3

แทนที่จะใช้ฟังก์ชันที่มีลายเซ็น:

object if(bool, object, object)

ให้ลายเซ็น:

object if(bool, object function(), object function())

จากนั้นifฟังก์ชั่นของคุณจะเรียกใช้ฟังก์ชั่นที่เหมาะสมตามเงื่อนไขเพียงแค่ประเมินหนึ่งในนั้น


1

มันค่อนข้างง่ายถ้าคุณรวบรวมทุกอย่างอย่างเกียจคร้าน คุณต้องมีวิธีการบางอย่างเพื่อดูว่าค่าได้รับการประเมินแล้วหรือถ้ามันต้องการการ evlauation เพิ่มเติม

จากนั้นคุณสามารถทำสิ่งต่อไปนี้: ถ้าเป็นตัวอักษรหรือตัวแปร (คุณมีสิ่งเหล่านั้นหรือไม่เช่นชื่อฟังก์ชั่น?) ให้กดลงบนสแต็ก หากเป็นแอปพลิเคชั่นของฟังก์ชั่นให้รวบรวมแยกจากกันและกดจุดเข้าใช้งานบนสแต็ก

การดำเนินการของโปรแกรมนั้นจะทำการวนซ้ำจนกระทั่งส่วนบนสุดของสแต็กถูกประเมินและไม่ใช่ฟังก์ชัน ถ้ามันไม่ได้รับการประเมินหรือฟังก์ชั่นโทรรหัสด้านบนของสแต็กชี้ไปที่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.