context-awareness: function knows about the current context

Started by cormullion, November 11, 2010, 10:11:26 AM

Previous topic - Next topic

cormullion

I've forgotten whether it's possible for a function to find out in which context it's being called from.




(context MAIN)
(define (f)
   (println "hi there I'm in context " (context)))
   
(global 'f)
(f)
hi there I'm in context MAIN

(context 'Fred)
(f)
hi there I'm in context MAIN


Each returns MAIN, but is it possible to write the f  function so that it returns 'Fred when it's in Fred?

m i c h a e l

Hi cormullion!



Defining f as global hides the fact that f is still defined in MAIN. You can see this more clearly in the following:


> (define (f) (context))
(lambda () (context))
> (f)
MAIN
> (context 'Fred)
Fred
Fred> (MAIN:f)
MAIN
Fred> _


In order to refer to f without the global definition, we must prefix it with MAIN within contexts, which shows why context is returning MAIN.



In answer to your question, yes, it is possible, by using macro:


> (module "macro.lsp")
MAIN
> (macro (F) (context))
(lambda-macro () (expand '(context)))
> (F)
MAIN
> (context 'Fred)
Fred
Fred> (MAIN:F)
Fred
Fred> (context MAIN)
MAIN
> (global 'F)
F
> (context Fred)
Fred
Fred> (F)
Fred
Fred> _


m i c h a e l

cormullion

Thanks. This looks like it will do the trick. I'd forgotten about these rewrite macros.

cormullion

It's going well, thanks to your help, michael. One last piece of the puzzle - how to get a call to a newLISP function divert to calling the macro. I know you can do this with regular functions, but can you do it with these rewrite macros?


(module "macro.lsp")
(macro (my-sys-info)
    (let ((meaning (list {Number of Lisp cells}
                {Maximum number of Lisp cells constant}
                {Number of symbols}
                {Evaluation/recursion level}
                {Environment stack level}
                {Maximum call stack constant}
                {Pid of the parent process or 0}
                {Pid of running newLISP process}
                {Version number as an integer constant}
                {Operating system constant}))
          (value   (sys-info)))
    (transpose (list meaning value))))

(global 'my-sys-info)
(constant (global 'sys-info) my-sys-info)
(context 'Fred)
(set 's 3)
(println s)

s

(my-sys-info)
; it works:
(("Number of Lisp cells" 704)
 ("Maximum number of Lisp cells constant" 268435456)
 ("Number of symbols" 404)
 ("Evaluation/recursion level" 3)
 ("Environment stack level" 0)
 ("Maximum call stack constant" 2048)
 ("Pid of the parent process or 0" 0)
 ("Pid of running newLISP process" 37682)
 ("Version number as an integer constant" 10208)
 ("Operating system constant" 131))

(sys-info)
; but this doesn't:
(let ((MAIN:meaning (list "Number of Lisp cells" "Maximum number of Lisp cells constant"  ....



Not sure, am I asking for the impossible?

m i c h a e l

I'm not sure if it's possible either, unfortunately. I noticed something that could be a problem, though: the use of sys-info within my-sys-info after you redefine it to be my-sys-info.



It's probably better to think of these kinds of macros as rewrite macros. I use them mostly for writing DSLs. They're well-suited for that.



Good luck on solving your problem, cormullion!



m i c h a e l

cormullion

Yes, you're probably right. I think my mental model is wrong. Perhaps I've switched to writing Forth without realising it. ;)

m i c h a e l

I like the mental state programming in Forth puts you in. Focusing on thinking about the problem first, then breaking it down into stack shuffling operations. This can be a deeply rewarding mental exercise. Chuck Moore is a brilliant person.



I gave up on Forth after I realized the language seemed to be forcing me to do the stack operations I want my programming language to do for me! :-)



m i c h a e l