Archive for the ‘context’ Tag
newLISP の context について考える。。。その2
;; pass data by context reference
(set 'Mydb:data (sequence 1 100000))
(define (change-db obj idx value)
(setf (obj:data idx) value))
(change-db Mydb 1234 "abcdefg")
(nth 1234 Mydb:data) → "abcdefg"
; or
(Mydb:data 1234) → "abcdefg"
これは、マニュアル“Passing data by reference”項の最後の例題です。
私は、これで何故、関数change-db が動くのか、判りませんでした。
ちなみに、macro.lsp を使って、macro を定義している場合、関数change-db は定義できません。定義できないだけで、動作はします(笑)。つまり、関数change-db を定義してから、macro を定義しても、関数change-db は動作するということです。v10.2.15 以降であれば、macro を定義した後でも、関数change-db を定義できます。詳しくは、こちらでもどうぞ。
閑話休題。関数change-db の引数 obj は、コンテキスト名です。
でも、関数change-db 内で使われている変数は、obj:data 、コンテキスト名が先付されたシンボルのように見えます。
そして、関数の動作からすると、obj:data のうち、obj は、変数で data は、変数ではなく、シンボル名です。
newLISPer には、当たり前?
さて、マニュアルで : の項を見ると、
演算子として使う時、コロン : は、オブジェクト・リストのコンテキスト名からくるコンテキスト・シンボルとコロンに続くシンボルを組み立てます。
When used as an operator, the colon : constructs a context symbol from the context name in the object list and the symbol following the colon.
とあり、さらに、
コロンとそれに続くシンボルの間は、スペースを要求されません。
No space is required between the colon and the symbol following it.
No space is required がクセモノでした。要求されないけれど、在ってもよいようです。
その例が、やはり、マニュアルにありました。
(:area myrect) → 200 ; same as (: area myrect)
(:area mycircle) → 314.1592654 ; same as (: area mycircle)
なるほどね。関数change-db は、
(define (change-db obj idx value)
(setf (obj: data idx) value))
とも書けるのですね。
: の前は、必ずコンテキストなので評価されます。コンテキスト名そのものなら、コンテキストは、それ自身に評価され、コンテキスト名が現れます。変数なら、ここでは、引数に割り当てられたコンテキスト(つまり、コンテキスト名)が入るわけです。
一方、: の後は、シンボルです。変数にすると、変数名シンボルがそのまま、使われます。
だから、<a href="“>例題のあったマニュアル項にあるように、
不利な点は、呼び出す関数が使われるシンボルを知っていなければならいないことです:
The disadvantage is that the calling function must have knowledge about the symbol being used:
と、なる訳です。
だから、マニュアルは読んでおかないとね(笑)。
以上、如何でしょうか?
newLISP の context について考える
突然ですが、次のコードの間違いはどこでしょう?
(context 'FOO)
(set 'ABC 123)
(context MAIN)
(context 'ABC)
(set 'FOO 456)
(context 'MAIN)
答えの前に、正しいコードを
(context 'FOO)
(set 'ABC 123)
(context MAIN)
(context 'ABC)
(set 'FOO:ABC 456)
(context 'MAIN)
これは、newLISP のマニュアルにある
コンテキストを生成あるいはロードするシーケンスは、予期しない結果につながることがあります。
The sequence in which contexts are created or loaded can lead to unexpected results.
に続く例題です。
予期しないと書いてありますが、マニュアル の Symbol creation in contexts に、
コード翻訳中に、見知らぬシンボルに出会うと、その定義の検索が現在のコンテキスト内で始まります。それに失敗すると、検索は、MAIN 内で組込関数、コンテキスト、グローバル変数について続けられます。定義が見つからなければ、シンボルは、現在のコンテキスト内にローカルに生成されます。
When an unknown symbol is encountered during code translation, a search for its definition begins inside the current context. Failing that, the search continues inside MAIN for a built-in function, context, or global symbol. If no definition is found, the symbol is created locally inside the current context.
とあります。だから、
ABC のロードの時は、FOO がグローバル・プロテクト・シンボルとして、すでに存在していて、正常にプロテクトのフラグがセットされています。
When ABC loads, FOO already exists as a global protected symbol and will be correctly flagged as protected.
となるわけです。
だから、マニュアルは読んでおかないとね(笑)。
以上、如何でしょうか?