在 Scheme 中访问调用堆栈深度
Accessing call stack depth in Scheme
为了演示尾递归的有效性,我想要一种在Scheme中动态访问调用堆栈深度的方法。
有办法吗?如果没有,有没有办法在其他主要函数式语言(OCaml、Haskell 等)中做到这一点?
没有标准的方法来做到这一点。
尾调用优化== 没有增加调用堆栈。您通过编写通常会破坏堆栈和 运行 的内容来演示它。
在发出深层错误信号时,您可能会得到一个简短的堆栈跟踪,但它的外观是特定于实现的。
在 CL 中,您可以跟踪函数,并且在尾调用优化后您将看不到连续尾调用的输出。
惰性语言不需要尾递归,因为评估是按需进行的。
Racket 允许您在调用堆栈中存储值。
您可以使用它来跟踪深度。
以下是我的做法:
#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
中增加。
为了演示尾递归的有效性,我想要一种在Scheme中动态访问调用堆栈深度的方法。
有办法吗?如果没有,有没有办法在其他主要函数式语言(OCaml、Haskell 等)中做到这一点?
没有标准的方法来做到这一点。
尾调用优化== 没有增加调用堆栈。您通过编写通常会破坏堆栈和 运行 的内容来演示它。
在发出深层错误信号时,您可能会得到一个简短的堆栈跟踪,但它的外观是特定于实现的。
在 CL 中,您可以跟踪函数,并且在尾调用优化后您将看不到连续尾调用的输出。
惰性语言不需要尾递归,因为评估是按需进行的。
Racket 允许您在调用堆栈中存储值。 您可以使用它来跟踪深度。 以下是我的做法:
#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
中增加。