Page 1 of 1

macro to create default functions

Posted: Sat Jul 14, 2007 4:56 pm
by cormullion
Getting stuck again - please help!

Code: Select all

(define-macro (create-function)
	(letex 
 	 ((f1 (sym (first (args))))) 
	(define (f1) 
		(println  { args are } (args))) 
	)
)
(create-function foo)
(foo 1)
 args are (1)
(foo)
 args are ()
works as expected. But if I replace (define (f1) with (define (f1:f1)) it doesn't:

Code: Select all

(define-macro (create-function)
	(letex 
 	 ((f1 (sym (first (args))))) 
	(define (f1:f1) 
		(println  { args are } (args))) 
	)
)

(create-function foo)
context expected in function define : f1
But I thought you didn't need to quote the symbol when defining a default function...

thanks for any help!

Posted: Sat Jul 14, 2007 6:45 pm
by Lutz
you have to put f1:f1 in both places, f1 and f1:f1 are diferent animals

Code: Select all

(define-macro (create-function) 
   (letex 
     ((f1:f1 (sym (first (args))))) 
   (define (f1:f1) 
      (println  { args are } (args))) 
   ) 
) 
But in a function call situation (f1 ...) when newLISP sees that f1 is a context symbol (they are global too) it will use f1:f1 instead. f1 than defaults to f1:f1. Thats why its called a default symbol/function.

But in (letex (f1 ...)..) it is not a function call, just an assignment.

Lutz

ps: but in your case you are just using it as a temporary variable, and in this siutation it is not really necessary, you could just use any normal symbol.

Posted: Sat Jul 14, 2007 10:24 pm
by cormullion
OK, thanks. I see that now.

In this:

Code: Select all

(define-macro (create-functions group-name) 
(letex 
 ((f1 (sym (append (name group-name) "1"))) 
  (f2 (sym (append (name group-name) "2")))) 
 (define (f1 arg) (+ arg 1)) 
 (define (f2 arg) (+ arg 2)))) 
 
(create-functions foo) 
There's presumably no way to write the 'f1' and 'f2' function definitions to use (args) rather than the arg, since (args) is still part of the macro definition, rather than the f1/f2 function definition?

Posted: Sat Jul 14, 2007 11:04 pm
by Lutz
Not sure what your mean. Isn't that exactly what you did before? And it worked! The (args) in the (define (f1:f1) ... (args) ...) doesn't get evaluated until the function created bye (create-functions ...) is used. Only the (args) in the letex assignment gets evaluated:

Code: Select all

(define-macro (create-function) 
   (letex 
     ((f1:f1 (sym (first (args))))) ;<- evaluated during create-function
   (define (f1:f1) 
      (println  { args are } (args))) ;<- not evaluated during create-function
   ) 
) 
Lutz

Posted: Sun Jul 15, 2007 12:15 am
by Lutz
I didn't pay attention earlier to the title of this thread: "macro to create default functions". None of the example really creates default functions. They use default symbols during the creation process, but all just return a lambda expression living in the same name space as the caller.

I believe what you want to do is described here:

http://newlisp.org/downloads/newlisp_ma ... al_scoping

The example creates a function 'acc:acc' where all of its symbols live in a namespace 'acc', including a symbol 'acc:sum' which keeps state when accumulating numbers over various invocations of calls to (acc ...).

Lutz

Posted: Sun Jul 15, 2007 8:49 am
by cormullion
What I'm trying to investigate (to see if it's possible and to give me a task to try and solve using some of these more advanced topics ;-)) is to create a macro that provides a modified/enhanced version of an existing function:

Code: Select all

(define-macro (enhance-function)
...)

(enhance-function add)
;-> my-add

(my-add 1 2 3)
;-> 6

(my-add 2 2)
;-> 4

(my-add:total)
;-> 10

(enhance-function sin)  ; possibly different macro
;-> my-sin

(my-sin 1)
;-> 0.8414709838

(my-sin (div pi 2))
;-> 1

(my-sin:acc)
;-> 1.841470938

Posted: Mon Jul 16, 2007 11:49 am
by cormullion
This is as close as I've got so far:

Code: Select all

(define-macro (enhance-function)
    (let 
    	((fname  (args 0 0))
    	 (fname1 (string "my>" (args 0 0)))
    	 (fbody (append 
    	 		(lambda) 
    	 		 (list
    	 		   (1 (args 0)) 
    	 		   (args 1)))))
    (def-new 'fbody (sym fname1 (context (sym fname1))))))

(enhance-function (add)
	(if invocations
		(inc 'invocations)
		(set 'invocations 0)))
The big problem with this is that the new function that gets created (my>add:my>add) doesn't do the adding as well as keep count of its invocations, so it's not exactly enhanced. :-( But I can't work out where to put the add (presumably (apply add (args)) in the lambda list...