作用域为调用堆栈的变量

问题描述 投票:0回答:2

前提:这不是一个特定于特定语言的问题,而是一个通用的编程问题,以了解是否有某种语言有这种结构,如果没有,原因是什么,因为它看起来很有用?

问题:什么是允许在调用堆栈级别声明变量的构造,以便只有特定调用堆栈内的函数才能访问它?我将尝试使用 javascript 突出显示这一点:

async function main() {
  await Promise.all([foo(), bar()])
}

async function foo() {
   await setTimeout(100);
   setting (const a = 1) {  // <===== set here
      await setTimeout(100);
      await baz();
   }
}

async function bar() {
   await setTimeout(100);
   setting (const a = 2) {  // <===== set here
      await setTimeout(100);
      await baz();
   }
}

async function baz() {
   const a = STACK_CONTEXT.a; // <===== used here
   console.log(a)
}

虽然这看起来像一个全局的,但该函数仅在正在执行的特定调用堆栈下可用。我正在使用假设关键字

setting
来强调这一点。在该特定示例中,有 2 个
bar->baz()
调用堆栈并行运行,其局部上下文变量“a”不同。这会比通过管道传递变量更好(在 bar 和 baz 之间有很多函数的情况下)并且会比使用 threadLocal 或全局变量之类的东西有更好的属性,原因很明显。我还没有遇到过具有此功能的编程语言,但我想知道为什么,因为这在很多情况下都非常有用。

design-patterns scope global-variables language-agnostic
2个回答
1
投票

Java 20 添加了一个名为 Scoped Values 的孵化特性,它与 OP 示例有些相似,不同之处在于此类变量是不可变的(为了性能和安全性)。

JEP 的最后一段提到了一些历史背景。

Scoped values 的灵感来自于许多 Lisp 方言为动态范围自由变量提供支持的方式;特别是,此类变量在深度绑定、多线程运行时(如 Interlisp-D)中的行为方式。作用域值通过添加类型安全、不变性、封装以及线程内和线程间的高效访问来改进 Lisp 的自由变量。

所以这个想法有一些先例。


0
投票

这个想法被称为“动态作用域”,与“词法作用域”或“静态作用域”形成对比,这是当今几乎所有编程语言都使用的。

参见:https://www.geeksforgeeks.org/static-and-dynamic-scoping/

曾经有过关于哪个更好的争论,你可以在一些古老的语言中找到动态作用域——早期的 LISP、SNOBOL、APL 等

不过,辩论现在以另一种方式解决了。词法作用域让你更容易推断你的程序是如何工作的。

© www.soinside.com 2019 - 2024. All rights reserved.