creating context inside macro

Started by frontera000, August 28, 2006, 09:35:57 AM

Previous topic - Next topic

frontera000

This may be a dumb thing to do:



(define-macro (foo1 ctx1 arg1)
  (context  ctx1)
  (define (foo1 arg1)
    (setq var1 arg1)))

(foo1 fooctx1 "hello1")


And it crashes newLISP.exe.


Quote
> (debug (foo1 fooctxt1 "hello1"))



-----



(define-macro (foo1 ctx1 arg1)

  #(context ctx1)#

  (define (foo1 arg1)

   (setq var1 arg1)))





[-> 3 ] s|tep n|ext c|ont q|uit > ctx1

fooctxt1



[-> 3 ] s|tep n|ext c|ont q|uit > s



-----



(define-macro (MAIN:foo1 MAIN:ctx1 MAIN:arg1)

  #(context MAIN:ctx1)#

  (define (MAIN:foo1 MAIN:arg1)

   (setq MAIN:var1 MAIN:arg1)))





RESULT: fooctxt1



[<3> s



-----



(define-macro (MAIN:foo1 MAIN:ctx1 MAIN:arg1)

  (context MAIN:ctx1)

  #(define (MAIN:foo1 MAIN:arg1)

   (setq MAIN:var1 MAIN:arg1))#)





[-> 3 fooctxt1] s|tep n|ext c|ont q|uit > s

***newLISP  Crashes here *****

C:Documents and SettingsOwner>






Another thing is that I wanted to create foo1 in foo1 context.  But I guess while running the macro in MAIN context, creating context inside the running macro and defining new function does not make the new ones go into the newly created context -- they instead go to MAIN.  But still that crashes, so I don't know.



But the following seems to work a little better:



(define-macro (foo1 ctx1 arg1)
  (setq FOO1 (context  ctx1))
  (define (FOO1:foo1 FOO1:arg1)
    (setq FOO1:var1 FOO1:arg1)))


Basically I want to be able to create a context and a function and call that function in one expression.

Lutz

#1
Modifying a function while running it, will always crash the system.



Lutz

frontera000

#2
Thanks.



I realize that it has turned out to be that way - modifying the function while running it. But it was due to my lack of understanding. I was intending to do the same kind of thing as I do from the interpreter prompt.



(context 'FOO1)

(define (foo1) (setq var1 123))



This works from the repl.



So I thought I could do the same inside a macro.



(define-macro (make-foo1)

   (context 'FOO1)

    (define (foo1) (setq var1 123)))



So when I run what I expect (perhaps wrongly) is that foo1 created will be inside FOO1 context.  But foo1 gets created inside MAIN.



Is there a way to create a function and variables in a new context from inside another function or macro?  I would like to be able to do that and eval the function on the fly.



I can't figure out how to do that in newLISP.

Lutz

#3
yes there is a way, but let me first explain what is going on here:


(define-macro (make-foo1)
   (context 'FOO1)
   (define (foo1) (setq var1 123)))


The context statement switches the context during runtime  executing 'make-foo1', but at this time all other symbols in 'make-foo1' are already created as symbols in MAIN when reading the source from the program file. So at this time the context switch doesn't do anything anymore. newLISP reads a toplevel expression then evaluates it then reads the next toplevel expressin etc. While rading all symbols are created for the current context swithced to with a top level context statement.



'context' changes the context only for subsequent source code translation. When switching the context during runtime of 'make-foo1' it would only change the subsequent behaviour of an 'eval-string' or a 'sym' statement (if they don't have a context specified).



To create a function for a different context and that context at the same time you can use the following function described here:

http://newlisp.org/downloads/newlisp_manual.html#lexical_scoping">http://newlisp.org/downloads/newlisp_ma ... al_scoping">http://newlisp.org/downloads/newlisp_manual.html#lexical_scoping
;; define static functions (use only in context MAIN)
;;
;; Example:
;;
;; (def-static (foo x) (+ x x))
;;
;; foo:foo   ? (lambda (foo:x) (+ foo:x foo:x))
;;
;; (foo 10)  ? 20
;;
(define-macro (def-static)
    (let (temp (append (lambda) (list (1 (args 0)) (args 1))))
        (def-new 'temp (sym (args 0 0) (args 0 0)))))

It is defined as a hygienic macro. Easier to understand perhaps this older version from the 8.7.1 manual, which does the same:


(define (def-static s contents)
       (def-new 'contents (sym s s)))

(def-static 'acc (fn (x) (if sum (inc 'sum x) (set 'sum x))))

    (acc 5) => 5
    (acc 5) => 10
    (acc 2) => 12

    acc:sum => 12
    acc:x   => nil


The current definition from the link just mentioned lets you use 'def-static' like 'define'.



So the link and the older previous example show how to define a function (actually the default function) for another context.



Doing a function define for the same current context is much more streight forward:


(define-macro (make-func func body)
        (set func body))

(make-func foo (fn (x) (+ x x)))

(foo 10) => 20


You just do an assignment of a lambda/fn expression to a symbol, which is the same as a 'define'.



If you are more interested in code to write functions in newLISP you should definitely also look into:



http://newlisp.org/downloads/newlisp_manual.html#expand">http://newlisp.org/downloads/newlisp_manual.html#expand

and

http://newlisp.org/downloads/newlisp_manual.html#letex">http://newlisp.org/downloads/newlisp_manual.html#letex



In newLISP variable expansion is something you do explicitly with 'expand' or 'letex'. You can use both to fill in function templates, which I think is what you want to do.



'define-macro' alone is just a 'define' without argument evaluation.



Lutz

frontera000

#4
Thanks.



I think def-new is definitely something I can use!