From: Nicolas Edel on
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
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
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
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
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.