newLISP Fan Club

Forum => Whither newLISP? => Topic started by: pda on April 03, 2026, 05:57:13 AM

Title: Parametrized access to context
Post by: pda on April 03, 2026, 05:57:13 AM

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:

(define CTX:s 7)
(print CTX:s)

This way I can create any kind of symbol, including functions:

(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:

(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 :

(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:

(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:

(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:

(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:
   
(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:

(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:

(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:

(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:

(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:


(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:

(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):

(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:

(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:

(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:

(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:

(define (mk-ctx c f b) (define c:f b) c)

Now I can define any  function in the context:

(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 :

(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?