macro to create default functions

Started by cormullion, July 14, 2007, 09:56:36 AM

Previous topic - Next topic

cormullion

Getting stuck again - please help!


(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:


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

Lutz

#1
you have to put f1:f1 in both places, f1 and f1:f1 are diferent animals



(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.

cormullion

#2
OK, thanks. I see that now.



In this:


(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?

Lutz

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


(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

Lutz

#4
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_manual.html#lexical_scoping">http://newlisp.org/downloads/newlisp_ma ... al_scoping">http://newlisp.org/downloads/newlisp_manual.html#lexical_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

cormullion

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


(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

cormullion

#6
This is as close as I've got so far:


(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...