I'd like to know if there's some way to access to context symbols in a parametrized way, that is, passing the context or the full qualified path to context symbols.
Let's clarify the question with some examples.
If I want to create a symbol in a context (or access to it) I can just prefix the symbol with the context:
Code Select
(define CTX:s 7)
(print CTX:s)
This way I can create any kind of symbol, including functions:
Code Select
(define CTX:f (lambda (a) (+ 1 a)))
The problem appears with free symbols inside the function, if I use a free symbol its is resolving depending on the context prefix and assuming MAIN if no prefix:
Code Select
(define CTX:g (lambda (a) (+ n a)))
What n inside CTX:g referes to? it refers to context MAIN since it is not prefixed at all :
Code Select
(setq CTX:n 66)
(setq n 1)
(CTX:g 2) ---> 3
so, what if I want n to refer to context CTX inside CTX:g function? I have to prefix it with CTX symbol:
Code Select
(define CTX:g (lambda (a) (+ CTX:n a)))
(CTX:g 2) ---> 68
The problem arise when I don't know the context, i.e. I don't know the context symbol so I cannot use a context prefix , let's say I have a function g in several contexts and I want to execute the right one depending on the context.
Fortunately newlisp allow to pass a variable as a context prefix and doing so it uses the variable value as prefix:
Code Select
(define C:n 1)
(define C:g (lambda (a) (+ C:n a)))
(setq cn CTX)
(cn:g 2) -> 68
(setq cn C)
(cn:g 2) -> 3
And so you can define the same symbols in differente contexts provided you set previously the context, i.e. the prefix:
Code Select
(setq cn C)
(define cn:X 8)
(define cn:X2 (lambda () (* cn:X 2)))
(cn:X2) -> 16
(setq cn CTX)
(define cn:X 1)
(define cn:X2 (lambda () (* cn:X 2)))
(cn:X2) -> 2
What to do in order to avoid setting the prefix previously each time, well you can pass it to the function:
Code Select
(define X2 (lambda (cn) (* cn:X 2))
(X2 C) -> 16
(X2 CTX) -> 2
Pretty good, know I have a general function in context MAIN that use symbols in context passed as parameter.
But I want to have the function defined in the context I'm passing as parameter, not in MAIN
The obvious solution is to create a function with a context as parameter, that creates a contex with th X2 function inside:
Code Select
(define (mk-ctx c) (define c:X2 (lambda (cn) (* cn:X 2))))
Now if I want the function created in context OO I call mk-ctx with that context:
Code Select
(context 'OO)
(context MAIN)
(mk-ctx OO)
(OO:X2 C) ---> 16
(OO:X2 CTX) ---> 2
Pretty good, but I still have to pass the evaluation context to X2, I want X2 to use the context in which it is defined, here OO, so easy:
Code Select
(define (mk-ctx c) (define c:X2 (lambda () (* c:X 2))))
But this fails, because now c:X in lambda's body uses a free variable c which is evaluated in context MAIN (where it can even be unbind)
This is better seen with this alternative definition of mk-ctx showing the value of c symbol inside the lambda:
Code Select
(define (mk-ctx c) (define c:X2 (lambda () (print c) (* c:X 2))))
if I set c in MAIN context to be 9382, I can see the problem:
Code Select
(setq OO:X 10)
(setq c 9382)
(mk-ctx OO)
(OO:X2)
9382
ERR: context expected in function * : MAIN:c
called from user function OO:(X2)
If I set c to a valid context in MAIN, everything is ok:
Code Select
(setq c OO)
(mk-ctx OO)
(OO:X2) ---> 20
OO
So the problem is how to use in the body of lambda X2 a parametrized context WITHOUT passing it as parameter,
that is, I want that body of lambda evaluates the free variables in the context it is defined and not in main (or a passed prefix):
Code Select
(define (mk-ctx c) (define c:X2 (lambda () (let (cn (context)) (* cn:X 2)))) c)
Now I can create a "autoreferenced" X2 function, and also mk-ctx returns the context in which it is defined:
Code Select
(setq the-ctx (mk-ctx OO))
(the-ctx:X2) --> 20
That is so good, but I have to take care of all that context stuff inside the body, it would be better if I can forget about context machinery
What I want is something like this:
Code Select
(define (mk-ctx c) (define c:X2 (lambda () (* (my 'X) 2))) c)
But the problem is to define that my funcion, it's tempted to define it as:
Code Select
(define (my v) (eval (sym v (context))))
But again the problem is the evaluation of (my 'X) is done in context MAIN and so (my v) returns the value of symbol V in MAIN, not in context of X2
Of course you can solve it by passing the context to function my, but this get us back to the begining
Another problem is to define any function in the context not just X2, but this is easy just changing the mk-ctx to:
Code Select
(define (mk-ctx c f b) (define c:f b) c)
Now I can define any function in the context:
Code Select
(setq the-ctx (mk-ctx OO 'f (lambda () (let (cn (context)) (* cn:X 2))) ))
(the-ctx:f) --> 20
(setq the-ctx (mk-ctx OO 'f (lambda () 1) ))
(the-ctx:f) --> 1
So the problem is to define a proper my function in order to skip context machinery when defining the function body,
that is function "my" has to return the value of symbol passed in the current context when invoking the funcion f (in the previous example)
which is the contex in which function f is define (OO in the previous example)
ideally this my function not only have to get the current value of the symbol in context but also should be able to set it using setf :
Code Select
(my 'v) ---> returns the value of symbol v in context defined using mk-ctx (current context, OO, when invoking the function f)
(setf (my 'v) 4) ---> set the value of symbol v to 4 in context defined using mk-ctx
Any idea to define this my function or a schema to resolve symbols in current schema avoid to deal with it inside function body?