เพื่อแสดงให้เห็นถึงประสิทธิภาพของการเรียกซ้ำส่วนท้าย ฉันต้องการวิธีเข้าถึงความลึกของ call stack แบบไดนามิกใน Scheme
มีวิธีการทำเช่นนี้หรือไม่? ถ้าไม่ มีวิธีการทำเช่นนี้ในภาษาการทำงานหลักอื่น ๆ (OCaml, Haskell ฯลฯ ) หรือไม่?
เพื่อแสดงให้เห็นถึงประสิทธิภาพของการเรียกซ้ำส่วนท้าย ฉันต้องการวิธีเข้าถึงความลึกของ call stack แบบไดนามิกใน Scheme
มีวิธีการทำเช่นนี้หรือไม่? ถ้าไม่ มีวิธีการทำเช่นนี้ในภาษาการทำงานหลักอื่น ๆ (OCaml, Haskell ฯลฯ ) หรือไม่?
แร็กเก็ตช่วยให้คุณเก็บค่าไว้ใน call stack คุณสามารถใช้สิ่งนี้เพื่อติดตามความลึกได้ นี่คือวิธีที่ฉันจะทำอย่างไร:
#lang racket
;;; This module holds the tools for keeping track of
;;; the current depth.
(module depth racket
(provide (rename-out [depth-app #%app])
current-depth)
(define (extract-current-continuation-marks key)
(continuation-mark-set->list (current-continuation-marks) key))
(define (current-depth)
(car (extract-current-continuation-marks 'depth)))
(define-syntax (depth-app stx)
(syntax-case stx ()
[(_depth-app proc args ...)
#'(let ([p (with-continuation-mark 'depth (+ (current-depth) 1)
proc)]
[as (with-continuation-mark 'depth (+ (current-depth) 1)
(list args ...))])
(apply p as))])))
;;; Importing the #%app from the depth module will override
;;; the standard application to use depth-app which keeps
;;; track of the depth.
(require 'depth)
(with-continuation-mark 'depth 0 ; set the initial depth to 0
(let ()
;;; Example: foo is tail recursive
(define (foo n)
(displayln (list 'foo n (current-depth)))
(if (< n 5)
(foo (+ n 1))
'done))
;;; bar is not tail recursive
(define (bar n)
(displayln (list 'bar n (current-depth)))
(if (< n 5)
(cons n (bar (+ n 1)))
'()))
;;; Call the examples
(foo 0)
(bar 0)))
ผลลัพธ์คือ:
(foo 0 2)
(foo 1 2)
(foo 2 2)
(foo 3 2)
(foo 4 2)
(foo 5 2)
(bar 0 2)
(bar 1 3)
(bar 2 4)
(bar 3 5)
(bar 4 6)
(bar 5 7)
'(0 1 2 3 4)
ผลลัพธ์แสดงว่าความลึกไม่เพิ่มขึ้นใน foo
และเพิ่มขึ้นใน bar
(apply p as)
อยู่ในตำแหน่งส่วนท้าย เอกสารกล่าวถึง apply
ว่า proc ที่กำหนดถูกเรียกในตำแหน่งส่วนท้ายที่เกี่ยวข้องกับการเรียกใช้ Apply กล่าวอีกนัยหนึ่ง นอกจากเครื่องหมายต่อเนื่องแล้ว สแต็กการโทรก่อนและหลังการใช้ #%app
ที่แก้ไขควรจะเทียบเท่ากัน
- person soegaard; 23.11.2015
ไม่มีวิธีมาตรฐานในการทำ
การเพิ่มประสิทธิภาพการโทรแบบหาง == ไม่มีการเพิ่มสแต็กการโทร คุณสาธิตมันโดยการเขียนสิ่งที่ปกติจะทำให้สแต็กระเบิดและรันมัน
คุณอาจได้รับสแต็กเทรซสั้นๆ เมื่อส่งสัญญาณถึงข้อผิดพลาดในเชิงลึก แต่ลักษณะที่ปรากฏนั้นเป็นการดำเนินการเฉพาะเจาะจง
ใน CL คุณสามารถติดตามฟังก์ชันได้ และคุณจะไม่เห็นเอาต์พุตใด ๆ จากการเรียก tail ต่อเนื่องกันเมื่อมีการปรับการเรียก tail ให้เหมาะสม
ภาษาที่ขี้เกียจไม่จำเป็นต้องเรียกซ้ำหางเนื่องจากการประเมินเป็นไปตามความจำเป็น