ส่งกลับค่า
ค่าที่ส่งกลับมีความสำคัญเนื่องจากช่วยให้คุณควบคุมโฟลว์ได้โดยไม่ต้องมีสถานะเพิ่มเติม ใน Scheme นิพจน์ที่ได้รับการประเมินล่าสุดจะกลายเป็นค่าที่ส่งคืน
หน้านี้ใช้ตัวช่วยในการตรวจสอบจากตัวอย่างข้อความเพื่อแสดงให้เห็นว่าค่าที่ส่งคืนอย่างชัดเจนทำให้การเขียนโค้ดง่ายขึ้นได้อย่างไร
มูลค่าการส่งคืนคืออะไร?
ใน Scheme ค่าที่ส่งคืนของฟังก์ชันจะถูกกำหนดโดยนิพจน์สุดท้ายที่ฟังก์ชันประเมิน ซึ่งหมายความว่าบรรทัดสุดท้ายของโค้ดในฟังก์ชันที่ประเมินค่าจะถูกส่งกลับตามผลลัพธ์ของฟังก์ชัน หากไม่มีการส่งคืนค่าอย่างชัดเจน ฟังก์ชันจะส่งคืน #f (false) หรือ undefined
เรามาทบทวนฟังก์ชั่นการตรวจสอบอีกครั้ง (is-valid-string?)
;; Purpose: Validates that the message is a non-empty string
(define (is-valid-string? message)
;; Check if the message is a non-empty string
(if (or (not (string? message)) (string=? message ""))
(error "Message must be a non-empty string")))ในฟังก์ชันนี้ หากข้อความไม่ถูกต้อง ระบบจะแสดงข้อผิดพลาด อย่างไรก็ตาม หากข้อความถูกต้อง จะไม่ระบุค่าที่ส่งคืนอย่างชัดเจน และฟังก์ชันจะส่งคืน #f ตามค่าเริ่มต้น
ทำให้ค่าส่งคืนชัดเจน
เราสามารถปรับปรุงสิ่งนี้ได้โดยทำให้ค่าที่ส่งคืนชัดเจนยิ่งขึ้น ตัวอย่างเช่น เราอาจส่งคืน #t (true) หากข้อความถูกต้อง:
;; Purpose: Validates that the message is sent to a valid output
(define (is-valid-output-display? output)
;; Check if the output is one of the expected display destinations
(if (not (member output '(dialog-box status-bar error-console terminal)))
(error "Invalid output destination: " output)
#t))ในเวอร์ชันนี้ ฟังก์ชันจะส่งกลับ #t เมื่อข้อความถูกต้อง โดยให้ผลลัพธ์ที่ชัดเจน ซึ่งช่วยให้สามารถใช้ฟังก์ชันได้อย่างยืดหยุ่นมากขึ้นในบริบทอื่นๆ ที่จำเป็นต้องใช้ผลลัพธ์แบบบูลีน
การใช้ค่าส่งคืนอย่างมีประสิทธิภาพ
การตัดสินใจว่าฟังก์ชันของเราส่งคืนอะไร เราสามารถทำให้สามารถคาดเดาได้และมีประโยชน์มากขึ้น การส่งคืนค่า เช่น #t, #f หรือผลลัพธ์เฉพาะเจาะจงช่วยให้เราควบคุมวิธีที่ฟังก์ชันโต้ตอบกับโค้ดที่เหลือได้มากขึ้น ตัวอย่างเช่น คุณสามารถใช้ค่าที่ส่งคืนเพื่อทำการตัดสินใจเพิ่มเติมในฟังก์ชันการโทร หรือส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันอื่นได้
ต่อไปนี้เป็นตัวอย่างง่ายๆ ของการใช้ค่าตอบแทนเพื่อควบคุมการไหลของตรรกะ:
;; Purpose: Dispatches a message to the appropriate output destination
(define (send-message message output)
(if (is-valid-output-display? output)
(cond
((eq? output 'error-console) (send-to-error-console message))
((eq? output 'dialog-box) (send-to-dialog-box message))
((eq? output 'status-bar) (send-to-status-bar message))
((eq? output 'terminal) (send-to-terminal message)))))ในกรณีนี้ (ส่งข้อความ) อาศัยค่าที่ส่งคืนของ (is-valid-output-display?) เพื่อตัดสินใจว่าจะดำเนินการต่อไปหรือไม่
คำสั่งแบบมีเงื่อนไข cond จะถูกข้ามหากการทดสอบครั้งแรกล้มเหลว นอกจากนี้ ให้สังเกตว่ามันอ่านในลักษณะที่เป็นธรรมชาติอย่างไร หากเป็นจอแสดงผลเอาท์พุตที่ถูกต้อง
ถ้าตรรกะคำสั่งในโครงการ
ก่อนตัวอย่างไลบรารีที่ปรับโครงสร้างใหม่ ต่อไปนี้คือการตรวจสอบตรรกะแบบมีเงื่อนไขโดยย่อ Scheme ใช้ if เพื่อเลือกระหว่างสองเส้นทาง
นี่คือรูปแบบง่ายๆ ของคำสั่ง if:
(if (conditional test)
do if true
do if false)โครงสร้างนี้จะตรวจสอบเงื่อนไข และหากเงื่อนไขเป็นจริง โครงสร้างจะดำเนินการในการดำเนินการแรก หากเงื่อนไขเป็นเท็จ จะดำเนินการที่สอง
ในกรณีที่คุณจำเป็นต้องดำเนินการหลายอย่างเมื่อเงื่อนไขเป็นจริงหรือเท็จ คุณสามารถใช้ begin เพื่อจัดกลุ่มเข้าด้วยกัน:
(if (conditional test)
(begin
do if true)
(begin
do if false))สิ่งนี้ช่วยให้คุณสามารถจัดการกับสถานการณ์ที่ซับซ้อนมากขึ้น ซึ่งจำเป็นต้องดำเนินการหลายนิพจน์หรือคำสั่ง ทั้งนี้ขึ้นอยู่กับผลลัพธ์ของการทดสอบแบบมีเงื่อนไข
โอเค นี่คือโค้ดไลบรารีที่มีค่าส่งคืนฝังอยู่และใช้เพื่อควบคุมกระบวนการดำเนินการ
ปรับโครงสร้างใหม่ด้วยค่าส่งคืน
;; Purpose: Sends a message to the status bar, returns #t if successful
(define (send-to-status-bar message)
(if (is-valid-string? message)
(begin
(lumi-message-set-handler MESSAGE-BOX)
(lumi-message message)
(lumi-message-set-handler ERROR-CONSOLE)
#t)
#f))
;; Purpose: Sends a message to the dialog box, returns #t if successful
(define (send-to-dialog-box message)
(if (is-valid-string? message)
(begin
(lumi-message-set-handler MESSAGE-BOX)
(lumi-message (string-append message "\n"))
(lumi-message-set-handler ERROR-CONSOLE)
#t)
#f))
;; Purpose: Sends a message to the error console, returns #t if successful
(define (send-to-error-console message)
(if (is-valid-string? message)
(begin
(lumi-message-set-handler ERROR-CONSOLE)
(lumi-message message)
#t)
#f))
;; Purpose: Sends a message to the terminal, returns #t if successful
(define (send-to-terminal message)
(if (is-valid-string? message)
(begin
(display message)
(lumi-message-set-handler ERROR-CONSOLE)
#t)
#f))
;; Purpose: Dispatches a message to the appropriate output, returns #t if successful
(define (send-message message output)
(if (is-valid-string-output? output)
(cond
((eq? output 'error-console) (send-to-error-console message))
((eq? output 'dialog-box) (send-to-dialog-box message))
((eq? output 'status-bar) (send-to-status-bar message))
((eq? output 'terminal) (send-to-terminal message)))
#f))
;; Purpose: Validates that the message is a non-empty string, returns #t if valid
(define (is-valid-string? message)
(if (or (not (string? message)) (string=? message ""))
(begin
(error "Message must be a non-empty string")
#f)
#t))
;; Purpose: Validates that the output is a valid destination, returns #t if valid
(define (is-valid-string-output? output)
(if (not (member output '(dialog-box status-bar error-console terminal)))
(begin
(error "Invalid output destination: " output)
#f)
#t))บทสรุป
ค่าที่ส่งคืนเป็นส่วนพื้นฐานของการทำให้ฟังก์ชันมีความยืดหยุ่นและนำกลับมาใช้ใหม่ได้ ด้วยการตัดสินใจอย่างรอบคอบว่าแต่ละฟังก์ชันควรส่งคืนอะไร เราสามารถมั่นใจได้ว่าฟังก์ชันของเราโต้ตอบกันได้ดี และให้ข้อมูลที่เป็นประโยชน์กับส่วนที่เหลือของโค้ด ไม่ว่าจะเป็นการส่งคืน #t หรือ #f หรืออะไรที่เฉพาะเจาะจงมากขึ้น ค่าที่ส่งคืนทำให้เรามีวิธีในการควบคุมโฟลว์ของโปรแกรมของเราและจัดการกับผลลัพธ์ต่างๆ