Macro version of define that prints args when func is called

Started by cormullion, October 21, 2007, 07:38:56 AM

Previous topic - Next topic

cormullion

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?

Fanda

#1
'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

Lutz

#2
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

cormullion

#3
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!

cormullion

#4
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

Fanda

#5
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.

Fanda

#6
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

cormullion

#7
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!