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

Scheme中为何无法如此使用values?有无不依赖call-with-values的多值绑定方法?

报错核心原因

Scheme对表达式返回值的接收有严格的上下文规则:

  • 普通函数调用的实参位、变量定义/赋值的右值这类场景属于单值上下文,仅允许表达式返回0或1个值,一旦返回多个值就会直接抛出运行时错误。
  • 只有专门为多值设计的语法位置(比如多值绑定结构的接收位、call-with-values的消费者函数入口)属于多值上下文,才能正确接收values返回的多个结果。

你写的(avg (delist '(1 2 3)))中,(delist '(1 2 3))只是avg的第一个实参表达式,这个位置是单值上下文,根本不会把返回的1、2、3三个值当成avg的三个参数传入——运行时只会尝试取返回的第一个值作为avg的第一个实参,多余的返回值会直接触发异常,和显式写(avg 1 2 3)传三个离散参数的调用逻辑完全不同。很多刚接触Scheme多值返回的开发者都会误以为values会自动把多值展开成多个实参,实际上从R5RS到最新的R7RS标准都没有定义这种隐式行为,单值上下文下传入多值本身就是非法操作。

不使用call-with-values的实现方式

有两种成熟方案,都不需要显式调用call-with-values:

  • 最简洁的方案:完全不需要通过values中转。你的核心需求是把列表元素作为离散参数传入可变参数函数avg,这本来就是apply的原生能力,连自定义的delist函数都不需要:
(apply avg '(1 2 3)) ;; 直接返回2,和(avg 1 2 3)运行效果完全一致
  • 如果确实需要先接收values返回的固定个数多值,可以用Scheme标准的多值绑定语法let-values先把多值绑定到独立变量,再传入目标函数:
;; 适配固定3个返回值的场景
(let-values ([(a b c) (delist '(1 2 3))])
  (avg a b c)) ;; 正常返回2

如果是变长多值的场景,没有比直接用apply处理原列表更简洁的方案,刻意绕路走values多值返回反而会增加不必要的逻辑复杂度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:45:50