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

PostScript字典语义疑问:def与键值对定义的差异解析

PostScript字典中def操作符与直接键值对定义的差异解析

问题背景

在PostScript字典中定义条目时,使用def操作符和直接书写键值对的行为存在明显差异,出现了看似矛盾的现象:

  • 用def在字典/d中定义/a,直接写键值对定义/b;
  • 用===打印/d时,仅能看到/b;
  • 将/d加载到字典栈后,可访问并打印/a和/b;
  • 用get访问/d的/b能得到对应值,但访问/a时触发未定义错误。

def操作符官方定义

def - 将键与值关联到当前字典(即字典栈顶部的字典)。若键已存在则替换值,否则创建新条目存储值。——《PostScript语言参考手册》第3版第568页

代码示例

/d <<
        /a 22 def
        /b 33 
    >> def % Define dictionary 'd'

d ===      % Print out contents of d; Prints /b 33 but no /a

d begin    % Push d onto the dictionary stack
a =        % Prints value of d/a '22'
b =        % Prints value of d/b '33'
end        % Pop d off of the dictionary stack

d /b get =  % Prints value of d/b '33'
d /a get =  % Error /undefine. Cannot find /a in d

Ghostscript执行输出

$ gs -q -dALLOWPSTRANSPARENCY -dBATCH -dNOPAUSE -dQUIET -dNOSAFER     -sDEVICE=pdfwrite  -o tmp_test.pdf tmp_test.ps
<< /b 33 >>
22
33
33
Error: /undefined in --get--
Operand stack:
   --dict:1/1(L)--   a
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   1990   1   3   %oparray_pop   1989   1   3   %oparray_pop   1977   1   3   %oparray_pop   1833   1   3   %oparray_pop   --nostringval--   %errorexec_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--
Dictionary stack:
   --dict:795/1123(ro)(G)--   --dict:0/20(G)--   --dict:77/200(L)--
Current allocation mode is local
Current file position is 317
GPL Ghostscript 10.01.2: Unrecoverable error, exit code 1
$

核心原因解析

你之前的误解在于:在字典字面量<< ... >>内部执行def时,当前字典并不是正在构建的/d,而是字典栈顶部的用户字典。具体执行流程如下:

  1. 执行/d << ... >> def时,PostScript解释器先进入字典字面量构建模式,但字面量内部的/a 22 def是独立的操作——def会将/a和22绑定到当前字典栈顶部的字典(此时是用户字典,而非正在创建的/d)。
  2. 字面量中的/b 33才是被添加到正在构建的/d字典中的条目,所以d ===仅显示/b 33。
  3. 当执行d begin将/d压入字典栈后,访问a时,解释器会遍历字典栈:先查找/d(无/a),接着查找栈中的用户字典,找到了之前用def存入的/a,因此能打印22——这个/a不属于/d,而是属于用户字典。
  4. d /a get是直接从/d字典内部查找/a,但/d中从未存入过这个条目,因此触发未定义错误。

两种定义方式的本质区别

  • 直接键值对(/key value):仅在字典字面量<< ... >>构建时生效,将键值对添加到正在创建的新字典中。
  • def操作符:不受字面量构建影响,始终将键值对添加到当前字典栈顶部的字典(若要往目标字典存入条目,需先将该字典压入字典栈,再执行def)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:58:24