You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Racket中实现call-stack-max-depth函数以获取无参函数的最大调用栈深度

Calculating Maximum Call Stack Depth in Scheme Using Continuation Marks

Got it, let's tackle writing that call-stack-max-depth function you need. The core idea is to use continuation marks to track the current stack depth as we execute the target thunk, while keeping a running tally of the maximum depth reached throughout the execution.

Here's a working implementation (Racket-specific, adaptable to other Scheme variants with similar continuation mark support):

#lang racket

(define (call-stack-max-depth thunk)
  ; Create a unique key to track stack depth in continuation marks
  (define depth-key (make-continuation-mark-key 'call-stack-depth))
  ; Initialize our max depth tracker
  (define max-depth 0)

  ; Wrapped apply function that updates depth and tracks the maximum value
  (define (traced-call proc . args)
    ; Calculate current depth: parent depth + 1 (default to 0 if no parent mark exists)
    (define current-depth (add1 (or (continuation-mark-set-first #f depth-key) 0)))
    ; Update max depth if current depth is larger
    (when (> current-depth max-depth)
      (set! max-depth current-depth))
    ; Set the new depth mark and execute the original procedure
    (with-continuation-mark depth-key current-depth
      (apply proc args)))

  ; Temporarily override the default apply behavior to use our traced version
  (parameterize ([current-apply traced-call])
    (thunk) ; Run the target thunk
    max-depth)) ; Return the recorded maximum stack depth

How this works:

  • Continuation Mark Key: We create a unique key (depth-key) to store the current stack depth in the continuation mark set. This ensures our tracking doesn't interfere with other system-level marks.
  • Traced Apply: The traced-call function replaces the default apply behavior. Every time a procedure is called, it increments the parent context's depth to get the current depth, updates the maximum depth if needed, sets the new depth mark, then executes the original procedure.
  • Parameterize: Using parameterize lets us safely override current-apply only for the duration of running the thunk—no global changes, so other code isn't affected.

Testing with your factorial examples:

Let's verify the function behaves as expected:

; Recursive factorial (should have a stack depth ~101 for n=100)
(define (fac n)
  (if (<= n 1)
      1
      (* n (fac (- n 1)))))

(call-stack-max-depth (lambda () (fac 100))) ; Returns ~101 (varies slightly by implementation)

; Iterative/tail-recursive factorial (constant small stack depth)
(define (fac-iter n)
  (define (iter acc count)
    (if (<= count 0)
        acc
        (iter (* acc count) (- count 1))))
  (iter 1 n))

(call-stack-max-depth (lambda () (fac-iter 100))) ; Returns a small constant (e.g., 3 or 4)

Notes for other Scheme implementations:

If you're not using Racket, adjust the procedure call interception step to match your Scheme's capabilities:

  • Chez Scheme uses $apply instead of current-apply
  • Some variants may require make-procedure-wrapper or other extension hooks
  • The core logic of tracking depth via continuation marks stays consistent—you just need to hook into your implementation's procedure call mechanism.

内容的提问来源于stack exchange,提问作者TomatoFarmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:17:33