From: Nicolas Edel on 2 Nov 2009 11:06 Dear group I'd like to make some closures to speed up operations that are specified at run time, as it is done for regex compilation. So let's take a *very* simple exmaple: CL-USER> (defun foo (value) #'(lambda (x) (eq x value))) FOO CL-USER> foo #<CLOSURE (LAMBDA (X)) {AF278FD}> CL-USER> (funcall (foo 1) 0) NIL CL-USER> (funcall (bar 1) 1) T So that's ok. Now let's suppose we would like the invert the test depending on a predicate value: CL-USER> (defun foo (value predicate) #'(lambda (x) (if predicate (eq x value) (not (eq x value))))) FOO Or, in order to avoid a test at runtime: CL-USER> (defun foo (value predicate) (if predicate #'(lambda (x) (eq x value)) #'(lambda (x) (not (eq x value))))) FOO It looks like a macro would allow to avoid code duplication here CL-USER> (defmacro maybe (predicate statement) (if predicate `(,@statement) `(not ,statement))) MAYBE CL-USER> (macroexpand-1 '(maybe T (eq x value))) (EQ X VALUE) T CL-USER> (macroexpand-1 '(maybe NIL (eq x value))) (NOT (EQ X VALUE)) T Now redefine foo: CL-USER> (defun foo (value predicate) #'(lambda (x) (maybe predicate (eq x value)))) ;[...] ; caught STYLE-WARNING: ; The variable PREDICATE is defined but never used. ;[...] STYLE-WARNING: redefining FOO in DEFUN FOO Calling the function shows that the variable PREDICATE is indeed not taken into account. Now (finally) the questions: 1. Why ? 2. How to use macros for generating the lambdas ? Many thanks, :Nicolas
From: xach on 2 Nov 2009 11:38 Nicolas Edel <nicolas.edel(a)gmail.com> writes: > So that's ok. Now let's suppose we would like the invert the test > depending on a predicate value: > > CL-USER> (defun foo (value predicate) > #'(lambda (x) > (if predicate > (eq x value) > (not (eq x value))))) > FOO > > Or, in order to avoid a test at runtime: > > CL-USER> (defun foo (value predicate) > (if predicate > #'(lambda (x) (eq x value)) > #'(lambda (x) (not (eq x value))))) > FOO > > It looks like a macro would allow to avoid code duplication here There's another way to avoid code duplication: add a new higher-order function. (defun foo (value) (lambda (x) (eq x value))) (defun predicator (predicate fun) (if predicate fun (complement fun))) So your second "foo" could be: (defun foo-2 (value predicate) (predicator predicate (foo value))) Zach
From: milanj on 2 Nov 2009 11:42 On Nov 2, 5:06 pm, Nicolas Edel <nicolas.e...(a)gmail.com> wrote: > Dear group > > I'd like to make some closures to speed up operations that are > specified at run time, as it is done for regex compilation. So let's > take a *very* simple exmaple: > > CL-USER> (defun foo (value) > #'(lambda (x) > (eq x value))) > FOO > CL-USER> foo > #<CLOSURE (LAMBDA (X)) {AF278FD}> > CL-USER> (funcall (foo 1) 0) > NIL > CL-USER> (funcall (bar 1) 1) > T > > So that's ok. Now let's suppose we would like the invert the test > depending on a predicate value: > > CL-USER> (defun foo (value predicate) > #'(lambda (x) > (if predicate > (eq x value) > (not (eq x value))))) > FOO > > Or, in order to avoid a test at runtime: > > CL-USER> (defun foo (value predicate) > (if predicate > #'(lambda (x) (eq x value)) > #'(lambda (x) (not (eq x value))))) > FOO > > It looks like a macro would allow to avoid code duplication here > > CL-USER> (defmacro maybe (predicate statement) > (if predicate > `(,@statement) > `(not ,statement))) > MAYBE > CL-USER> (macroexpand-1 '(maybe T (eq x value))) > (EQ X VALUE) > T > CL-USER> (macroexpand-1 '(maybe NIL (eq x value))) > (NOT (EQ X VALUE)) > T > > Now redefine foo: > CL-USER> (defun foo (value predicate) > #'(lambda (x) > (maybe predicate (eq x value)))) > ;[...] > ; caught STYLE-WARNING: > ; The variable PREDICATE is defined but never used. > ;[...] > STYLE-WARNING: redefining FOO in DEFUN > FOO > > Calling the function shows that the variable PREDICATE is indeed > not taken into account. > Now (finally) the questions: > > 1. Why ? > 2. How to use macros for generating the lambdas ? > > Many thanks, > > :Nicolas The answer is in topic name, you cant expand macro at runtime and your macro expansion depends on runtime value (predicate)
From: joswig on 2 Nov 2009 11:46 On 2 Nov., 17:06, Nicolas Edel <nicolas.e...(a)gmail.com> wrote: > Dear group > > I'd like to make some closures to speed up operations that are > specified at run time, as it is done for regex compilation. So let's > take a *very* simple exmaple: > > CL-USER> (defun foo (value) > #'(lambda (x) > (eq x value))) > FOO > CL-USER> foo > #<CLOSURE (LAMBDA (X)) {AF278FD}> > CL-USER> (funcall (foo 1) 0) > NIL > CL-USER> (funcall (bar 1) 1) Numbers are compared with EQL, not EQ. > T > > So that's ok. Now let's suppose we would like the invert the test > depending on a predicate value: > > CL-USER> (defun foo (value predicate) > #'(lambda (x) > (if predicate > (eq x value) > (not (eq x value))))) > FOO > > Or, in order to avoid a test at runtime: > > CL-USER> (defun foo (value predicate) > (if predicate > #'(lambda (x) (eq x value)) > #'(lambda (x) (not (eq x value))))) > FOO > > It looks like a macro would allow to avoid code duplication here > > CL-USER> (defmacro maybe (predicate statement) > (if predicate > `(,@statement) > `(not ,statement))) (if predicate ...) - you are checking a macro expansion time for the value of predicate. Not a good idea. You think you now a macro expansion time the value of predicate, but you don't. All you know is the code, but not its value. Try: `(if ,predicate ... ) > MAYBE > CL-USER> (macroexpand-1 '(maybe T (eq x value))) > (EQ X VALUE) > T > CL-USER> (macroexpand-1 '(maybe NIL (eq x value))) > (NOT (EQ X VALUE)) > T > > Now redefine foo: > CL-USER> (defun foo (value predicate) > #'(lambda (x) > (maybe predicate (eq x value)))) The macro maybe is used. It has two parameters: predicate and statement. The arguments are predicate and (eq x value) predicate = predicate statement = (eq x value) Remember above (if predicate ... ) ? predicate evaluates to the symbol predicate, which is always true. It is similar to (if 'predicate ...) .... > ;[...] > ; caught STYLE-WARNING: > ; The variable PREDICATE is defined but never used. > ;[...] > STYLE-WARNING: redefining FOO in DEFUN > FOO > > Calling the function shows that the variable PREDICATE is indeed > not taken into account. > Now (finally) the questions: > > 1. Why ? > 2. How to use macros for generating the lambdas ? > > Many thanks, > > :Nicolas
From: Captain Obvious on 2 Nov 2009 13:24 NE> 1. Why ? Because macros work at macroexpansion time, NOT runtime. NE> 2. How to use macros for generating the lambdas ? You can use macro to generate a code which generates lambda, for example.
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: Article about lisp and array languages Next: lisp, java and evolution of types |