newLISP Fan Club

Forum => Anything else we might add? => Topic started by: cormullion on October 21, 2007, 07:38:56 AM

Title: Macro version of define that prints args when func is called
Post by: cormullion on October 21, 2007, 07:38:56 AM
Hi. I'm trying to make a new version of define, such that when the function it defines is called, it prints its arguments (eg to a log file). I think it should be possible.



Here's how far I've got:


(define-macro (my-define)
  (set (args 0 0)
    (append (lambda)
      (list
        (rest (first (args))))
        (println {call } (first (args)))
        (rest (args)))))

(my-define (p2 a1 a2)
    (println a1)
    (println a2)
    )

(p2 "bill" "bob")


But this prints the arguments when the function is first defined, not when it's subsequently called. Is there a way of delaying that 'print' till later on?
Title:
Post by: Fanda on October 21, 2007, 11:35:19 AM
'define' creates a lambda function/list. You need to include your 'print' functions into the newly created function:



Try if this works:
(define-macro (my-define @farg)
(set (@farg 0)
(letex (@arg (rest @farg)
@arg-p (cons 'list (map (fn (@x) (if (list? @x) (first @x) @x)) (rest @farg)))
@body (args))
(append (lambda @arg
(println "params: " @arg-p)
(println "args: " (args)))
'@body))))

(constant (global 'define) my-define)


Example:
> (define (f x) (+ x x))
(lambda (x) (println "params: " (list x)) (println "args: " (args))
 (+ x x))
> f
(lambda (x) (println "params: " (list x)) (println "args: " (args))
 (+ x x))
> (f 2)
params: (2)
args: ()
4
> (f 2 3 4)
params: (2)
args: (3 4)
4

> (define (f (x 10)) (+ x x))
(lambda ((x 10)) (println "params: " (list x)) (println "args: "
  (args))
 (+ x x))
> f
(lambda ((x 10)) (println "params: " (list x)) (println "args: "
  (args))
 (+ x x))
> (f)
params: (10)
args: ()
20
> (f 3)
params: (3)
args: ()
6
> (f 3 4 5)
params: (3)
args: (4 5)
6


Enjoy, Fanda
Title:
Post by: Lutz on October 21, 2007, 12:46:03 PM
Quote from: "Fanda"(constant (global 'define) my-define)


nice idea, this way a Cormullion style trace module can be written and can be used with any exisiting code by simply including a (load "trace.lsp") at the beginning of a program.



Lutz
Title:
Post by: cormullion on October 21, 2007, 01:33:29 PM
Wicked cool, Fanda! You've done the clever bit for me...



I might change those @ signs to something else - I find them visually distracting... Underscores appear to work...



thanks!
Title:
Post by: cormullion on October 21, 2007, 03:13:34 PM
Could this be easily modified so that the function name is also printed?



Edit: oh yes, i see:


(define-macro (my-define @farg)
   (set @fn (@farg 0)) ; that's the function name
   (set (@farg 0)
      (letex....



Edit 2: Ah,  that doesn't work properly because it's global... Hmm
Title:
Post by: Fanda on October 22, 2007, 02:40:50 AM
Again, you need to put the function name inside the 'println' inside the 'lambda fn'.


(define-macro (my-define @farg)
  (set (@farg 0)
    (letex (@fn (@farg 0)
            @arg (rest @farg)
            @arg-p (cons 'list (map (fn (@x) (if (list? @x) (first @x) @x)) (rest @farg)))
            @body (args))
      (append
 (lambda @arg (println "[" '@fn "] params: " @arg-p " args: " (args)))
        '@body))))

(constant (global 'define) my-define)


Example:
> (define (f x) (+ x x))
(lambda (x) (println "[" 'f "] params: " (list x) " args: " (args))
 (+ x x))
> f
(lambda (x) (println "[" 'f "] params: " (list x) " args: " (args))
 (+ x x))
> (f 2)
[f] params: (2) args: ()
4
 
> (define (f (x 10) y) (+ x y))
(lambda ((x 10) y) (println "[" 'f "] params: " (list x y) " args: "
  (args))
 (+ x y))
> (f 2 3)
[f] params: (2 3) args: ()
5
> (f 2 3 4 5)
[f] params: (2 3) args: (4 5)
5


PS: I am using @ sign as an other-than-underscore sign, because some functions can be macro-like and use underscores for their variables.
Title:
Post by: Fanda on October 22, 2007, 03:04:52 AM
One more version returning result of a function:
(define-macro (my-define @farg)
  (set (@farg 0)
    (letex (@fn (@farg 0)
            @arg (rest @farg)
            @arg-p (cons 'list (map (fn (@x) (if (list? @x) (first @x) @x)) (rest @farg)))
            @body (cons 'begin (args)))
   (lambda @arg
         (println "[" '@fn "] params: " @arg-p " args: " (args))
         (println "[" '@fn "] result: " @body)))))

(constant (global 'define) my-define)


Example:

> (define (f (x 10) y) (+ x y))
(lambda ((x 10) y) (println "[" 'f "] params: " (list x y) " args: "
  (args))
 (println "[" 'f "] result: "
  (begin
   (+ x y))))
> (f 2 3)
[f] params: (2 3) args: ()
[f] result: 5
5
> (f 2 3 4 5)
[f] params: (2 3) args: (4 5)
[f] result: 5
5
Title:
Post by: cormullion on October 22, 2007, 03:27:00 AM
Aha - that looks like the one.



I find these constructions really difficult to conjure up, and so I'm really glad for your help. Perhap's it's something to do with the hypothetical nature of things that are going to be evaluated sometime in the future but now now...



thanks!