スクリプト言語間における「lexical closure」の違い─PostScript 版

ネタ元は スクリプト言語間における「lexical closure」の違い、それともプログラムの違い? - karasuyamatenguの日記。(スクリプト言語間における「lexical closure」の違い ― Squeak Smalltalkの場合 - Smalltalkのtは小文字です経由)PostScript なら、数行入れ替えるだけで Perl 風にも Python 風にもなります。
PostScript は動的スコープなので、まず lexical closure を自作する必要があります。Perl 風、 Python 風共通です。

%!PS
/closure{
    [
        countdictstack array dictstack
        [
            exch{
                dup systemdict eq{
                    cleartomark mark systemdict
                }if
            }forall
        ]{ begin }/forall cvx
        counttomark 2 add -1 roll
        /stopped cvx
        4 index length{ end }/repeat cvx
        { stop }/if cvx
    ]cvx
}def

文字列結合オペレータも作っておきます。

/strcat{
    3 dict begin
        /str2 exch def
        /str1 exch def
        /buf str1 length str2 length add string def
        str1 buf copy pop
        buf str1 length str2 putinterval
        buf
    end
}def

for ループの中で dict begin ... end すると、繰り返し毎に別のスコープが作られ、Perl 風になります。

/closures 5 array def
0 1 4{
2 dict begin
    /i exch def
    /localvar (foo) i ( ) cvs strcat def
    closures i { localvar }closure put
end
}for
closures{
    exec =
}forall
$ gsnd -q -dBATCH colv.ps
foo0
foo1
foo2
foo3
foo4

for ループの外で dict begin ... end すると、変数のスコープがループ中で共通になり、Python 風に振る舞います。

/closures 5 array def
2 dict begin
0 1 4{
    /i exch def
    /localvar (foo) i ( ) cvs strcat def
    closures i { localvar }closure put
}for
end
closures{
    exec =
}forall
$ gsnd -q -dBATCH colv.ps
foo4
foo4
foo4
foo4
foo4