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

SICP练习1.3:Racket用when实现的函数为何返回#<void>

问题根因

代码返回#<void>是两个Racket基础语义理解偏差导致的:

  • Racket过程的返回值固定为过程体内最后一个求值完成的表达式的结果,中间表达式算出的值如果没有被绑定、也没有成为最后一个返回表达式,会被直接丢弃。
  • when是面向副作用操作(打印、变量赋值等)设计的语法,不会在条件命中时中断后续代码执行:条件成立时它会执行内部语句并返回内部最后一个语句的值,条件不成立时直接返回#<void>,没有任何分支跳转、提前返回的效果。

拿你测试用的(procsq 1 2 3)举例,执行流是:

  1. 第一个when条件成立,算出两个大数的平方和13,但值直接被丢弃,继续执行后续代码
  2. 第二个when条件也成立,重复计算一次13,同样丢弃,继续向下
  3. 剩下四个when的判断条件全部不成立,每个都返回#<void>
  4. 整个过程最后执行的是第六个when,返回#<void>,自然最终输出就是void
    而(procsq 3 2 1)能返回正确结果纯属于巧合——这个入参刚好命中第六个when,最后一个表达式的计算结果是正确的平方和,才碰巧返回了预期值。
修正方法

需要根据条件返回值的场景不要用when,替换为专门做值分支的cond即可。另外你原来的6个条件判断有大量重复,其实逻辑可以简化:只要找到三个数里最小的那个,剩下两个数算平方和就行,不需要枚举所有排列:

#!/usr/bin/env racket
#lang racket/base

(define (square x) (* x x))
(define (procsq a b c)
  (cond
    [(and (<= a b) (<= a c)) (+ (square b) (square c))]
    [(and (<= b a) (<= b c)) (+ (square a) (square c))]
    [else (+ (square a) (square b))]))

(displayln (procsq 1 2 3))  ; 输出13
(displayln (procsq 3 2 1))  ; 输出13
(displayln (procsq 3 1 2))  ; 输出13

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:45:33