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

动态作用域下SML代码求值疑问求助:结果推导与local块困惑

动态作用域下SML代码的求值推导

代码回顾

val (x,t) = (13,50);

fun zod x = (x+t);

local 
  val t = zod (x+t) 
in 
  fun foo x = zod (x+t) 
end;

val t = ~40;

fun bar x = 
  let 
    val t = zod (x+t) 
  in 
    foo (x+t) 
  end;

val t = 60;

foo(x+t);
bar(x+t);

核心规则:动态作用域

动态作用域下,变量的取值由调用时的当前栈环境决定,而非函数定义时的环境——函数不会捕获定义时的变量绑定,只会在执行时查找当前调用栈中最近的变量绑定。


分步求值过程

初始环境与函数定义

  1. 执行val (x,t) = (13,50); → 全局绑定:x=13,t=50。
  2. 定义fun zod x = x + t; → 函数zod接收参数x,内部引用的t为调用时栈中的最近t绑定。
  3. 处理local块:
    • 计算val t = zod(x+t):此时环境为全局x=13、t=50,x+t=13+50=63。调用zod(63)时,zod内的t取全局的50,返回63+50=113。因此local块内的t被绑定为113,但该绑定仅在foo的定义阶段有效,foo不会捕获这个t(动态作用域特性)。
    • 定义fun foo x = zod(x + t) → foo接收参数x,内部的t将在调用时查找当前栈的t。
  4. 执行val t = ~40; → 全局t被覆盖为-40。
  5. 定义fun bar x = let val t = zod(x+t) in foo(x+t) end; → bar内部的let块会在调用时计算t,foo的调用将使用当时的栈环境。
  6. 执行val t = 60; → 全局t被覆盖为60。

第一个调用:foo(x+t)

  1. 计算参数:x+t=13+60=73,调用foo(73)。
  2. 进入foo函数,参数x=73,函数体为zod(x + t):
    • 当前栈环境为全局环境,t=60,因此x+t=73+60=133。
    • 调用zod(133),zod内的t取全局的60,返回133+60=193。
      最终结果:193

第二个调用:bar(x+t)

  1. 计算参数:x+t=13+60=73,调用bar(73)。
  2. 进入bar函数,参数x=73,执行let块:
    • 计算val t = zod(x+t):当前栈环境为全局t=60,x+t=73+60=133。调用zod(133)返回133+60=193,因此let块内的t被绑定为193。
    • 执行foo(x+t):x=73,t=193,因此x+t=73+193=266,调用foo(266)。
  3. 进入foo函数,参数x=266,函数体为zod(x + t):
    • 当前栈环境为bar的let块,t=193,因此x+t=266+193=459。
    • 调用zod(459),zod内的t取当前栈的193,返回459+193=652。
      最终结果:652

你的误区解析

  1. 错误认为local块的t会在调用foo时生效:动态作用域下,函数不会捕获定义时的环境变量。local块的t仅在foo的定义阶段存在,foo执行时会直接查找当前调用栈的t(这里是全局的60),而非local块的113。
  2. 混淆静态/动态作用域:静态作用域下函数会捕获定义时的环境,而动态作用域完全依赖调用时的栈环境,这是你推导结果错误的核心原因。

local块在动态作用域下的行为

local块的声明部分(local内的val)会在程序执行到该块时立即求值,但in部分定义的函数不会捕获local内的变量绑定——因为动态作用域的函数不携带定义环境,变量取值完全由调用时的栈决定。因此local块在这里仅用于定义foo函数,foo内部的t与local块的t无关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:35:02