From: Pascal Costanza on 3 Nov 2009 09:25 Juanjo wrote: > On Nov 3, 9:31 am, Pascal Costanza <p...(a)p-cos.net> wrote: >> Nicolas Edel wrote: >>> On Nov 2, 7:24 pm, "Captain Obvious" <udode...(a)users.sourceforge.net> >>> wrote: >>>> 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. >>> Ok, so I use macro to generate code and then invoke the compiler at >>> runtime. >>> What is best practice for this: eval or compile ? Do they have similar >>> meaning in this context ? >>> (defun foo (predicate value) >>> (eval `(function (lambda (x) >>> (maybe ,predicate (eql x ,value)))))) >>> or >>> (defun foo (predicate value) >>> (compile nil `(lambda (x) >>> (maybe ,predicate (eql x ,value))))) >> The semantics are the same. Which one is better depends on context. If >> you use these functions only one or two times, or so, it's not >> worthwhile to compile them, because compilation creates a considerable >> overhead by itself. If you use them more often, then compilation is >> worthwhile (although I recently heard that in, say,ECLor GCL, >> compilation is almost always prohibitive). > > It is not "almost always prohibitive". The cost is basically executing > a C compiler. And that is worthwhile if you need the function often > and if the function it is low level enough that it profits from > compilation. > > What is prohibitive is to compile using C a function that you are > going to use only once, and do it for every use. > > The alternative then is to use bytcompiled functions, which do save > some time, but are not as efficient as natively compiled ones. You can > always do this, without much hassle. One cheap way is to coerce a > lambda form to a function type. > >> (coerce '(lambda (x) (1+ x)) 'function) > > #<bytecompiled-function 0000000102a301e0> >> (funcall * 2) > > 3 OK, thanks a lot for the clarification, and also for the hint about byte compilation, which is certainly useful! Pascal -- My website: http://p-cos.net Common Lisp Document Repository: http://cdr.eurolisp.org Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pillsy on 3 Nov 2009 10:59 On Nov 3, 6:02 am, Pascal Costanza <p...(a)p-cos.net> wrote: [...] > Here is a sketch [untested]: > (defclass smart-function (funcallable-standard-object) () > (:metaclass funcallable-standard-class)) > (defparameter *threshold* 10) > (defun make-smart-function (body) > (let ((fun (make-instance 'smart-function))) > (set-funcallable-instance-function > fun > (let ((counter 0) (funfun (eval body))) > (lambda (&rest args) > (declare (dynamic-extent args) > (when (> (incf counter) *threshold*) > (unless (compiled-function-p funfun) > (setq funfun (compile nil body))) > (set-funcallable-instance-function fun funfun)) > (apply funfun args)))) > fun)) [...] > Yes, this requires the CLOS MOP. ;) What's the advantage of using the MOP over a straight-up closure in this instance? Thanks, Pillsy
From: Pascal Costanza on 3 Nov 2009 11:14 Pillsy wrote: > On Nov 3, 6:02 am, Pascal Costanza <p...(a)p-cos.net> wrote: > [...] >> Here is a sketch [untested]: > >> (defclass smart-function (funcallable-standard-object) () >> (:metaclass funcallable-standard-class)) > >> (defparameter *threshold* 10) > >> (defun make-smart-function (body) >> (let ((fun (make-instance 'smart-function))) >> (set-funcallable-instance-function >> fun >> (let ((counter 0) (funfun (eval body))) >> (lambda (&rest args) >> (declare (dynamic-extent args) >> (when (> (incf counter) *threshold*) >> (unless (compiled-function-p funfun) >> (setq funfun (compile nil body))) >> (set-funcallable-instance-function fun funfun)) >> (apply funfun args)))) >> fun)) > [...] >> Yes, this requires the CLOS MOP. ;) > > What's the advantage of using the MOP over a straight-up closure in > this instance? Good question. Maybe there is none. Originally I thought I had to store the body in a slot of the smart-function instance, but that turned out not to be necessary. So indeed, maybe you can replace this by a plain closure. Pascal -- My website: http://p-cos.net Common Lisp Document Repository: http://cdr.eurolisp.org Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza on 3 Nov 2009 11:58 Pascal Costanza wrote: > Pillsy wrote: >> On Nov 3, 6:02 am, Pascal Costanza <p...(a)p-cos.net> wrote: >> [...] >>> Here is a sketch [untested]: >> >>> (defclass smart-function (funcallable-standard-object) () >>> (:metaclass funcallable-standard-class)) >> >>> (defparameter *threshold* 10) >> >>> (defun make-smart-function (body) >>> (let ((fun (make-instance 'smart-function))) >>> (set-funcallable-instance-function >>> fun >>> (let ((counter 0) (funfun (eval body))) >>> (lambda (&rest args) >>> (declare (dynamic-extent args) >>> (when (> (incf counter) *threshold*) >>> (unless (compiled-function-p funfun) >>> (setq funfun (compile nil body))) >>> (set-funcallable-instance-function fun funfun)) >>> (apply funfun args)))) >>> fun)) >> [...] >>> Yes, this requires the CLOS MOP. ;) >> >> What's the advantage of using the MOP over a straight-up closure in >> this instance? > > Good question. Maybe there is none. Originally I thought I had to store > the body in a slot of the smart-function instance, but that turned out > not to be necessary. So indeed, maybe you can replace this by a plain > closure. Yes, I guess this should work: (defparameter *threshold* 10) (defun make-smart-function (body) (let ((counter 0) fun funfun) (setq funfun (eval body) fun (lambda (&rest args) (declare (dynamic-extent args)) (when (> (incf counter) *threshold*) (unless (compiled-function-p funfun) (setq funfun (compile nil body)) (setq fun funfun))) (apply funfun args))) (lambda (&rest args) (declare (dynamic-extent args)) (apply fun args)))) (defmacro smart-lambda ((&rest args) &body body) `(make-smart-function (lambda ,args ,@body))) Pascal -- My website: http://p-cos.net Common Lisp Document Repository: http://cdr.eurolisp.org Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Captain Obvious on 3 Nov 2009 17:21 P> What's the advantage of using the MOP over a straight-up closure in P> this instance? Might have better performance. If you use &rest and then apply I guess most compilers will make a list, that is, you have more consing. (lambda (&rest args) (let ((fn ....)) (apply fn args))) But if you're doing it via macro, you can use certain number of parameters directly: (lambda (a b c) (let ((fn ....)) (funcall fn a b c))) Then there is no consing. There might be some overhead from using closure's variable and funcall, but I guess funcallable-object's funcall is not totally overheadless either. So probably funcallable-object offers only a minuscule advantage in this case.
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: Article about lisp and array languages Next: lisp, java and evolution of types |