返回资讯中心
外部精选
软件工程
#开发者实时流

Adobe 介绍 Adam 声明式编程语言与 Source Libraries

来源标题:Adobe Source Libraries Overview (2007)

Adobe 在 2007 年概述了 Source Libraries,其中包含声明式语言 Adam,可自动追踪数据依赖并更新输出。示例语句 unlink flatness 展示了当 path 变化时自动重算 flatness 的机制。该语言还支持不变量(invariant)及异常处理。

Hacker News 最新GaryBluto2026/11/12 · 今天22 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

sheet clipping_path output: result <== { path: path, flatness: flatness }; interface: unlink flatness : 0.0 <== (path == empty) ? 0.0 : flatness; path : 1; [Open Issue 1] invariant 是类型为 Boolean 的输出单元。可以将 handler 附加到 invariant 上,当 invariant 求值为 false 时就会调用该 handler。该 handler 会收到 invariant 的名称,以及该 invariant 所依赖的输入单元列表。默认 handler 会抛出 adam::invariant_violation() 类型的异常。 要理解 Adam 如何实现如此强大的表达力,请看下面这条语句: unlink flatness : 0.0 <== (path == empty) ? 0.0 : flatness; 如果作为 C++ 代码,这条语句仅仅意味着: 执行时,求值 path 的输出,并据此将 0.0 或 flatness 的输入赋值给 flatness 的输出。 而作为 Adam 语句,它隐含了以下含义: 每当 path 的输出被修改时,就将 0.0 或 flatness 的输入赋值给 flatness 的输出。 如果 path 的输出不等于 empty,并且 flatness 的输入被修改,则更新 flatness 的输出。 此外,还可以进行以下查询: 给定当前状态,哪些输入单元对输出单元有影响? 给定当前状态,flatness 的输出依赖于哪些输入值? 在 flatness 的输出当前所依赖的值中,哪一个最近被更新过? 最后,还可以将动作关联到上述任何语句的结果上,例如: 当 flatness 的输出被修改时,更新显示。 根据 flatness 的输入是否影响任何输出值,来设置与 flatness 输入关联的编辑文本框的启用状态,并在该状态变化时更新它。 一个 sheet 中相互关联的语句越多,Adam 相对于传统事件模型的有效表达力就越强。上面这一条语句替代了 Photoshop 中一个 57 行(按分号计为 15 条语句)的函数。 sheet 的实例是一个写时复制(copy-on-write)对象,以支持事务性操作。这在实现撤销时很有用,也可用于实现 reset 和 revert 以响应 invariant 违例。[注:如果认为该特性有用,写时复制也可用于在对话框中实现多重撤销。] [Open issue 2] sheet 上的输入单元可以从字典加载,输出单元也可以作为字典提取出来。这一功能可用于实现加载、保存、“收藏”和预设,同时也是将 sheet 绑定到应用程序的一种有用方式。 修改 sheet 上的输入单元会触发重新计算(在设置复杂状态时可以抑制该行为)。任何依赖于已更改值的单元都会被重新计算。如果某个 invariant 单元在重新计算时返回 false,就会抛出异常,其中包含被违反的 invariant 的名称,以及(基于 sheet 当前状态)触发该 invariant 的任何单元。[注:提供该 invariant 所依赖的所有输入单元的列表也可能有用。引入“弱 invariant”的概念也可能有用,它会中止传播并使进一步依赖的输出单元进入“无效”状态。这需要更多实践经验才能确定实际需要什么。] 逻辑单元用于中间计算,其状态既不能从 sheet 外部读取,也不能从外部设置。 接口单元同时用于输入和输出。通常,接口单元的输入值和输出值彼此保持同步。可以在接口单元前加上“unlink”关键字,以阻止输出值反向传播到输入值。 [Open Issue 3] [Open Issue 4] 有时,接口依赖于“最近发生了什么”这一概念。例如,调整大小对话框中的显示“宽度”的编辑文本框,可能显示用户输入到宽度中的内容,也可能显示用户更改高度时计算出的内容。为支持这一概念,Adam 在 sheet 上维护一个代数计数(generation count),每次重新计算时递增。当单元因重新计算而被修改时,会打上该代数计数的标记。 Virtual Machine Virtual Machine 是一个用于求值表达式的简单栈式机。表达式会被归约为一个代码序列,其中每个代码要么表示一个值,要么表示一个操作符。值被压入栈,操作符作用于栈顶的值,并将结果压入栈。通过重写操作符,可以从该序列重建中缀表达式。这对往返编辑很有用。从概念上讲,AVM 与 FORTH 或 PostScript 语言非常相似,并支持将代码序列作为值压入栈。 在 Adam 中,依赖关系是通过在语句执行期间监视单元查找来跟踪的。查找会推迟到实际执行时才进行。短路布尔运算符和条件运算符以表达式为参数,因此哪些单元被标记为依赖于给定表达式,取决于 sheet 的当前状态。 [Open Issue 5] 可能希望将对函数参数的求值推迟到函数请求求值时进行。尽管这会使作用域规则复杂化,但它允许编写有条件地使用其参数的函数,从而能更好地跟踪依赖关系。 Binding Eve2 的一个关键特性是能够将 HI 元素绑定到 Adam sheet 中的单元。绑定通过各种 bind 属性完成。bind 属性的值是某个 Adam 单元或多个 Adam 单元的名称。例如: check_box(name: "Check this", bind: @check_this); name 也可用于将其他属性绑定到 sheet。例如,如果上述复选框的名称是由用户设置的,则可以写成: check_box(name: @user_name, bind: @check_this); Guides

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →